Day 38 — Make reconciliation and rollback conditional on the state actually observed
Learning task. Explain how an otherwise correct candidate becomes unsafe after a concurrent update. The version captured with a scoped read is a precondition, not a timeless property. A real approved transaction must compare the expected version and perform its mutation atomically; checking in a script and writing later leaves a race. If another accepted transaction changes the state, stop and rebuild the reconciliation argument. Do not overwrite the new value simply because an earlier plan was approved.
At the 10:20 planning boundary, C26's snapshot/current/target comparison and C28's isolated pass support a proposed S42 correction. They do not supply the complete current production version or an actual production mutation receipt. Preserve the bounded pre-change state and source version, confirm which business changes must survive, select the owner-approved application path and bind the proposal to that version. If the application cannot enforce the required invariant, return the design to the owner rather than silently using a direct database path that bypasses audit and dependencies.
Offline laboratory W8-CAS — stale write and stale rollback controls. Python 3 standard library, pure in-memory records with invented version 7/8/9; these are not CTN version observations. This sequential simulator shows conditional state transitions. It does not implement atomicity against a real database, authenticate the Boolean permission or authorize a live correction. Preserve its before-state and predict seven lines:
from copy import deepcopy
def cas8(record, expected_version, values, permitted):
if permitted is not True:
return "STOP_NO_AUTHORITY", deepcopy(record)
if record["version"] != expected_version:
return "STOP_STALE_VERSION", deepcopy(record)
return "SIM_APPLIED", {"version": expected_version + 1, "values": dict(values)}
before8 = {"version": 7, "values": {"S40": "reserved", "S41": "reserved", "S42": "unavailable"}}
target8 = {**before8["values"], "S42": "open"}
print("W8 NO_AUTH", cas8(before8, 7, target8, False)[0])
print("W8 STALE", cas8({**before8, "version": 8}, 7, target8, True)[0])
status8, applied8 = cas8(before8, 7, target8, True)
print("W8 APPLY", status8, "v" + str(applied8["version"]))
print("W8 preserved slots", ",".join(k for k in ("S40", "S41") if applied8["values"][k] == before8["values"][k]))
status8, reverted8 = cas8(applied8, 8, before8["values"], True)
print("W8 ROLLBACK", status8, "v" + str(reverted8["version"]), "S42=" + reverted8["values"]["S42"])
print("W8 LATE_ROLLBACK", cas8({**applied8, "version": 9}, 8, before8["values"], True)[0])
print("W8 baseline", "v" + str(before8["version"]), "S42=" + before8["values"]["S42"])
Exact transcript reproduced during publication validation:
W8 NO_AUTH STOP_NO_AUTHORITY
W8 STALE STOP_STALE_VERSION
W8 APPLY SIM_APPLIED v8
W8 preserved slots S40,S41
W8 ROLLBACK SIM_APPLIED v9 S42=unavailable
W8 LATE_ROLLBACK STOP_STALE_VERSION
W8 baseline v7 S42=unavailable
Worked interpretation. A successful invented correction preserves S40/S41. A stale request and an unapproved request return unchanged copies. Reversal also needs a version precondition: after another accepted update, replaying an old before-state could destroy later work. The simulator creates a new version on reversal rather than pretending version 7 became current again. Its preserved baseline remains unchanged. However, reversing to that baseline makes S42 unavailable again; rollback is not synonymous with acceptable service. The decision owner must weigh the failed-candidate risk, renewed business harm and permitted next recovery path.
Contrast and limits. “The rollback file is intact, so replay it after any error” ignores intervening valid updates, configuration versus business-state differences and irreversible external effects. A corrected design checks source/version, scope, trigger, owner, transaction boundary, relevant audit and post-action service. The toy cas8 would trust arbitrary supplied values and has no row authorization, real locking, cross-record invariants or event delivery. Its success label verifies only the simulated transition; review those omitted controls before any operational implementation.
Practice. Complete EX038 with §8.3/§8.11's original differences, W8-CAS's transcript, one stale-candidate stop rule and one stale-rollback stop rule. Compare the worked answer. No production correction has occurred at this lesson's checkpoint.
Previous: Day 37 · Week 8 index · Course index · Next: Day 39.
Exercise for this lesson
EX038 — Value-diff fixture. Objective: preserve valid business changes and reject stale correction or rollback. Inputs: C26/C28, §§8.3/8.11 and Day 38 W8-CAS; no production result yet. Reproduce original differences/mismatch lists and W8-CAS's seven lines. Give the proposed current-version/target/source/authority/transaction/rollback contract and a stop rule for both stale write and stale reversal. Explain why toy version 7/8/9 is not CTN metadata and why a successful reversal can restore an unavailable S42 value. Rubric: 0 = fixture authorizes a live write or stale overwrite; 1 = correct differences but missing concurrency, rollback or environment limit; 2 = exact outputs and a falsifiable owner-governed version/rollback plan preserving S40/S41. Worked answer.