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.
1. Core · Mekanizma
Hareket olmadan bütün senaryoları oku
Kabul ve sonuç
- Ö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
- 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
- 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
- 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
- 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
- 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ı
- Ö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
- 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
- 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
- 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
- Ö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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- Ö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
- 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
- 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
- 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
- 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
- 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ıç
- Ö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ı
- İş 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
- 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
- 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
- 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ı
- 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
- 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
- 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
- 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
- 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
- İ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
- 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
- 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
- İ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
- 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
- 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’ı
- 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
- 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ç
- 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
- 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
- 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
- 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
- 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
- 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?
- Hayır. lateness=4 olduğu için sonuç skip-late.
- 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"}
- Evet. Job’ın kabul edilmesi tamamlandığını gösterir.
- 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