Project 02 · Deterministic simulationProje 02 · Deterministik simülasyon

TRACEFORGE

Turn a bug that happened once into a scenario anyone can inspect and replay.Bir kez ortaya çıkan hatayı, incelenebilir ve tekrar üretilebilir bir senaryoya dönüştürmek.

StatusDurum
Working prototype, 2026Çalışan prototip, 2026
RunsÇalıştığı yer
In the browser, 36 kB, no serverTarayıcıda, 36 kB, sunucusuz
MethodYöntem
Deterministic simulation; safety and progress checked apartDeterministik simülasyon; doğruluk ve ilerleme ayrı denetlenir
My partBenim kısmım
Simulator, service model, fault plans, checks, shrinker, replay interfaceSimülatör, servis modeli, arıza planları, denetimler, küçültücü, tekrar oynatma arayüzü

The project in four partsDört bölümde proje

01

ProblemProblem

An order system lost stock once. A worker had saved the stock change and died before telling the queue the job was done; the queue delivered the job again and the stock dropped a second time. No unit test fails like this: the crash has to land exactly between two writes.

Bir sipariş sistemi bir kez stok kaybetti. Bir çalışan stok değişikliğini kaydetmiş, kuyruğa işin bittiğini söyleyemeden çökmüştü; kuyruk işi yeniden teslim etti ve stok ikinci kez düştü. Hiçbir birim testi böyle başarısız olmaz: çökmenin tam iki yazma işleminin arasına denk gelmesi gerekir.

02

ConstraintsKısıtlar

  • Real clocks and threads make every run different; the same inputs must give the same run.
  • Faults must be planned: delays, duplicates, drops, partitions, a crash at a named point.
  • "Nothing broke" and "everything finished" are different questions.
  • A failure with 30 orders and 8 faults is too big to read.
  • Gerçek saat ve iş parçacıkları her çalıştırmayı farklı kılar; aynı girdi aynı çalıştırmayı vermeli.
  • Arızalar planlanmalı: gecikme, kopya, kayıp, bölünme, belirli bir noktada çökme.
  • "Hiçbir şey bozulmadı" ile "her şey bitti" farklı sorulardır.
  • 30 sipariş ve 8 arızalı bir hata okunamayacak kadar büyüktür.
03

DecisionKarar

Simulate the system instead of running it: a virtual clock, randomness keyed by message, an event queue with a stable order. Check the safety rules after every event and progress after the faults end. Shrink every failure automatically.

Sistemi çalıştırmak yerine simüle et: sanal saat, mesaja bağlı rastgelelik, sırası kararlı bir olay kuyruğu. Doğruluk kurallarını her olaydan sonra, ilerlemeyi arızalar bittikten sonra denetle. Her hatayı otomatik olarak küçült.

04

SolutionÇözüm

Orders, a queue with leases and at-least-once delivery, and a stock worker, written as state machines. Three workers: the buggy one, the fix, and a queue that never redelivers, which is safe but stuck. The fix saves the job id and its result in the same write as the stock change.

Sipariş servisi, kiralama süreli ve en az bir kez teslim eden bir kuyruk ve bir stok çalışanı; hepsi durum makinesi olarak yazıldı. Üç sürüm var: hatalı sürüm, düzeltme ve hiç yeniden teslim etmeyen kuyruk (doğru ama takılı). Düzeltme, iş kimliğini ve sonucunu stok değişikliğiyle aynı yazma işleminde saklar.

Walkthrough · captured from the lab belowAdım adım · aşağıdaki laboratuvardan alınmış ekranlar

One order, two stock drops, one fixTek sipariş, iki stok düşüşü, tek düzeltme

The redelivered job on its way to the stock worker Yeniden teslim edilen iş stok çalışanına giderken Two safety rules broken at 627 ms 627 ms'de çiğnenen iki güvenlik kuralı The buggy and the fixed version side by side Hatalı ve düzeltilmiş sürüm yan yana The smallest scenario that still fails Hâlâ başarısız olan en küçük senaryo

01600 ms: the worker has taken the stock for job o2 and crashed before confirming it. The lease runs out and the queue delivers the job again.600 ms: çalışan o2 işi için stoğu düşmüş ve onaylamadan çökmüş. Kiralama süresi doluyor, kuyruk işi yeniden teslim ediyor.

02627 ms: the same job is applied a second time. Stock falls by more than the orders account for, and two safety rules break at once.627 ms: aynı iş ikinci kez uygulanıyor. Stok, siparişlerin açıklayabileceğinden fazla düşüyor ve iki güvenlik kuralı birden çiğneniyor.

03Compare: the same workload and the same fault plan run against the fix. The second delivery is recognised and skipped.Karşılaştırma: aynı iş yükü ve aynı arıza planı düzeltmeye karşı çalışıyor. İkinci teslim tanınıyor ve atlanıyor.

04Shrink: the failing scenario reduced step by step to one order and one fault. It still breaks the same rules.Küçültme: başarısız senaryo adım adım tek siparişe ve tek arızaya indiriliyor. Hâlâ aynı kuralları çiğniyor.

Working demonstrationÇalışan gösterim

Watch the stock drop twice. Then watch the fix.Stoğun iki kez düşüşünü izle. Sonra düzeltmeyi izle.

Run the incident in the buggy version: j-o2 changes the stock twice and a real order is refused later. Press "Compare with fix" to run the same orders and the same crash against the fix. "Shrink" turns a failing random seed into its smallest version.

Olayı hatalı sürümde çalıştır: j-o2 stoğu iki kez değiştirir ve sonra gerçek bir sipariş reddedilir. Aynı siparişleri ve aynı çökmeyi düzeltmeye karşı çalıştırmak için "Düzeltmeyle karşılaştır"a bas. "Küçült", başarısız bir rastgele tohumu en küçük hâline indirir.

36 kB, runs entirely in this page.36 kB, tamamen bu sayfada çalışır.

ValidationDoğrulama

What was checked, and howNeyin, nasıl denetlendiği

TestsTestler · 7/7

  1. same engine and scenario give the same event log, byte for byteaynı motor ve senaryo bayt bayt aynı olay kaydını veriyor15 ms
  2. the incident: the buggy worker applies a redelivered job twice, the fix does notolay: hatalı çalışan yeniden teslim edilen işi iki kez uyguluyor, düzeltme uygulamıyor1 ms
  3. safety and progress are separate checks: a queue that never redelivers is safe but stuckdoğruluk ve ilerleme ayrı denetimler: hiç yeniden teslim etmeyen kuyruk doğru ama takılı0 ms
  4. a seeded sweep finds the injected bug and never fails the fixed versiontohumlu tarama eklenen hatayı buluyor, düzeltilmiş sürümü hiç başarısız göstermiyor585 ms
  5. timeline navigation: a snapshot plus replay equals the straight run at every point checkedzaman çizelgesi: anlık görüntü + ileri oynatma, denetlenen her noktada düz çalıştırmayla aynı14 ms
  6. shrinking keeps the failure and removes everything that is not needed for itküçültme hatayı koruyor ve ona gerekmeyen her şeyi atıyor9 ms
  7. scenario files: round trip, strict rejection of bad or oversized input, bounded runssenaryo dosyaları: gidiş-dönüş, bozuk ya da büyük girdinin katı reddi, sınırlı çalıştırma1 ms

Node v24.20.0 · run 2026-10-08 · node --test lab/tests/traceforge.test.mjsNode v24.20.0 · 2026-10-08 tarihinde çalıştırıldı · node --test lab/tests/traceforge.test.mjs

The incident in three versionsOlay, üç sürümde

VersionSürümEventsOlayLog hash, two runsKayıt özeti, iki çalıştırmaRules brokenÇiğnenen kurallarStock at the endSon stok
BuggyHatalı480b125cad7bfea7 ✓applied twice at 627 ms627 ms'de iki kez uygulandı, stock does not add up at 627 ms627 ms'de stok tutmuyorA 0
FixedDüzeltilmiş48010ceaa0842b9a ✓noneyokA 0
No redeliveryYeniden teslimsiz36128016d7145532 ✓jobs left unfinished at 951 ms951 ms'de bitmeyen iş kaldıA 4

Five orders of 2 units against a stock of 10; the worker crashes after its second commit. In the buggy version order o4 is refused because the stock was taken twice. traceforge-sim 1.0.0.10 birimlik stoğa karşı 2'şer birimlik beş sipariş; çalışan ikinci kaydından sonra çöker. Hatalı sürümde o4 siparişi, stok iki kez düştüğü için reddedilir. traceforge-sim 1.0.0.

300 random seeds300 rastgele tohum

VersionSürümFailing seedsBaşarısız tohumRuleKural
BuggyHatalı167 / 300applied twiceiki kez uygulandı, stock does not add upstok tutmuyor
FixedDüzeltilmiş0 / 300noneyok
No redeliveryYeniden teslimsiz274 / 300jobs left unfinishedbitmeyen iş kaldı

900 runs, 151,655 events in 594 ms: 255,353 events per second, Node v24.20.0, Ryzen 5 9600X.900 çalıştırma, 594 ms'de 151.655 olay: saniyede 255.353 olay, Node v24.20.0, Ryzen 5 9600X.

Shrinking a failureBir hatayı küçültmek

Seed 2: 8 orders and 8 faults → 1 order and 1 fault, in 75 runs (4 ms). It still breaks the same rules; the fix passes it.Tohum 2: 8 sipariş ve 8 arıza → 1 sipariş ve 1 arıza; 75 çalıştırmada (4 ms). Hâlâ aynı kuralları çiğniyor; düzeltme bunu geçiyor.

{
 "stock": {
  "A": 2
 },
 "workload": [
  {
   "id": "o8",
   "at": 0,
   "sku": "A",
   "qty": 1
  }
 ],
 "faults": [
  {
   "type": "crash",
   "svc": "stock",
   "point": "after-commit",
   "nth": 1,
   "downtime": 0
  }
 ]
}

Decision notesKarar notları

Constraint, method, resultKısıt, yöntem, sonuç

Randomness keyed by messageMesaja bağlı rastgelelik

ConstraintKısıt
A seeded generator draws numbers in order: remove one order while shrinking and every later delay shifts, so the bug can vanish.Tohumlu bir üreteç sayıları sırayla çeker: küçültürken bir siparişi kaldırırsan sonraki bütün gecikmeler kayar ve hata kaybolabilir.
MethodYöntem
Each random choice is a hash of the seed and a stable key (link, message, job, attempt), so the rest of the run stays where it was.Her rastgele seçim, tohumun ve kararlı bir anahtarın (bağlantı, mesaj, iş, deneme) özetidir; çalıştırmanın geri kalanı yerinde kalır.
ResultSonuç
Removing orders while shrinking leaves the rest of the run in place: seed 2 shrank from 8 orders and 8 faults to 1 and 1 and still failed the same way.Küçültürken sipariş çıkarmak çalıştırmanın geri kalanını yerinden oynatmıyor: tohum 2, 8 sipariş ve 8 arızadan 1 ve 1'e indi ve hâlâ aynı şekilde başarısız oldu.

Crash at a named pointBelirli bir noktada çökme

ConstraintKısıt
A crash scheduled at a time almost never hits the gap between commit and acknowledgement.Belirli bir zamana planlanan çökme, kayıt ile onay arasındaki boşluğa neredeyse hiç denk gelmez.
MethodYöntem
A fault names a point in the worker (before commit, after commit, after ack) and which time it is reached.Bir arıza, çalışandaki bir noktayı (kayıttan önce, kayıttan sonra, onaydan sonra) ve oraya kaçıncı varışta tetikleneceğini belirtir.
ResultSonuç
The incident's crash lands between commit and acknowledgement on every run: 48 events and the same log hash each time.Olaydaki çökme her çalıştırmada kayıt ile onay arasına düşüyor: her seferinde 48 olay ve aynı kayıt özeti.

Safety and progress, apartDoğruluk ve ilerleme ayrı

ConstraintKısıt
A queue that never redelivers never applies a job twice. It simply never finishes.Hiç yeniden teslim etmeyen bir kuyruk, bir işi asla iki kez uygulamaz. Sadece hiç bitmez.
MethodYöntem
Safety rules run after every event. The progress rule runs once the last fault is over plus four seconds of quiet.Doğruluk kuralları her olaydan sonra çalışır. İlerleme kuralı, son arıza bittikten ve dört saniye sessizlikten sonra çalışır.
ResultSonuç
Over 300 seeds, the version without redelivery never broke a safety rule and stalled on 274; the progress rule caught every one.300 tohumda yeniden teslimsiz sürüm hiçbir güvenlik kuralını çiğnemedi, 274'ünde takıldı; ilerleme kuralı hepsini yakaladı.

A snapshot every 25 eventsHer 25 olayda bir anlık görüntü

ConstraintKısıt
Scrubbing back through a timeline should not replay the whole run from zero.Zaman çizelgesinde geri gitmek, bütün çalıştırmayı sıfırdan oynatmamalı.
MethodYöntem
The nearest snapshot is restored and at most 25 events are replayed; playing forward reuses the replaying copy, one step per event.En yakın anlık görüntü geri yüklenir, en fazla 25 olay ileri oynatılır; ileri oynatma aynı kopyayı kullanır, her olay için bir adım.
ResultSonuç
At every point checked, a snapshot plus replay gave exactly the state of a straight run.Denetlenen her noktada anlık görüntü ve ileri oynatma, düz çalıştırmanın durumunu birebir verdi.

Shrink to the same failureAynı hataya küçült

ConstraintKısıt
A smaller scenario that fails for a different reason is not a reproduction.Başka bir nedenle başarısız olan daha küçük bir senaryo, hatanın yeniden üretimi sayılmaz.
MethodYöntem
Delta debugging over orders and faults, then simpler values; a candidate is kept only if it breaks one of the original rules.Siparişler ve arızalar üzerinde delta hata ayıklama, ardından daha sade değerler; aday, yalnızca ilk kurallardan birini çiğnerse tutulur.
ResultSonuç
Seed 2: from 8 orders and 8 faults to 1 and 1 in 75 runs and 4 ms, still breaking the same rules; the fix passes it.Tohum 2: 75 çalıştırmada ve 4 ms'de 8 sipariş ve 8 arızadan 1 ve 1'e; hâlâ aynı kuralları çiğniyor, düzeltme geçiyor.

One write for the change and its idDeğişiklik ve kimliği için tek yazma

ConstraintKısıt
The queue delivers at least once; it cannot know whether a silent worker had already applied the job.Kuyruk en az bir kez teslim eder; sessizleşen bir çalışanın işi uygulayıp uygulamadığını bilemez.
MethodYöntem
The worker stores the job id and its result together with the stock change. A redelivered job finds its id, gets the stored answer and leaves the stock alone.Çalışan, iş kimliğini ve sonucunu stok değişikliğiyle birlikte saklar. Yeniden teslim edilen iş kimliğini bulur, saklanan cevabı alır ve stoğa dokunmaz.
ResultSonuç
Same seeds, same faults: the buggy worker fails 167 of 300 runs, the fix none.Aynı tohumlar, aynı arızalar: hatalı çalışan 300 çalıştırmanın 167'sinde başarısız, düzeltme hiçbirinde.

Built on, and what I addedÜzerine kurulduğu fikirler ve benim eklediklerim

Ideas it builds onDayandığı fikirler

  • FoundationDBTesting a distributed system inside a deterministic simulation with injected network and machine faults.Dağıtık bir sistemi, enjekte edilen ağ ve makine arızalarıyla deterministik bir simülasyon içinde test etmek.
  • TigerBeetleChecking safety and liveness as separate goals, with faults that stop so progress can be judged.Doğruluğu ve ilerlemeyi ayrı hedefler olarak denetlemek; arızalar durur ki ilerleme değerlendirilebilsin.
  • No runtime dependencyÇalışma bağımlılığı yokThe page code is written from scratch: no library code ships with it.Sayfa kodu sıfırdan yazıldı: yanında hiçbir kütüphane kodu gelmiyor.

Added in TRACEFORGETRACEFORGE'ta eklenenler

  • SimulatorSimülatörVirtual clock, stable event order, keyed randomness, network faults, crash points, snapshots.Sanal saat, kararlı olay sırası, anahtarlı rastgelelik, ağ arızaları, çökme noktaları, anlık görüntüler.
  • The systemSistemOrders, a leasing queue with at-least-once delivery, a stock worker in three versions.Sipariş servisi, en az bir kez teslim eden kiralamalı kuyruk, üç sürümlü stok çalışanı.
  • Checks and toolsDenetimler ve araçlarThree safety rules, one progress rule, seed search, shrinker, scenario file format.Üç doğruluk kuralı, bir ilerleme kuralı, tohum arama, küçültücü, senaryo dosyası biçimi.
  • InterfaceArayüzLive service view, scrubbable timeline, event log, state inspector, side-by-side comparison.Canlı servis görünümü, kaydırılabilir zaman çizelgesi, olay kaydı, durum incelemesi, yan yana karşılaştırma.