Hacker DirectoryHacker Directory
Öğrenmeye devam et
ENHTML kaydet ↓

WEB / WEB-19.S01

Races, transactions ve idempotency

Note okunduktan sonra revision değişebilir. Eski koşul, DB commit ve caller’ın sonucu öğrenmesi arasındaki farkı izle.

CORE · RED · BLUE · ARTIFACT · PRACTICE

1. Core · Mekanizma

Hareket olmadan bütün senaryoları oku

Commit sonucu

  1. Operation hazırlandı

    Caller, public note işlemini purpose ve key alias ile hazırlar. Bu key bir credential değildir.

    Caller
    Public note işlemi
    Service
    Request scope seçildi
    Note DB
    Tea note / version=1 committed
    Saved result
    Saved result yok
  2. Scope eşleştirildi

    Service caller, purpose ve key’i note/title parameters ile eşleştirir. Aynı key’in hangi işlem kapsamında kullanılacağı belirlenir.

    Caller
    Public note işlemi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Tea note / version=1 committed
    Saved result
    Saved result yok
  3. Mutation henüz pending

    Rename transaction içinde hazırlanır. Bağımsız observer hâlâ önceki committed note’u görür.

    Caller
    Public note işlemi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Pending: Updated note / version=2
    Saved result
    Saved result yok
  4. Mutation ve result birlikte commit

    Note değişikliği ile normalize edilmiş parameters ve saved result aynı SQL transaction’da commit edilir. Dış effect bu transaction’a dahil değildir.

    Caller
    Public note işlemi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Updated note / version=2 committed
    Saved result
    Committed result: Updated note / version=2
  5. Caller sonucu öğrendi

    Caller noteId, title ve version sonucunu yerel tamamlanma adımında öğrenir. Gerçek HTTP teslimi ayrıca gözlenmelidir.

    Caller
    Updated note / version=2 / mutationCount=1
    Service
    Scope+parameters eşleştirildi
    Note DB
    Updated note / version=2 committed
    Saved result
    Committed result: Updated note / version=2

Eski revision

  1. Operation hazırlandı

    Caller, public note işlemini purpose ve key alias ile hazırlar. Bu key bir credential değildir.

    Caller
    Public note işlemi
    Service
    Request scope seçildi
    Note DB
    Tea note / version=1 committed
    Saved result
    Saved result yok
  2. Revision 1 okundu

    Uygulama revision=1 okur. Verinin sonraki kullanıma kadar değişmeden kalacağı garanti değildir.

    Caller
    Okunan expected=1
    Service
    Request scope seçildi
    Note DB
    Tea note / version=1 committed
    Saved result
    Saved result yok
  3. Başka update commit edildi

    Bağımsız note değişikliği store’da Coffee note ve version=2 oluşturur. Önceki read artık current değildir.

    Caller
    Okunan expected=1
    Service
    Request scope seçildi
    Note DB
    Coffee note / version=2
    Saved result
    Saved result yok
  4. Expected revision DB’ye taşındı

    Service expected=1 koşulunu authoritative UPDATE’e bound value olarak verir. Yalnız eski UI kontrolüne güvenmez.

    Caller
    Okunan expected=1
    Service
    Expected=1 / current=2 koşulu
    Note DB
    Coffee note / version=2
    Saved result
    Saved result yok
  5. Eski revision reddedildi

    Guarded statement rowcount=0 üretir. Current title ve revision korunur; eski operation mutation yapmamıştır.

    Caller
    Okunan expected=1
    Service
    Expected=1 / current=2 koşulu
    Note DB
    Coffee note / version=2 / changedRows=0
    Saved result
    Saved result yok
  6. Conflict sonucu

    Caller conflict sonucunu öğrenir. Reddedilmiş eski operation business mutation olarak sayılmaz.

    Caller
    Conflict / current state korundu
    Service
    Expected=1 / current=2 koşulu
    Note DB
    Coffee note / version=2 / changedRows=0
    Saved result
    Saved result yok

Unknown + retry

  1. Operation hazırlandı

    Caller, public note işlemini purpose ve key alias ile hazırlar. Bu key bir credential değildir.

    Caller
    Public note işlemi
    Service
    Request scope seçildi
    Note DB
    Tea note / version=1 committed
    Saved result
    Saved result yok
  2. Scope eşleştirildi

    Service caller, purpose ve key’i note/title parameters ile eşleştirir. Aynı key’in hangi işlem kapsamında kullanılacağı belirlenir.

    Caller
    Public note işlemi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Tea note / version=1 committed
    Saved result
    Saved result yok
  3. Mutation henüz pending

    Rename transaction içinde hazırlanır. Bağımsız observer hâlâ önceki committed note’u görür.

    Caller
    Public note işlemi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Pending: Updated note / version=2
    Saved result
    Saved result yok
  4. Mutation ve result birlikte commit

    Note değişikliği ile normalize edilmiş parameters ve saved result aynı SQL transaction’da commit edilir. Dış effect bu transaction’a dahil değildir.

    Caller
    Public note işlemi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Updated note / version=2 committed
    Saved result
    Committed result: Updated note / version=2
  5. Caller sonucu bilmiyor

    Örnekte caller ilk tamamlanma bilgisini alamaz. Database commit’i korunur; eksik response rollback değildir.

    Caller
    İlk result bilgisi unknown
    Service
    Scope+parameters eşleştirildi
    Note DB
    Updated note / version=2 committed
    Saved result
    Committed result: Updated note / version=2
  6. Aynı scope ile retry

    Aynı purpose, key ve parameters ile stored result aranır. Yeni işlem başlatmadan önce önceki tamamlanma kaydı değerlendirilir.

    Caller
    İlk result bilgisi unknown
    Service
    Aynı scope+parameters ile retry
    Note DB
    Updated note / version=2 committed
    Saved result
    Committed result: Updated note / version=2
  7. Saved result tekrar kullanıldı

    Stored result bulunur ve ikinci note mutation yapılmaz. Result record sayısı 1 kalır.

    Caller
    İlk result bilgisi unknown
    Service
    Aynı scope+parameters ile retry
    Note DB
    Updated note / version=2 committed
    Saved result
    Saved result kullanıldı / mutationCount=1
  8. Caller sonucu öğrendi

    Caller noteId, title ve version sonucunu yerel tamamlanma adımında öğrenir. Gerçek HTTP teslimi ayrıca gözlenmelidir.

    Caller
    Updated note / version=2 / mutationCount=1
    Service
    Aynı scope+parameters ile retry
    Note DB
    Updated note / version=2 committed
    Saved result
    Saved result kullanıldı / mutationCount=1

Rollback result

  1. Operation hazırlandı

    Caller, public note işlemini purpose ve key alias ile hazırlar. Bu key bir credential değildir.

    Caller
    Public note işlemi
    Service
    Request scope seçildi
    Note DB
    Tea note / version=1 committed
    Saved result
    Saved result yok
  2. Scope eşleştirildi

    Service caller, purpose ve key’i note/title parameters ile eşleştirir. Aynı key’in hangi işlem kapsamında kullanılacağı belirlenir.

    Caller
    Public note işlemi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Tea note / version=1 committed
    Saved result
    Saved result yok
  3. Mutation henüz pending

    Rename transaction içinde hazırlanır. Bağımsız observer hâlâ önceki committed note’u görür.

    Caller
    Public note işlemi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Pending: Updated note / version=2
    Saved result
    Saved result yok
  4. Result kaydı oluşturulamadı

    NOT NULL koşulu saved result kaydını reddeder. Mutation bu anda hâlâ pending durumdadır; sonraki adımda explicit rollback hem mutation’ı hem result kaydını geri alır.

    Caller
    Public note işlemi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Pending: Updated note / version=2
    Saved result
    Constraint hatası / kayıt yok
  5. Transaction geri alındı

    Database Tea note ve version=1 kaydını korur. Operation result record’u commit edilmemiştir.

    Caller
    Public note işlemi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Tea note / version=1 korundu
    Saved result
    Result record=0
  6. Caller başarısızlığı biliyor

    Caller failure sonucunu öğrenir. Bu, commit başarılıyken response’un bilinmediği durumla aynı sonuç değildir.

    Caller
    Failure / rollback gözlendi
    Service
    Scope+parameters eşleştirildi
    Note DB
    Tea note / version=1 korundu
    Saved result
    Result record=0

ROLLER · STATE · VERİ AKIŞI

Bir read sonraki use için söz vermez

Application public notu revision=1 olarak okur. Operation uygulanana kadar authoritative owner’daki not revision=2’ye değişebilir. TOCTOU, check sırasında bilinen state ile use sırasındaki state arasındaki bu boşluğu anlatır. Order-dependent davranış, lost update ve invariant ihlali aynı sonuç değildir. Atlas örneği sıradan bir revision değişimi sonrasında guarded update’in eski expectation’ı reddetmesini gösterir.

Kontrol, UI’daki eski check’i tekrar etmek yerine operation condition’ını authoritative statement içinde değerlendirir. Örneğin UPDATE, note ID ve expected revision için bound values kullanır. Expected revision=1 iken current revision=2 olduğunda affectedRows=0 olur ve current title/revision korunur. Transaction açmak yanlış application predicate’ini doğru yapmaz. Korunacak invariant hangi row, field ve operation’ı kapsıyorsa açıkça tanımlanmalıdır.

Transaction visibility başka bir sorudur. Seçilen SQLite ayarlarında independent connection uncommitted update’i görmez; commit sonrasında okuyabilir. Bu, revision predicate’inin doğruluğundan ve HTTP caller’ın yanıt almasından ayrıdır. Örnekte before/after revision ve affected-row count sırayla gözlenir. Gerçek concurrent traffic veya timing ölçümü yerine finite state geçişleri incelenir.

Retry kimliğinin result ve purpose’u vardır

Caller completion response’unu alamadığında operation’ın hiç çalışmadığını bilemez. Atlas’ta note rename commit olur fakat caller’ın bilgisi UNKNOWN kalır. Aynı request alias ve aynı parameters ile retry committed result’u yeniden kullanır. Idempotency scope caller alias, operation purpose ve key’den oluşur; normalized note ID/title parameters da kaydedilir. Aynı scope/key farklı parameters ile gelirse conflict oluşur; önceki result başka intent adına sunulmaz.

Idempotency record ile business mutation aynı SQLite transaction’ında commit edilir. Zararsız NOT NULL failure dalında explicit rollback ikisini de bırakmaz. Record’un kendisi bir garanti değildir: server anlamını, validation’ını, retention’ını ve key reuse davranışını tanımlar. Stripe’ın saved status/body ve parameter comparison contract’ı buna bir örnektir; farklı product’larda failure retention veya pruning sonrası davranış farklı olabilir.

HTTP safe/idempotent method semantiği application’ın retry contract’ıyla aynı mekanizma değildir. Endpoint adı, bir key header’ı veya transaction tek başına end-to-end exactly-once effect sağlamaz. Email, file ve network effect’i seçilen SQL transaction’ının dışındadır. UNKNOWN response dalı da gerçek socket timeout ölçümü değil, caller bilgisinin kaybını gösteren öğretim olayıdır.

2. Red · Güven ve etki

Hareket olmadan bütün senaryoları oku

Eski revision

  1. Caller önce version 1’i okudu

    ReadVersion=1, caller’ın rename niyetini oluşturduğu kopyanın revision’ıdır. Bu sayı, kayıt sahibinin şimdi de version 1 tuttuğunu söylemez.

    Rename niyeti
    readVersion=1
    Kayıt sahibi
    Current revision henüz okunmadı
    Kabul sözleşmesi
    Update kararı henüz yok
  2. Kullanımdan önce kayıt version 2

    CurrentBeforeUse=2 ve başlık Coffee note. Önceki read’in kopyası güncel kayıt sahibinin revision’ından farklıdır.

    Rename niyeti
    expectedVersion=1
    Kayıt sahibi
    Coffee note / currentVersion=2
    Kabul sözleşmesi
    Revision koşulu gerekir
  3. Karar ve write aynı statement içinde

    Sabit UPDATE statement’ı id ile birlikte version koşulunu da değerlendirir. Eski expectedVersion=1, currentVersion=2 kaydını eşleştirmediğinden write kabul edilmez.

    Rename niyeti
    expectedVersion=1
    Kayıt sahibi
    affectedRowsOnStale=0
    Kabul sözleşmesi
    revision mismatch
  4. Coffee note korunuyor

    After kaydı Coffee note ve version=2 olarak kalıyor. AffectedRows=0, bu guarded update’in uygulanmadığını gösterir; önceki read’in yok olduğunu söylemez.

    Rename niyeti
    readVersion=1
    Kayıt sahibi
    after: Coffee note / version=2
    Kabul sözleşmesi
    Eski revision ile update uygulanmadı
  5. Parameter binding bu kararın yerine geçmez

    Title ve noteId data olarak bind edilir; revision guard ayrıca operation’ın güncel kayıt için geçerli olup olmadığını sınırlar. Data/query ayrımı ile güncellik koşulu farklı soruları cevaplar.

    Rename niyeti
    Parametreler data olarak kalır
    Kayıt sahibi
    affectedRowsOnStale=0
    Kabul sözleşmesi
    Binding != revision agreement
  6. Sonucu kendi kapsamıyla bildir

    Doğrulanan sonuç, eski revision koşuluyla yapılan bu update’in kaydı değiştirmemesidir. Her distributed writer veya başka store için aynı concurrency garantisi çıkarılmaz.

    Rename niyeti
    readVersion=1
    Kayıt sahibi
    Coffee note / version=2
    Kabul sözleşmesi
    Revision koşullu update reddedildi

Parameter farkı

  1. Operation scope’u sabitle

    Caller-demo, rename-public-note purpose’u ve request-a key’i bir arada değerlendirilir. Key’in tek başına bilinmesi caller identity veya permission kanıtı değildir.

    Rename niyeti
    caller-demo / rename-public-note / request-a
    Kayıt sahibi
    Saved result henüz incelenmedi
    Kabul sözleşmesi
    keyIsCredential=false
  2. İlk operation’ın sonucu kayıtlı

    Normal result, tea notunu Updated note ve version=2 olarak kaydetmiş. Bu kayıt, seçilen scope’taki ilk operation’ın parametrelerine aittir.

    Rename niyeti
    title=Updated note
    Kayıt sahibi
    saved result: Updated note / version=2
    Kabul sözleşmesi
    İlk operation parametrelerine bağlı
  3. Aynı key, farklı title

    Yeni aday Different note title istiyor, ama sameScopeKey=true. Aynı key etiketi, farklı parametreleri otomatik olarak aynı operation yapmaz.

    Rename niyeti
    newTitle=Different note title
    Kayıt sahibi
    Kayıtlı sonuç değişmedi
    Kabul sözleşmesi
    sameScopeKey=true
  4. Parameter conflict kararı

    Örneğin sonucu parameter-conflict. Uygulama aynı scope/key için ilk parametrelerle uyuşmayan adayı yeni rename olarak uygulamıyor.

    Rename niyeti
    Yeni parametreler farklı
    Kayıt sahibi
    existingResultPreserved=true
    Kabul sözleşmesi
    outcome=parameter-conflict
  5. Önceki sonuç silinmedi

    ExistingResultPreserved=true, önceki operation sonucunun korunduğunu belirtir. Conflict kaydı rollback edilmiş ilk operation veya silinmiş result anlamına gelmez.

    Rename niyeti
    parameter conflict
    Kayıt sahibi
    Kayıtlı sonuç korundu
    Kabul sözleşmesi
    No second rename accepted
  6. Yeni iş için yeni sözleşme gerekir

    Başka purpose veya farklı parametreler yeni bir operation olabilir; bunların permission ve identity scope’u ayrı değerlendirilir. Idempotency key’i authorization yerine koyamazsın.

    Rename niyeti
    separatePurposeIsSeparateScope=true
    Kayıt sahibi
    Mevcut sonuç korundu
    Kabul sözleşmesi
    keyIsCredential=false

VARSAYIM · SINIR · KONTROL

İlk check’in bilgisi sınırlıdır

Artifact readVersion=1 ile use sırasındaki currentVersion=2’yi ayrı gösterir. Yanlış varsayım eski observation’ın hâlâ current state olduğunu kabul etmektir. Sonuç yeni title’ın eski karar tarafından ezilmesi olabilir. Doğru guard dalında affectedRows=0 ve current state korunur. Öğrenci expected revision’ın hangi authoritative statement’ta değerlendirildiğini ve yanlış eşleşmede ne değişmediğini inceler.

Transaction declaration görmek application invariant’ının bütünüyle kapsandığını söylemez. Başka row, dış effect veya başka data owner aynı boundary’nin dışında kalabilir. Atlas transaction’ı mutation, result ve idempotency record’u birlikte tutar. Bu kapsamı farklı isolation level veya distributed topology’ye taşımadan önce onların condition ve failure davranışları ayrıca değerlendirilir.

UNKNOWN response failed operation değildir

Caller’ın yanıt alamaması ile store’un rollback etmesi farklı sonuçlardır. Commit olmuş iş aynı scope/key/parameters ile tekrar sorulduğunda stored result kullanılabilir. Key’i değiştirmek yeni intent anlamına gelebilir; aynı key’i farklı title veya purpose için kullanmak da contract kararı gerektirir. Idempotency key identity veya permission sağlamaz.

Yalnız success flag saklamak hangi note ve revision’ın tamamlandığını anlatmayabilir. Saved result noteId, title ve revision içerir; parameter conflict bu kaydı değiştirmez. Dış effect için bir sent flag varsa onun hangi owner’ın receipt’ini gösterdiği ayrıca bilinmelidir. Exactly-once iddiası aynı owner ve aynı effect kapsamına bağlanmadıkça sonuçlar karışır.

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

Hareket olmadan bütün senaryoları oku

Sonuç bilinmiyor

  1. Caller’ın ilk sonucu unknown

    Before/after revision ve affectedRows, yerel SQLite statement’ı ile ayrı SELECT okuyucusundan gelir; caller’ın UNKNOWN bilgisi ise ayrıca verilen senaryo koşuludur. CallerFirstKnowledge=unknown, caller’ın ilk sonucu öğrenemediğini anlatır. Bu alan, database’de commit olmadığına dair bir sonuç değildir.

    Caller gözlemi
    callerFirstKnowledge=unknown
    Operation sonucu
    Commit henüz incelenmedi
    Kanıt yorumu
    Sonuç kanıtı henüz yok
  2. Database commit’i ayrı gözlendi

    FirstCommitted=true ve kayıtlı result Updated note, version=2. Caller’ın unknown bilgisi ile kalıcı commit aynı anda bulunabilir.

    Caller gözlemi
    callerFirstKnowledge=unknown
    Operation sonucu
    firstCommitted=true / result version=2
    Kanıt yorumu
    Commit != caller receipt
  3. Retry aynı operation parametrelerini taşıyor

    SameParameters=true ve aynı caller/purpose/key scope’u, retry’nin ilk operation ile ilişkilendirilmesini sağlar. Sadece aynı title benzerliği bu ilişkiyi kurmaz.

    Caller gözlemi
    same scope / sameParameters=true
    Operation sonucu
    saved result version=2
    Kanıt yorumu
    Aynı operation ile eşleştirildi
  4. Kayıtlı sonuç yeniden kullanıldı

    ResultReused=true ve mutationCount=1. Retry, ikinci rename yazmadan ilk operation’ın sonucunu kullanmış.

    Caller gözlemi
    retry correlated
    Operation sonucu
    resultReused=true / mutationCount=1
    Kanıt yorumu
    Tek değişiklik gözlendi
  5. Unknown dalını başarısız sayma

    Buradaki kanıt, ilk operation’ın commit edildiğini ve retry’de tekrar effect yaratılmadığını gösterir. Caller’ın önceki unknown durumu “ilk iş başarısızdı” diye değiştirilemez.

    Caller gözlemi
    Caller’ın ilk sonuç bilgisi eksik
    Operation sonucu
    firstCommitted=true / mutationCount=1
    Kanıt yorumu
    Unknown knowledge != failed operation
  6. Doğrulanan sınırı açık bırak

    Bu örnek kaydedilmiş sonucu tekrar kullanır. Dış API effect’leri aynı SQLite transaction’ına katılmaz; local kayıt bütün sistem için exactly-once garantisi değildir.

    Caller gözlemi
    same operation
    Operation sonucu
    mutationCount=1
    Kanıt yorumu
    externalEffectsAtomic=false

Bilinen rollback

  1. Transaction öncesi revision’ı oku

    Before/after revision ve affectedRows, yerel SQLite statement’ı ile ayrı SELECT okuyucusundan gelir; caller’ın UNKNOWN bilgisi ise ayrıca verilen senaryo koşuludur. Rollback fixture’ında beforeVersion=1. Sonraki kayıtları aynı transaction’ın sonucuyla karşılaştırmak için bu başlangıç bilinmelidir.

    Caller gözlemi
    Caller sonucu henüz bilinmiyor
    Operation sonucu
    beforeVersion=1
    Kanıt yorumu
    Transaction sonucu henüz yok
  2. Result kaydı constraint’e takıldı

    Zararsız NOT NULL result adayı başarısız oluyor ve explicit rollback uygulanıyor. Bu, yalnız caller gözleminin eksik olmasından farklı bir transaction sonucudur.

    Caller gözlemi
    Caller sonucu ayrı değerlendirilir
    Operation sonucu
    Constraint hatası / explicit rollback
    Kanıt yorumu
    Rollback gözlendi
  3. Revision ve result birlikte incelendi

    AfterVersion=1 ve resultRecords=0. Önceki revision korunmuş ve bu transaction için committed result bırakılmamış.

    Caller gözlemi
    Caller sonucu ayrı değerlendirilir
    Operation sonucu
    afterVersion=1 / resultRecords=0
    Kanıt yorumu
    Bu transaction’dan committed result yok
  4. Bu dalın kanıtı rollback’tir

    Explicit rollback ile bağımsız after kaydı birlikte bilinen başarısız transaction’ı destekler. Unknown-response dalının firstCommitted=true kaydı bu dala taşınmaz.

    Caller gözlemi
    Başka dal: response sonucu bilinmiyor
    Operation sonucu
    afterVersion=1 / resultRecords=0
    Kanıt yorumu
    Known rollback != unknown commit
  5. Eksik gözlem üçüncü bir durumdur

    Commit veya rollback için gerekli gözlem yoksa iki daldan birini seçemezsin. Selector’ın sıfır eşleşmesi, eksik transaction kaydını tamamlamaz.

    Caller gözlemi
    Eksik sonuç bilinmiyor olarak kalır
    Operation sonucu
    Rollback örneği ayrı doğrulandı
    Kanıt yorumu
    Eksik kanıt başka daldan tamamlanmaz
  6. Retry kararını bilinen state’e bağla

    Saved result varsa aynı operation için onu değerlendir; bilinen rollback’te kalıcı sonuç olmadığını dikkate al; unknown durumunda outcome kanıtı iste. Key possession tek başına bu kararların hiçbirini vermez.

    Caller gözlemi
    keyIsCredential=false
    Operation sonucu
    rollback resultRecords=0
    Kanıt yorumu
    Result / rollback / unknown ayrı tutulur

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

Invariant authoritative statement’ta değerlendirilsin

Before/after revision ve affectedRows, yerel SQLite statement’ı ile ayrı SELECT okuyucusundan gelir; caller’ın UNKNOWN bilgisi ise ayrıca verilen senaryo koşuludur. Atlas invariant’ı title’ın yalnız current revision expected revision’a eşitken değişmesidir. Expected=1/current=2 mismatch rowcount=0 üretir ve yeni title/revision korunur. Before/after değerleri independent SELECT ile karşılaştırılır; UI kopyasının kendiliğinden güncellendiği varsayılmaz. Transaction visibility ve operation condition ayrı kontrollerdir.

Örnek explicit transaction control ve iki independent connection kullanır. Daha geniş invariant için row set, condition veya locking semantics ve failure handling seçilen database’in contract’ına göre belirlenir. Tek row üzerinde gözlenen doğru davranış başka owner veya external effect için atomicity kanıtı değildir.

Mutation ile saved result birlikte commit edilsin

Caller-demo / rename-public-note / request-a scope’u normalized tea ve Updated note parameters’ını saklar. Normal response ile aynı-parameter retry aynı result’u döndürür; mutationCount=1 kalır. Alias bu öğretim kaydındaki request kimliğidir, credential değildir. Başka purpose için aynı key farklı namespace’e ait olabilir; aynı purpose içinde parameter mismatch ise ayrı conflict’tir.

Rollback dalında note eski revision’da kalır ve result record oluşmaz. UNKNOWN response dalında commit korunur ve retry saved result’u bulur. İkisinde caller yeniden işlem yapmak isteyebilir ama bilinen business state farklıdır. Retry policy bu farkı korumalıdır; browser receipt veya external effect gözlenmemişse bunların sonucu ayrıca UNKNOWN kalır.

ŞİMDİ VAKAYA UYGULA

Eski revision, tekrar gelen operation ve bilinmeyen sonuç hangi kanıtlarla ayrılır?

Duru, Atlas public tea notunun başlığını değiştirmek istiyor. Uygulama revision koşulunu ve caller/purpose/key ile bağlı operation kaydını ayrı değerlendiriyor. Bir sonuç caller’a görünmese bile database’de commit edilmiş olabilir.

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 condition/retry result ledger

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

Ham kaydı ve alan açıklamalarını oku
{
  "invariant": {
    "noteId": "tea",
    "readVersion": 1,
    "currentBeforeUse": 2,
    "affectedRowsOnStale": 0,
    "after": {
      "title": "Coffee note",
      "version": 2
    },
    "statement": "UPDATE notes SET title=?,version=version+1 WHERE id=? AND version=?",
    "parameters": [
      "Updated note",
      "tea",
      1
    ]
  },
  "scope": {
    "callerAlias": "caller-demo",
    "purpose": "rename-public-note",
    "keyAlias": "request-a",
    "parameters": {
      "noteId": "tea",
      "title": "Updated note"
    },
    "keyIsCredential": false,
    "separatePurposeIsSeparateScope": true
  },
  "normal": {
    "result": {
      "noteId": "tea",
      "title": "Updated note",
      "version": 2
    },
    "mutationCount": 1,
    "resultRecords": 1
  },
  "retryUnknown": {
    "firstCommitted": true,
    "callerFirstKnowledge": "unknown",
    "sameParameters": true,
    "resultReused": true,
    "result": {
      "noteId": "tea",
      "title": "Updated note",
      "version": 2
    },
    "mutationCount": 1
  },
  "mismatch": {
    "sameScopeKey": true,
    "newTitle": "Different note title",
    "outcome": "parameter-conflict",
    "existingResultPreserved": true
  },
  "rollback": {
    "beforeVersion": 1,
    "afterVersion": 1,
    "resultRecords": 0,
    "reason": "benign NOT NULL result candidate; explicit rollback"
  },
  "limits": {
    "concurrentRequestsExecuted": false,
    "unknownResponse": "injected caller knowledge event, not socket loss",
    "externalEffectsAtomic": false,
    "universalExactlyOnce": false
  },
  "selector": {
    "language": "XPath",
    "xml": "<audit><revision expected=\"1\" current=\"2\" mutationAccepted=\"false\"/></audit>",
    "xpath": "count(/audit/revision[@expected != @current and @mutationAccepted='true'])",
    "expected": 0,
    "positiveFixtureXml": "<audit><revision expected=\"1\" current=\"2\" mutationAccepted=\"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."
  }
}
invariant
Fixed guarded SQL ve observed stale rejection.
scope
Caller/purpose/key ile normalized parameters.
retryUnknown/rollback
Commit korunması ile rollback ayrı outcomes.
selector
Synthetic stale mutation acceptance kararı.

Selected own SQLite +finite sequential public-note operations. Vulnerable reproduction, concurrency harness, actual network loss veya external side-effect guarantee yok.

İki yanlış kanı

Transaction açtım; application’ın bütün races’ı ve invariants’ı çözülmüştür.

Isolation/operation predicate/row scope ayrı seçimlerdir; transaction declaration tek başına correct business condition değildir.

Response gelmedi; operation kesin rollback oldu.

Caller knowledge unknown kalabilir; committed result same-scope retry’de reused olabilir, rollback ayrı kanıt ister.

SIRA SENDE

Bu hikâyeyi sen çöz.

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

Read sırasında version=1, kullanım anında current version=2. UPDATE version=1 koşuluyla çalışıyor. Yeni title yazılır mı?

  1. Evet. Bir kez read edilmiş olması sonraki bütün state değişikliklerini kilitler.
  2. Hayır. affectedRowsOnStale=0; Coffee note version=2 korunur.
Gerekçeli cevabı oku

Hayır. affectedRowsOnStale=0; Coffee note version=2 korunur. — Version koşulu write sırasında yeniden uygulanır. Eski read sonucu güncel kaydın üzerine yazma izni değildir.

Caller ilk sonucu bilmiyor, fakat ilk işlem commit etmiş. Aynı scoped key ve parametrelerle retry neden ikinci mutation üretmiyor?

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

retryUnknown.firstCommitted
true
retryUnknown.callerFirstKnowledge
unknown
retryUnknown.sameParameters
true
retryUnknown.resultReused
true
retryUnknown.mutationCount
1
  1. Önceki result yeniden kullanılır; mutationCount=1 kalır.
  2. Caller unknown dediğinde server bütün önceki write’ları geri alır.
Gerekçeli cevabı oku

Önceki result yeniden kullanılır; mutationCount=1 kalır. — callerFirstKnowledge=unknown, server commit’inin yokluğu değildir. Same-parameter dedupe, korunmuş sonucu döndürür ve effect’i tekrar uygulamaz.

Aynı scope/key farklı title ile gelince parameter-conflict oluşuyor. Idempotency scope, transaction ve gerçek concurrency için hangi sınırlar korunmalı?

Gerekçeli cevabı oku

Key caller, purpose ve parametrelerle aynı işlemi tanımlar; farklı title eski result’un üzerine yazılmaz. Key credential veya authorization değildir. Yerel transaction write ve result record’u birlikte koruyabilir; başarısız result adımında explicit rollback gerekir. Bu sıralı örnek parallel request isolation veya external effect atomicity ölçmez; universal exactly-once garantisi vermez.

□ Idempotency key’ini purpose/parametrelerine bağladım; permission saymadım.

□ Yerel result reuse’dan concurrency veya external atomicity garantisi çıkarmadım.

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

Kaynaklar ve kapsam