Exercise 2: Two Lost Writes, and Why a Post-Crash Flush Can't Recover Them — Possible Solution ==================================================================== SETUP: TWO WRITES, NO FLUSH ------------------------------ wb.set('PROD-1', 100) wb.set('PROD-2', 200) cache has both values: {'PROD-1': 100, 'PROD-2': 200} database BEFORE any flush: {} Both values live only in cache.cache and pending_writes - the database is still completely empty, exactly matching this chapter's own single- write finding, now confirmed for two independent keys at once. SIMULATING THE CRASH ------------------------------ A real crash doesn't just skip calling flush() - it destroys whatever lived only in the process's own memory, which is exactly where pending_writes lives. Simulated here by replacing wb.pending_writes with a fresh empty dict, discarding the two queued writes: database after simulated crash (pending_writes lost): {} VERIFYING A POST-CRASH FLUSH CANNOT RECOVER THE DATA ------------------------------ database after calling flush() post-crash (should be UNCHANGED - nothing to flush): {} both writes are permanently lost: True Calling flush() after the crash iterates over pending_writes - which is now empty, because that's precisely what crashed. flush() faithfully does its job (write everything currently queued to the database), but there's nothing left queued to write. The database stays at {} even after "recovery," because flush() was never given anything to recover FROM. WHY THIS IS A GENUINELY DIFFERENT FINDING FROM THIS CHAPTER'S OWN ------------------------------ This chapter's own text showed a write becoming permanently lost the moment a crash happens before flush(). This exercise adds a specific, important clarification: calling flush() AFTER a crash isn't a safety net - it only replays whatever is still sitting in memory at the moment it runs, and a crash by definition wipes exactly that memory. There is no version of "just call flush() again later" that fixes data that was never durably stored anywhere outside the crashed process to begin with. WHY THIS WORKS AS AN ANSWER ------------------------------ Two independent writes are used to confirm the loss isn't specific to a single key, the crash is simulated by actually discarding pending_writes (not just skipping a flush() call), and the post-crash flush() is explicitly tested and shown to be powerless - directly addressing the natural follow-up question this chapter's own original finding leaves open.