Hacker DirectoryHacker Directory
Öğrenmeye devam et
ENHTML kaydet ↓

WEB / WEB-19.03

Scheduled jobs ve async processing

İşin zamanının gelmesini, başlangıç iznini ve kalıcı sonucu ayrı izle. Atlas public-note job’unda kabul edilmiş bir işin neden başarısız kalabildiğini incele.

CORE · RED · BLUE · ARTIFACT · PRACTICE

1. Core · Mekanizma

Hareket olmadan bütün senaryoları oku

Kabul ve sonuç

  1. Önce işin zamanı var

    slot-10 için due=10 seçilmiş. Henüz iş kabul edilmedi, worker başlamadı ve result yok. Bu zamanlar duvar saati yerine küçük bir logical clock ile gösterilir.

    Logical scheduler
    due=10 / slot-10
    Local dispatcher
    Henüz kabul yok
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  2. Scheduler zamanı gözledi

    Scheduler’ın observed değeri, işin due değerinden ayrı bir gözlemdir. İki sayı arasındaki fark, bu örneğin başlangıç gecikmesi politikasında değerlendirilir.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    Henüz kabul yok
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  3. Başlangıç izni verildi

    Gecikme seçilen başlangıç penceresinin içindedir; dispatcher job’u kabul eder. Kabul kararı worker’ın tamamlandığı veya result’un commit edildiği anlamına gelmez.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  4. Worker işe başladı

    Worker, bilinen public-note job’unu işlemeye başlar. Job verisi purpose ve note ID’yi taşır; browser request object’i bu background işe aktarılmış sayılmaz.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    Public-note job çalışıyor
    SQLite result owner
    resultRows=0 / processedRows=0
  5. Result ve marker aynı transaction’da

    Result ile processed marker aynı transaction’da hazırlanır. COMMIT öncesinde ayrı okuyucu bu pending satırları göremez; transaction’ın başlaması kalıcı sonucu göstermez.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    Public-note job çalışıyor
    SQLite result owner
    Result/marker pending / okuyucu 0 görür
  6. Kalıcı sonuç artık ayrı biliniyor

    Normal dalda COMMIT tamamlanmış, result ve marker ayrı okuyucu için görünür olmuştur. Worker’ın finished kaydı ile önceki admission kararı farklı tamamlanmaları anlatır.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    finished=13 / COMMIT tamamlandı
    SQLite result owner
    resultRows=1 / processedRows=1 committed

Geç kaldı

  1. Önce işin zamanı var

    slot-10 için due=10 seçilmiş. Henüz iş kabul edilmedi, worker başlamadı ve result yok. Bu zamanlar duvar saati yerine küçük bir logical clock ile gösterilir.

    Logical scheduler
    due=10 / slot-10
    Local dispatcher
    Henüz kabul yok
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  2. Scheduler zamanı gözledi

    Scheduler’ın observed değeri, işin due değerinden ayrı bir gözlemdir. İki sayı arasındaki fark, bu örneğin başlangıç gecikmesi politikasında değerlendirilir.

    Logical scheduler
    observed=14 / lateness=4
    Local dispatcher
    Henüz kabul yok
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  3. Başlangıç penceresi kaçırıldı

    Gecikme 4, seçilen maxStartAge=3 sınırını aşar. Dispatcher işi kabul etmez; due olmuş olmak bu koşulu kaldırmaz. Worker başlamamıştır.

    Logical scheduler
    observed=14 / lateness=4
    Local dispatcher
    skip-late / admitted=false
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  4. Atlanan işin sonucu yok

    Ayrı result okuyucusu resultRows=0 görür. Bu dalda job kabul edilmediği için sonuç yoktur; kabul sonrası worker hatasıyla aynı durum değildir.

    Logical scheduler
    observed=14 / lateness=4
    Local dispatcher
    skip-late / admitted=false
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    Ayrı okuyucu: resultRows=0

Aynı slot tekrar

  1. Önce işin zamanı var

    slot-10 için due=10 seçilmiş. Henüz iş kabul edilmedi, worker başlamadı ve result yok. Bu zamanlar duvar saati yerine küçük bir logical clock ile gösterilir.

    Logical scheduler
    due=10 / slot-10
    Local dispatcher
    Henüz kabul yok
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  2. Scheduler zamanı gözledi

    Scheduler’ın observed değeri, işin due değerinden ayrı bir gözlemdir. İki sayı arasındaki fark, bu örneğin başlangıç gecikmesi politikasında değerlendirilir.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    Henüz kabul yok
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  3. Başlangıç izni verildi

    Gecikme seçilen başlangıç penceresinin içindedir; dispatcher job’u kabul eder. Kabul kararı worker’ın tamamlandığı veya result’un commit edildiği anlamına gelmez.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  4. Worker işe başladı

    Worker, bilinen public-note job’unu işlemeye başlar. Job verisi purpose ve note ID’yi taşır; browser request object’i bu background işe aktarılmış sayılmaz.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    Public-note job çalışıyor
    SQLite result owner
    resultRows=0 / processedRows=0
  5. Result ve marker aynı transaction’da

    Result ile processed marker aynı transaction’da hazırlanır. COMMIT öncesinde ayrı okuyucu bu pending satırları göremez; transaction’ın başlaması kalıcı sonucu göstermez.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    Public-note job çalışıyor
    SQLite result owner
    Result/marker pending / okuyucu 0 görür
  6. Kalıcı sonuç artık ayrı biliniyor

    Normal dalda COMMIT tamamlanmış, result ve marker ayrı okuyucu için görünür olmuştur. Worker’ın finished kaydı ile önceki admission kararı farklı tamamlanmaları anlatır.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    finished=13 / COMMIT tamamlandı
    SQLite result owner
    resultRows=1 / processedRows=1 committed
  7. Aynı slot için ikinci event

    İkinci event aynı public-note-index/slot-10 job kimliğini taşır. İlk operation’ın COMMIT edilmiş sonucu mevcut olduğundan yeni effect kararı bu marker’a dayanır.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    Aynı slot için ikinci event kabul edildi
    Application worker
    finished=13 / COMMIT tamamlandı
    SQLite result owner
    resultRows=1 / processedRows=1 committed
  8. Mevcut sonuç korunuyor

    Worker mevcut processed marker’ı bulur ve ikinci result yazmaz. İki event’e rağmen effects=1 kalır; bu gözlem aynı job’un bu örnekteki sonucuyla sınırlıdır.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    Aynı slot için ikinci event kabul edildi
    Application worker
    finished=13 / COMMIT tamamlandı
    SQLite result owner
    Mevcut marker / effects=1 korunur

Kabul, sonra hata

  1. Önce işin zamanı var

    slot-10 için due=10 seçilmiş. Henüz iş kabul edilmedi, worker başlamadı ve result yok. Bu zamanlar duvar saati yerine küçük bir logical clock ile gösterilir.

    Logical scheduler
    due=10 / slot-10
    Local dispatcher
    Henüz kabul yok
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  2. Scheduler zamanı gözledi

    Scheduler’ın observed değeri, işin due değerinden ayrı bir gözlemdir. İki sayı arasındaki fark, bu örneğin başlangıç gecikmesi politikasında değerlendirilir.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    Henüz kabul yok
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  3. Başlangıç izni verildi

    Gecikme seçilen başlangıç penceresinin içindedir; dispatcher job’u kabul eder. Kabul kararı worker’ın tamamlandığı veya result’un commit edildiği anlamına gelmez.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    Worker henüz başlamadı
    SQLite result owner
    resultRows=0 / processedRows=0
  4. Worker işe başladı

    Worker, bilinen public-note job’unu işlemeye başlar. Job verisi purpose ve note ID’yi taşır; browser request object’i bu background işe aktarılmış sayılmaz.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    Public-note job çalışıyor
    SQLite result owner
    resultRows=0 / processedRows=0
  5. Transaction rollback edildi

    Zararsız NOT NULL örneği transaction’da hata üretir. Explicit ROLLBACK sonrasında resultRows=0 ve processedRows=0 kalır; önceki admitted=true kararı silinmez.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    Public-note job çalışıyor
    SQLite result owner
    ROLLBACK / resultRows=0 / processedRows=0
  6. Kabul edildi, ama başarısız oldu

    Worker’ın final state’i failed, kalıcı result ise yoktur. Admission geçmişte başarılı olsa da final business sonucu başarılı değildir; iki alan ayrı okunur.

    Logical scheduler
    observed=12 / lateness=2
    Local dispatcher
    admitted=true / job bekliyor
    Application worker
    state=failed / admitted=true kalır
    SQLite result owner
    resultRows=0 / processedRows=0

ROLLER · STATE · VERİ AKIŞI

Due time bir sonuç değil, başlangıç koşuludur

Bir scheduled job, belirli bir schedule slot için iş başlatma niyetidir. Zamanının gelmesi, scheduler’ın bunu fark etmesi, worker’ın başlaması ve sonucun commit edilmesi ayrı olaylardır. Atlas örneğinde due=10, observed=12 ve finished=13 kullanılır. Bunlar küçük bir logical clock’un değerleridir. İşin zamanı 10’da gelmiş, 12’de gözlenmiş ve normal dalda sonuç 13’te oluşmuştur. Yalnız due alanından sonuç var diyemezsin; yalnız started alanından da işin bittiğini çıkaramazsın.

Timer ile durable scheduler aynı yaşam süresine sahip değildir. Node setTimeout, callback’i gecikme sonrasında çalıştırılmak üzere planlar; tam çağrı zamanını veya sırasını garanti etmez. Process kapanırsa içindeki timer da kalıcı bir job servisi gibi işi saklamaz. unref kullanımı, callback çağrılmadan process’in çıkmasına izin verebilir. Kubernetes CronJob ise controller üzerinden Job oluşturur. Job oluşturma yaklaşık zamanlamaya dayanır; bazı koşullarda aynı slot için iki Job veya hiç Job oluşabilir. Bu iki ürünün garantileri birbirine taşınmaz.

Başlangıç politikasını açıkça yazmak gerekir: hangi timezone, kaçırılmış slot için ne yapılacağı ve üst üste gelen işlere izin verilip verilmeyeceği. Bu dersin örneğinde slot-10 için maxStartAge=3 seçilir. observed=12 olduğunda gecikme 2’dir ve iş kabul edilir; observed=14 olduğunda gecikme 4’tür ve skip-late sonucu çıkar. Bu bir öğretim politikasıdır, production default değildir. Aynı slot tekrar geldiğinde job kimliği korunur; ikinci effect’i önlemek de scheduler’ın zamanından ayrı bir business kararıdır.

Async acceptance request dışındaki işi teslim etmez

Async processing, caller’ın işi devredip final sonucu beklemeden kabul yanıtı almasına izin verir. Örneğin AWS Lambda asynchronous invocation, event’i queue’ya koyabilir ve function’ın sonucu henüz yokken başarılı kabul yanıtı dönebilir. Caller burada devretme sonucunu öğrenmiştir; function’ın business sonucunu öğrenmemiştir. Atlas’ın kayıtlarında da admission, pending, running ve succeeded/failed durumları ayrı tutulur. Kabul edilmiş bir iş daha sonra başarısız olabilir. HTTP 202 seçildiğinde de kabul, final sonuç anlamına gelmez.

Request dışında çalışan iş, ne yapacağını kendi job verisinden ve açık erişim sözleşmesinden öğrenmelidir. Atlas worker’ı public note ID ile schedule-slot job ID’sini kullanır; browser request object’ini veya örtük bir kullanıcı kimliğini yanında taşımaz. Result ve processed marker aynı SQLite transaction’ında kaydedilir. Zararsız constraint failure örneğinde explicit rollback ikisini de kaldırır; geçmişteki admitted=true kaydı ise değişmez. Retry, dependency hatası ve result notification için de hangi job’un hangi durumundan devam edildiği ayrı belirlenir.

2. Red · Güven ve etki

Hareket olmadan bütün senaryoları oku

Geç başlangıç

  1. Önce başlangıç kuralını oku

    slot-10 için due=10 ve maxStartAge=3 seçilmiş. Bunlar bu öğretim örneğinin politikasıdır; Node timer veya cloud scheduler için ölçülmüş bir deadline değildir.

    Admission kararı
    due=10 / maxStartAge=3
    Business result
    Result henüz incelenmedi
    Caller beklentisi
    Logical clock politikası
  2. İş 14’te gözlendi

    Observed=14 ile due=10 arasındaki fark 4. Job’un zamanı gelmiş olsa da bu fark, seçilmiş başlangıç penceresinin dışındadır.

    Admission kararı
    observed=14 / lateness=4
    Business result
    Result henüz incelenmedi
    Caller beklentisi
    Zamanı gelmesi kabul edildiğini göstermez
  3. Admission reddedildi

    Bu dalda admitted=false ve outcome=skip-late. İşin yürütülmesi için gerekli kabul yok; “zamanı geldi” kaydı bunu değiştirmiyor.

    Admission kararı
    admitted=false / skip-late
    Business result
    Result henüz incelenmedi
    Caller beklentisi
    İşe başlama izni verilmedi
  4. Result owner’ı ayrıca kontrol et

    Late dalında resultRows=0. Bu kayıt, atlanan iş için kalıcı sonuç bulunmadığını gösterir; yalnız scheduler kararından çıkarılmış bir success yorumu değildir.

    Admission kararı
    admitted=false / skip-late
    Business result
    resultRows=0
    Caller beklentisi
    Bu dalda kalıcı sonuç yok
  5. Tam sınırdaki örnek farklı

    Observed=13 olduğunda gecikme 3’tür ve seçilen policy kabul eder. Observed=14 reddedilir. Sınırdaki bu karşılaştırma bütün scheduler’ların aynı policy’yi kullandığını söylemez.

    Admission kararı
    13’te kabul / 14’te ret
    Business result
    late resultRows=0
    Caller beklentisi
    Yalnız seçilmiş policy sınırı
  6. Caller yalnız bu dalın sonucunu söyler

    Bu job seçilen pencereyi kaçırmıştır. Kabul edilmeyen işi başarılı sonuç gibi göstermek yerine, skip-late durumunu ve eksik sonucu ayrı ifade edersin.

    Admission kararı
    admitted=false
    Business result
    resultRows=0
    Caller beklentisi
    Atlandı; başarılı sonuç yok

Kabul, sonra hata

  1. Başlangıç kabul edildi

    Failure dalında admitted=true. Bu alan, işe başlanmasına izin verildiğini anlatır; işin database’de kalıcı sonuç bıraktığını henüz söylemez.

    Admission kararı
    admitted=true
    Business result
    Result henüz incelenmedi
    Caller beklentisi
    Outcome pending
  2. Worker başladı

    Started=12, worker’ın bu örnekte işe başladığı logical clock değeridir. Started kaydını finished veya committed result yerine kullanamazsın.

    Admission kararı
    admitted=true / started=12
    Business result
    Result henüz incelenmedi
    Caller beklentisi
    Started != completed
  3. Transaction başarısız oldu

    Zararsız NOT NULL fixture’ı hata üretmiş ve explicit rollback uygulanmış. State=failed; örnek gerçek cloud worker’ında bir hata üretildiğini iddia etmiyor.

    Admission kararı
    admitted=true / started=12
    Business result
    state=failed / rollback
    Caller beklentisi
    Admission ayrı kalır
  4. Kalıcı marker ve sonuç yok

    ResultRows=0 ve processedRows=0 birlikte okunur. Başlama izni alınmış olsa da transaction bu job için tamamlanmış business effect bırakmamıştır.

    Admission kararı
    admitted=true
    Business result
    resultRows=0 / processedRows=0
    Caller beklentisi
    Bu job için commit edilmiş effect yok
  5. İlk kabulü final success’e yükseltme

    Caller, admitted=true bilgisini final success diye yorumlarsa failure kaydını kaybeder. Bu dalda doğru sonuç, kabul edilmiş ama başarısız olmuş bir iştir.

    Admission kararı
    admitted=true
    Business result
    state=failed / resultRows=0
    Caller beklentisi
    Kabul edildi, başarısız oldu
  6. Başarı için aynı job’un sonucunu iste

    Normal örnekte finished=13, resultRows=1 ve processedRows=1 vardır. Bunlar failure dalına taşınamaz; success, aynı operation’ın kendi sonucuyla doğrulanır.

    Admission kararı
    failure admitted=true
    Business result
    failure resultRows=0
    Caller beklentisi
    Different branch != this job evidence

VARSAYIM · SINIR · KONTROL

Timer sayacı business completion değildir

Bir timer tick veya scheduler log kaydı, en fazla trigger’ın gözlendiğini gösterebilir. İşin kalıcı sonucu için result owner’dan başka bir gözlem gerekir. Dersin kaydı due, observed, admitted, started ve resultRows alanlarını bu nedenle ayırır. due=10 ve observed=14 dalında policy işe başlama izni vermez. Kabul sonrası hata dalında ise admitted=true olmasına rağmen resultRows=0 kalır. İkisini yalnız “iş yok” diye etiketlemek, ilkinin admission kararını ve ikincinin execution hatasını görünmez yapar.

Timer’ın process içinde bulunması, onun durable scheduler olduğunu göstermez. Cloud controller kullanılması da tam deadline garantisi değildir. Event loop yükü ve servis politikaları gecikmeyi etkileyebilir. Bu derste gerçek timer gecikmesi ölçülmez; küçük logical clock örneğinin kararları incelenir. Değerlendirmede önce alanın hangi owner’ın bilgisini temsil ettiğini sor: scheduler zamanı mı, worker başlangıcı mı, database commit’i mi? Ardından bu bilgiyi hangi sonuç iddiası için kullandığını kontrol et.

Duplicate event aynı effect olmak zorunda değil

Aynı schedule slot için iki trigger gelmesi, seçilen ürünün davranışı içinde mümkün olabilir. İki event’in jobId alanı aynıysa iki ayrı business operation oldukları söylenemez. Atlas worker’ı processed marker ile sonucu aynı transaction’da tutar. İkinci event mevcut marker’ı bulduğunda aynı effect’i tekrar yazmaz. Bu marker’ın kapsamı seçilen job kimliğidir; başka bir purpose veya slot aynı operation sayılmaz. Event sayısı ile effect sayısını ayrı okuyarak neyin tekrarlandığını belirlersin.

Background function’ın request bittikten sonra devam etmesi de runtime davranışına bağlıdır. Process shutdown, worker hatası veya platform cancellation işi durdurabilir. Bu yüzden caller’ın ilk kabul kaydı final success yerine kullanılamaz. Atlas’ın failure dalı bu farkı görünür tutar: kabul vardır, başlangıç vardır, ama committed result yoktur. Retry tasarımında önce hangi state’in kalıcı olduğunu belirlersin. Sonucun kullanıcıya bildirilmesi de business commit’ten ayrı bir aşamadır; bildirim eksikliği tek başına commit’in yapılmadığını göstermez.

3. Blue · Güvenli geliştirme ve savunma

Hareket olmadan bütün senaryoları oku

Aynı slot

  1. Operation identity’yi sabitle

    Bu örnekte due/observed/admitted alanlarını logical scheduler ve dispatcher, resultRows ile processedRows alanlarını ayrı SQLite okuyucusu üretir. Aynı slot ve jobId ile eşleştirilen kayıtlar gerçek cloud scheduler log’u değildir. Public-note-index/slot-10, bu örnekte aynı işin kimliğidir. Scheduler event’lerinin sayısını yorumlamadan önce event’lerin hangi operation’a ait olduğunu belirlersin.

    Job gözlemi
    jobId=public-note-index/slot-10
    Result kaydı
    Result henüz incelenmedi
    Kanıt sınırı
    Correlation pending
  2. İki event aynı işi gösteriyor

    Duplicate dalında events=2 ve jobId aynıdır. İki event görmek, iki ayrı operation veya iki tamamlanmış effect görmek değildir.

    Job gözlemi
    events=2 / same jobId
    Result kaydı
    Result henüz incelenmedi
    Kanıt sınırı
    Event count != effect count
  3. Effect’i bağımsız sonuçtan oku

    Effects=1 ve resultRows=1, aynı operation için tek kalıcı sonuca işaret eder. Event kaydı ile result kaydı farklı soruları cevaplar.

    Job gözlemi
    events=2 / same jobId
    Result kaydı
    effects=1 / resultRows=1
    Kanıt sınırı
    Tek sonuç gözlendi
  4. Bu örneğin sonucunu genelleme

    Bu dal, aynı slot’un iki event’inin tek effect bırakmasını gösteriyor. Her external scheduler veya dış side effect için exactly-once garantisi üretmiyor.

    Job gözlemi
    events=2
    Result kaydı
    effects=1 / resultRows=1
    Kanıt sınırı
    Kapsam: yalnız bu örneğin operation’ı
  5. Saat doğruluğu ayrı bir ölçüm

    ExternalSchedulerExecuted=false ve nodeTimerTimingMeasured=false. Bu kayıtlarla gerçek timer gecikmesi veya cloud job creation zamanı ölçülmüş sayılamaz.

    Job gözlemi
    externalSchedulerExecuted=false
    Result kaydı
    effects=1
    Kanıt sınırı
    nodeTimerTimingMeasured=false
  6. Yalnız doğrulanan sonucu raporla

    Doğrulanan sonuç: aynı authored job için iki event, tek effect. Scheduler’ın üretim davranışı veya fiziksel saat garantisi için başka gözlem gerekir.

    Job gözlemi
    events=2 / same jobId
    Result kaydı
    effects=1 / resultRows=1
    Kanıt sınırı
    Gerçek scheduler ölçümü yok

Eksik sonuç

  1. Admission kaydı var

    Bu örnekte due/observed/admitted alanlarını logical scheduler ve dispatcher, resultRows ile processedRows alanlarını ayrı SQLite okuyucusu üretir. Aynı slot ve jobId ile eşleştirilen kayıtlar gerçek cloud scheduler log’u değildir. Bir audit yalnız admitted=true bilgisini taşıyabilir. Final state ve reportedSuccess gözlenmeden bu kayıt sonucun ne olduğunu anlatmaz.

    Job gözlemi
    admitted=true
    Result kaydı
    Final state gözlenmedi
    Kanıt sınırı
    Outcome unknown
  2. Selector için gerekli alanları belirle

    Dersin XPath kontrolü admitted=true, state=failed ve reportedSuccess=true alanlarının birlikte bulunmasını arıyor. Yalnız ilk alan bu çelişkiyi değerlendirmeye yetmez.

    Job gözlemi
    admitted=true
    Result kaydı
    state / reportedSuccess eksik
    Kanıt sınırı
    Gerekli gözlem eksik
  3. Sıfır eşleşme neden kesin sonuç değil?

    Eksik alanlar selector’ı eşleştirmeyebilir. Bu durumda sıfır eşleşme, uygulamanın doğru sonuç raporladığının kanıtı olmaz; gerekli observation yoktur.

    Job gözlemi
    admission observed
    Result kaydı
    Final sonuç gözlenmedi
    Kanıt sınırı
    Insufficient evidence
  4. Tam failure fixture’ı farklıdır

    Tam authored fixture admitted=true, state=failed ve reportedSuccess=false içerir. Beklenen eşleşme 0, bu fixture’ın success iddiası taşımamasından gelir; eksik kayıtla aynı kanıt değildir.

    Job gözlemi
    authored fixture admitted=true
    Result kaydı
    state=failed / reportedSuccess=false
    Kanıt sınırı
    expected=0 / complete fields
  5. Positive fixture kontrolün çalıştığını gösterir

    Positive fixture’da reportedSuccess=true seçilir ve expected=1 olur. Kontrolün bu örneği bulması, gerçek product log’larının aynı alanları kullandığını göstermez.

    Job gözlemi
    positive admitted=true
    Result kaydı
    positive state=failed / reportedSuccess=true
    Kanıt sınırı
    positiveExpected=1
  6. Eksik observation için unknown bırak

    İlk eksik kaydın final sonucu hâlâ bilinmiyor. Tam veya positive fixture’dan alan ödünç almak yerine, aynı operation için final state ve reportedSuccess gözlemi istersin.

    Job gözlemi
    İlk kayıtta admission gözlendi
    Result kaydı
    İlk kaydın final sonucu bilinmiyor
    Kanıt sınırı
    Eksik alanlar için yeni gözlem gerekir

UYGULAMA · GÜVENLİK KONTROLÜ · DOĞRULAMA

Lifecycle ledger admission’dan result’a kadar sürsün

Bu örnekte due/observed/admitted alanlarını logical scheduler ve dispatcher, resultRows ile processedRows alanlarını ayrı SQLite okuyucusu üretir. Aynı slot ve jobId ile eşleştirilen kayıtlar gerçek cloud scheduler log’u değildir. Lifecycle kaydında schedule slot, original due, observed start, admission kararı ve result owner açıkça ayrılmalıdır. Bu örneğin maxStartAge=3 politikasında observed=13 kabul edilir, observed=14 atlanır. Bu sınırı başka bir scheduler’ın default’u gibi kullanamazsın. Caller’ın aldığı yanıt yalnız admission ise, final sonucu sorgulayan sonraki status isteği veya notification aynı job’un result owner’ına dayanmalıdır. İlk yanıtın başarı kodu, sonucun tamamlandığını kendi başına söylemez.

Worker, index-public-note purpose’unu ve noteId=tea değerini bilinen job sözleşmesine göre değerlendirir. Böylece request dışındaki data erişimi browser’ın o andaki state’inden çıkarılmaz. Dersin SQLite örneğinde ayrı bir connection, devam eden transaction’ın uncommitted result’unu göremez; COMMIT sonrasında sonucu görür. Bu, sonucun hangi noktada başka bir okuyucu için mevcut olduğuna somut bir sınır koyar. Public note üzerinde yapılan bu gözlem, cloud recovery veya kullanıcı authentication davranışını doğrulamaz.

Miss, failure ve retry ayrı branch’lerdir

Late dalında job kabul edilmez ve result oluşmaz. Kabul edilmiş failure dalında ise lifecycle failed kalır; result ve marker transaction’ı rollback edilir. Duplicate dalında aynı job’un committed marker’ı bulunur ve resultRows=1 korunur. Bunlar farklı sonuçlardır ve ayrı raporlanmalıdır. Compensation, retry budget ve kaçırılmış schedule için catch-up davranışı gerçek uygulamanın politikasıdır. Bir dalın başarılı olması, başka bir dalın aynı koşullarda çalıştığı anlamına gelmez.

Kanıtı toplarken tek bir sayaca dayanma. Aynı job kimliğiyle admission kararını, final state’i ve committed result’u eşleştir. Final state veya reportedSuccess alanı yoksa XPath kontrolünün sıfır eşleşme vermesi, doğru sonuç raporlandığını kanıtlamaz. Gerekli gözlem eksiktir. Tam failure fixture’ı ile positive fixture, kontrolün hangi alanları aradığını açıklar; eksik kaydın alanlarını doldurmaz. Dersin bütün hareketleri yerel karar adımlarıdır: scheduler’a veya cloud worker’a gönderilmiş network packet olarak yorumlanmaz.

ŞİMDİ VAKAYA UYGULA

Bir job’un zamanı, kabulü ve commit edilen sonucu hangi kayıtlarla ayrılır?

Atlas, public notu slot-10 için indexlemek istiyor. Bu örnek duvar saati yerine küçük bir logical clock kullanıyor: due=10, izin verilen en büyük başlangıç gecikmesi 3. Duru önce işin kabulünü, sonra aynı job’un kalıcı sonucunu inceliyor.

Vakadaki accepted, delivery ve committed effect kayıtlarını farklı owner’lar üzerinden oku. Caller’ın bilinmeyen sonucunu business rollback olarak yeniden adlandırma.

Bağlı vaka dosyasını aç ↗

ÖRNEĞİ BİRLİKTE OKUYALIM

Public note schedule/admission/result ledger

Bir alan seç; hangi sonucu desteklediğini ve nerede yetersiz kaldığını incele.

Ham kaydı ve alan açıklamalarını oku
{
  "schedule": {
    "purpose": "index-public-note",
    "slot": "slot-10",
    "due": 10,
    "maxStartAge": 3,
    "unit": "authored logical clock; not wall clock"
  },
  "normal": {
    "observed": 12,
    "lateness": 2,
    "admitted": true,
    "started": 12,
    "finished": 13,
    "resultRows": 1,
    "processedRows": 1,
    "callerAdmissionIsResult": false
  },
  "late": {
    "observed": 14,
    "lateness": 4,
    "admitted": false,
    "outcome": "skip-late",
    "resultRows": 0
  },
  "duplicate": {
    "events": 2,
    "jobId": "public-note-index/slot-10",
    "effects": 1,
    "resultRows": 1
  },
  "failure": {
    "admitted": true,
    "started": 12,
    "state": "failed",
    "resultRows": 0,
    "processedRows": 0,
    "reason": "benign NOT NULL failure; explicit rollback"
  },
  "boundaries": {
    "dueBoundaryObserved13Admitted": true,
    "observed14Admitted": false,
    "externalSchedulerExecuted": false,
    "nodeTimerTimingMeasured": false,
    "requestContextCarried": false
  },
  "selector": {
    "language": "XPath",
    "xml": "<audit><async admitted=\"true\" state=\"failed\" reportedSuccess=\"false\"/></audit>",
    "xpath": "count(/audit/async[@admitted='true' and @state='failed' and @reportedSuccess='true'])",
    "expected": 0,
    "positiveFixtureXml": "<audit><async admitted=\"true\" state=\"failed\" reportedSuccess=\"true\"/></audit>",
    "positiveExpected": 1,
    "scope": "Only authored protocol-decision observations, not product log field names or a live HTTP capture.",
    "missingFieldBehavior": "Missing observation is insufficient evidence; zero matches is not proof of correct runtime behavior."
  }
}
schedule
İşin schedule slot’u, zamanı ve kabul edilen en büyük başlangıç gecikmesi.
normal/late/failure
İşe başlama izni ile kalıcı result ayrı gösterilir; late dalı kabul edilmez, failure dalı kabulden sonra başarısız olur.
duplicate
Aynı job kimliği için event sayısı ile business effect sayısını karşılaştırır.
selector
Kabul edilmiş ama başarısız bir işin yanlışlıkla başarılı raporlanmasını arayan öğretim kontrolü.

Bu örnek küçük bir logical clock ve yerel SQLite kullanır. Gerçek Node timer gecikmesi, cloud scheduler, Lambda veya request dışında çalışan production worker ölçülmez.

İki yanlış kanı

Due time veya async accepted sonucu işin tamamlandığını gösterir.

Trigger/admission ayrı boundary’dir; worker ve data owner’da final outcome ayrıca gerekir.

Her schedule slot tam bir kez ve exact zamanda çalışır.

Product/runtime policy’ye göre late, missed veya duplicate olabilir; logical fixture real timing guarantee değildir.

SIRA SENDE

Bu hikâyeyi sen çöz.

Sonucu tahmin et, kanıtın sınırını bul ve nedenini kendi cümlenle anlat.

Job için due=10 ve maxStartAge=3 tanımlanmış. Job, observed=14 anında görülüyor. Başlatılabilir mi?

  1. Hayır. lateness=4 olduğu için sonuç skip-late.
  2. Evet. Zamanı geçmiş her scheduled job mutlaka çalıştırılır.
Gerekçeli cevabı oku

Hayır. lateness=4 olduğu için sonuç skip-late. — İzin verilen 3 birimlik pencere aşılmıştır. observed=13 sınırda kabul edilirken observed=14 bu pencerenin dışında kalır.

admitted=true ve started=12, fakat state=failed ve resultRows=0. Caller başarı bildirebilir mi?

Dersten seçilen artifact alanları; öğretim örneği

failure
{"admitted":true,"started":12,"state":"failed","resultRows":0,"processedRows":0,"reason":"benign NOT NULL failure; explicit rollback"}
  1. Evet. Job’ın kabul edilmesi tamamlandığını gösterir.
  2. Hayır. Business işlem başarısız olmuş ve rollback yapılmış.
Gerekçeli cevabı oku

Hayır. Business işlem başarısız olmuş ve rollback yapılmış. — Kabul edilen job çalışmaya başlamış, fakat NOT NULL hatası sonrasında explicit rollback yapılmıştır. resultRows ve processedRows 0 kalır; başarı sonucu yoktur.

Aynı slot için events=2 ve effects=1 görülüyor. Logical clock ve requestContextCarried=false bu sonucu hangi sınırlar içinde yorumlamamızı gerektirir?

Gerekçeli cevabı oku

Slot’un sabit jobId değeri burada idempotency key olarak kullanılır; yinelenen trigger aynı effect’i tekrar uygulamaz. Zamanlar örneğin logical clock’una aittir. Node timer latency’si veya gerçek scheduler’ın exactly-once davranışı ölçülmez. Job, HTTP request’in dışında çalışır. Gerekli doğrulanmış subject ve scope, yürütme anındaki context’ten kurulmalıdır; correlation ID kullanıcı kimliğinin kanıtı değildir.

□ Trigger sayısı ile effect sayısını ayırdım.

□ Logical clock veya correlation ID’den gerçek scheduler ya da kullanıcı kimliği kanıtı çıkarmadım.

Uygulama konsolunu aç · request / response / browser
Request, URL, cookie ve DOM örneklerini ayrıca aç

Kaynaklar ve kapsam

  • Node.js v24.13.0 — TimerssetTimeout(callback[, delay[, ...args]]) · timeout.unref() · Cancelling timers
  • Kubernetes — CronJobTime zones · Concurrency policy · CronJob limitations: Job creation
  • AWS Lambda — Asynchronous invocationInvoking a Lambda function asynchronously
  • SQLite — Transaction2. Transactions · 2.1. Read transactions versus write transactions · 2.2. DEFERRED, IMMEDIATE, and EXCLUSIVE transactions · 2.3. Implicit versus explicit transactions
  • SQLite — IsolationIsolation Between Database Connections · Isolation And Concurrency
  • Python 3.14 — sqlite3Tutorial · sqlite3.connect · Cursor.execute · How to use placeholders to bind values in SQL queries · Transaction control via the isolation_level attribute · How to use the connection context manager