Zamanlanmış görev ve kuyruk
"Her pazartesi sabah hatırlat", "süresi dolan kayıtları gece kapat", "bu raporu arka planda hazırla" gibi işler için. Uygulama işi beyan eder ve işleyicisini yazar; işi Devoplus One tetikler. Uygulamada kendi zamanlayıcınızı ya da arka plan döngünüzü yazmayın; uygulama yalnız bir istek geldiğinde çalışır.
| İhtiyaç | Kullanın |
|---|---|
| Belli zamanlarda tekrarlanan iş | Zamanlama: manifest jobs.schedules[] + defineJobs({ schedules }) |
| Kullanıcının başlattığı, arka planda bitecek iş | Kuyruk: manifest jobs.queues[] + enqueue(...) + defineJobs({ queues }) |
| İşi bir süre sonra yapmak (en çok 24 saat) | enqueue(ad, gövde, { delaySeconds }) |
1. Manifest
"jobs": {
"schedules": [{ "name": "weekly-reminder", "cron": "0 9 * * 1", "timeZone": "Europe/Istanbul", "description": "Pazartesi 09:00 hatırlatma" }],
"queues": [{ "name": "send-report", "maxRetries": 3, "description": "Raporu hazırlayıp kaydeder" }]
}- Ad: küçük harfle başlar; küçük harf, rakam ve tire; 2-40 karakter. En çok 10 zamanlama ve 10 kuyruk.
cron: 5 alan; dakika saat ayın-günü ay haftanın-günü (0 9 * * 1= pazartesi 09:00,*/15 8-18 * * mon-fri= hafta içi mesai saatlerinde 15 dakikada bir). En sık aralık dakikada birdir.?,L,W,#desteklenmez.timeZone: verilmezseEurope/Istanbul. Kullanıcının saatiyle düşünün; platform çevirir.maxRetries(yalnız kuyruk): 0-10, varsayılan 3.services(isteğe bağlı): işin Devoplus'ta kullanacağı servisler (bkz. §4). Örnek:"services": ["ai.use", "mail.execute"].- Kurallar ve hata yolları: manifest içinde
jobsbölümü.
2. İşleyiciler
import { OneError, defineJobs, enqueue, handleJobRequest, readContext, requireUser, type OneApp } from '@devoplus/one-sdk'
const jobs = defineJobs<Env>({
schedules: {
'weekly-reminder': async (job, env) => {
// Kullanıcısız iş: ctx.user null. Devoplus servisi gerekiyorsa jobs.services + kurulum onayı (§4).
await env.DB.prepare('INSERT OR IGNORE INTO reminders (job_id, created_at) VALUES (?, ?)').bind(job.id, job.scheduledTime).run()
},
},
queues: {
'send-report': async (job, env, ctx) => {
const { reportId } = job.body as { reportId: number }
if (!reportId) throw new OneError(422, 'APP-E-001', 'Rapor kimliği yok.') // 4xx: kalıcı hata, yeniden denenmez
// ctx.user = iletiyi bırakan kullanıcı
await env.DB.prepare('INSERT OR IGNORE INTO reports (job_id, report_id, owner) VALUES (?, ?, ?)').bind(job.id, reportId, ctx.user?.sub ?? null).run()
},
},
})
export default {
async fetch(request, env, execution) {
const job = handleJobRequest(request, env, execution, jobs) // platformun iş çağrısı; değilse null
if (job) return job
const ctx = readContext(request.headers)
if (new URL(request.url).pathname === '/api/reports' && request.method === 'POST') {
requireUser(ctx)
const { id } = await enqueue('send-report', { reportId: 7 }) // 202 ve { id } döner
return Response.json({ queued: true, id }, { status: 202 })
}
// ...
},
} satisfies OneApp<Env>3. Sonuç ve yeniden deneme
| İşleyici | Platform |
|---|---|
| Döner | İş tamam (200) |
4xx OneError fırlatır (ör. 422) | Kalıcı hata; yeniden denenmez (ör. biçimsiz ileti, artık geçersiz kayıt) |
| Başka hata fırlatır, zaman aşımı, sınır aşımı | 500; geri çekilmeyle yeniden denenir (30 sn'den başlayıp ikiye katlanır, en çok 1 saat): kuyrukta maxRetries, zamanlamada 3 kez |
⛔ Aynı iş birden çok kez gelebilir (yeniden deneme; nadiren aynı dakikanın tekrarı). job.id her denemede aynıdır: kalıcı bir şey yazıyorsanız tabloda bu kimliği birincil anahtar yapın ve INSERT OR IGNORE kullanın. E-posta gibi geri alınamaz bir işi iş kimliğiyle işaretlemeden göndermeyin.
4. Kimlik
- Kuyruk işi iletiyi bırakan kullanıcının kimliğini (
ctx.user.sub) bilgi olarak taşır. Uygulama izinleri ve yönetici bilgisi işe taşınmaz (hasPermissionher zamanfalse): izin kararını iletiyi bırakırken verin. - Zamanlanmış iş kullanıcısızdır (
ctx.usernull). - Devoplus servisleri işte uygulamanın kimliğiyle çağrılır (
ctx.mode === 'job'), kişi adına değil. Kullanılabilen servisler yalnız şunlardır ve her biri manifestjobs.servicesvescopesiçinde beyan edilir:mail.execute(e-posta),sms.execute(SMS),push.execute(mobil bildirim),dexa.read(DEXA okuma) veai.use(yapay zeka). ⛔ Beyan yetmez: arka plan işi servisleri kurulumda portal yöneticisinin onayıyla açılır. Onaylanmamış servise çağrı 403 alır; bu durumda kurulum için portal yöneticisinden servis onayı isteyin. - ⛔ DEXA'ya yazma (ERP işlemi) arka plan işinde açılmaz. Organizasyon şeması ve diğer servisler de işte yoktur.
- DEXA okuma sorgusu kişiye bağlı bir kod istiyorsa (
UserCode,CompanyCode,CostCenterCode): işte oturum olmadığı için kodu uygulama gönderir. Bunun için kurulumda portal yöneticisinin "kodları uygulama belirler" onayı gerekir; onay yoksa gönderilen kod reddedilir. Kod gönderilmezse sorgu reddedilir (oturumdan çözülecek kişi yok). Kişi ve şirket kodu kurulumun portalına karşı doğrulanır; boş değer ERP'ye gitmez.LangCodegönderilmez. - İşte "kendime gönder" yoktur: e-posta/SMS/bildirim alıcısını açıkça verin. Denetim kaydında aktör uygulamadır.
- Servis istemcisini belirteçsiz kurun:
new BackendClient({ baseUrl: env.API_BASE, authorization: null }). Uygulamanın yazdığıAuthorizationbaşlığı işte Devoplus'a iletilmez. - Kimliği iletinin gövdesine yazmayın; platform kimliği istekten kendisi alır. Başka kullanıcı adına ileti bırakılamaz.
- Vekalet ya da Yerine Görüntüle oturumunda, uygulama bu oturumlarda yazmaya açık değilse (
actingSessions: "read") kuyruğa ileti bırakılamaz (403).
5. Sınırlar
- Gövde JSON'a çevrilebilir olmalı ve en çok 64 KiB'dir; gecikme 0-86.400 saniye (24 saat).
- Beyan edilmemiş kuyruk adına ileti bırakılamaz (404). Manifest'ten çıkarılan iş yeni sürüm yayımlanınca durur.
/__one/ile başlayan yollar platforma ayrılmıştır: bu yolda kendi ucunuzu yazmayın; internetten bu yola gelen istek uygulamaya ulaşmaz.- Kaçırılan bir zamanlama sonradan telafi edilmez. Yaz saati geçişinde atlanan yerel saatteki zamanlama o gün çalışmaz.
- Yerelde (
one dev) zamanlama tetiklenmez veenqueueçalışmaz (503). Uygulamanın yerel adresi (8788)/__one/yolunu platformdaki gibi reddeder; işleyiciyi denemek için yerel çalışma ortamının iç adresine (http://127.0.0.1:8789, yani--portartı iki)X-One-Auth: jobbaşlığıyla veX-One-App,X-One-Portal-Key,X-One-PortalbaşlıklarıylaPOST /__one/jobs/<schedule|queue>/<ad>gönderin, gövde{ "id": "deneme-1", "body": ... }. İşin Devoplus servis çağrıları yerelde taklit edilmez. Bu iç adres ad (Host) denetimi yapmaz ve başlıkları doğrulamaz; yalnız komut satırından deneme içindir, tarayıcıda açılmaz. - Hata kodları:
ONE-SDK-E-070(ad),-071(gövde JSON değil),-072(gövde büyük),-073(gecikme),-074(bırakılamadı),-075(iş bulunamadı),-076(çağrı gövdesi bozuk); platform tarafıONE-OUT-E-010ile-017arası.