engines: [postgres, mysql, mssql, mongo]
scenarios:
- id: batch_crash_after_source_read
what: "crash after reading the source, before any write → state stays completely clean"
postgres: { test: crash_after_source_read_leaves_state_completely_clean }
mysql: { test: mysql_crash_after_source_read_leaves_state_completely_clean }
mssql: { test: mssql_crash_after_source_read_leaves_state_completely_clean }
mongo: { na: "after_source_read fires only in src/pipeline/single.rs; the Mongo batch export runs the keyset path (mongo_parallel), whose crash boundaries are the shared pipeline::commit hooks (after_file_write / after_manifest_update, tested below) — it has no single.rs source-read boundary" }
- id: batch_crash_after_file_write
what: "crash after the part file, before the manifest → file present, no manifest/cursor, recoverable"
postgres: { test: crash_after_file_write_leaves_file_but_no_manifest_or_cursor }
mysql: { test: mysql_crash_after_file_write_leaves_file_but_no_manifest_or_cursor }
mssql: { test: mssql_crash_after_file_write_leaves_file_but_no_manifest_or_cursor }
mongo: { test: mongo_crash_after_file_write_recovers_without_loss }
- id: batch_crash_after_manifest_update
what: "crash after the manifest, before the cursor → file+manifest present, no cursor, recoverable"
postgres: { test: crash_after_manifest_update_leaves_file_and_manifest_but_no_cursor }
mysql: { test: mysql_crash_after_manifest_update_leaves_file_and_manifest_but_no_cursor }
mssql: { test: mssql_crash_after_manifest_update_leaves_file_and_manifest_but_no_cursor }
mongo: { test: mongo_crash_after_manifest_update_recovers_without_loss }
- id: batch_crash_after_cursor_commit
what: "crash after the cursor commit → fully recoverable with complete state"
postgres: { test: crash_after_cursor_commit_is_recoverable_with_full_state }
mysql: { test: mysql_crash_after_cursor_commit_is_recoverable_with_full_state }
mssql: { test: mssql_crash_after_cursor_commit_is_recoverable_with_full_state }
mongo: { na: "Mongo's keyset full export has no cursor-commit boundary of this shape (documented in live_mongo_crash_recovery.rs) — the file/manifest boundaries above cover it" }
- id: chunked_crash_after_chunk_complete
what: "crash after a chunk completes → resume finishes the export, no gap"
postgres: { test: chunked_crash_after_first_chunk_complete_resume_finishes_export }
mysql: { test: mysql_chunked_crash_after_first_chunk_complete_resume_finishes_export }
mssql: { test: mssql_chunked_crash_after_first_chunk_complete_resume_finishes_export }
mongo: { na: "Mongo has no SQL-style chunked path — it uses keyset/parallel (covered by the batch + keyset rows)" }
- id: chunked_crash_after_chunk_file_atleastonce
what: "crash after a chunk file, before its commit → resume re-runs the chunk (at-least-once, no loss)"
postgres: { test: chunked_crash_after_chunk_file_before_commit_resume_reruns_chunk_atleastonce }
mysql: { test: mysql_chunked_crash_after_chunk_file_before_commit_resume_reruns_chunk_atleastonce }
mssql: { test: mssql_chunked_crash_after_chunk_file_before_commit_resume_reruns_chunk_atleastonce }
mongo: { na: "no SQL-style chunked path on Mongo" }
- id: parallel_chunked_crash_recovery
what: "crash mid parallel-chunked run → resume finishes with no duplicates"
postgres: { test: parallel_chunked_crash_after_chunk_complete_resume_finishes_with_no_duplicates }
mysql: { test: mysql_parallel_chunked_crash_after_chunk_complete_resume_finishes_with_no_duplicates }
mssql: { test: mssql_parallel_chunked_crash_after_chunk_complete_resume_finishes_with_no_duplicates }
mongo: { na: "no SQL-style chunked path on Mongo" }
- id: part_name_no_clobber_batch
what: "rapid consecutive runs into the same prefix don't clobber — millisecond part stamp (single.rs), proven under sub-second incremental deltas"
postgres: { test: roast_rapid_incremental_runs_into_same_prefix_must_not_clobber_prior_parts }
mysql: { test: mysql_full_mode_repeated_run_accumulates_manifest_entries }
mssql: { test: mssql_full_mode_repeated_run_accumulates_manifest_entries }
mongo: { test: mongo_batch_two_rapid_runs_into_same_prefix_do_not_clobber }
- id: part_name_no_clobber_keyset_checkpoint
what: "keyset/chunk-checkpoint resume: second run captures only new keys, prior parts survive (ms-stamped, run-unique)"
postgres: { test: keyset_checkpoint_resume_pg_second_run_captures_only_new_keys }
mysql: { test: keyset_checkpoint_resume_second_run_captures_only_new_keys }
mssql: { test: keyset_checkpoint_resume_mssql_second_run_captures_only_new_keys }
mongo: { test: mongo_batch_resume_reads_only_new_since_last_run }
- id: sigkill_commit_window
what: "real SIGKILL in the commit window → temp+rename leaves no half-committed file"
postgres: { test: sigkill_in_commit_window_leaves_no_committed_file }
mysql: { na: "the commit seam (temp file + atomic rename, src/destination/local.rs + pipeline/commit.rs) is engine-agnostic — pinned once on PostgreSQL" }
mssql: { na: "same engine-agnostic commit seam; pinned once on PostgreSQL" }
mongo: { na: "same engine-agnostic commit seam; pinned once on PostgreSQL" }
- id: destination_outage_loud
what: "destination outage (bucket down / transient) → fails loud, then recovers on retry without loss"
postgres: { test: s3_export_recovers_when_destination_comes_back_after_transient_outage }
mysql: { na: "the destination write seam (destination::create_destination / commit::write_part_file) is engine-agnostic — pinned once on PostgreSQL" }
mssql: { na: "same engine-agnostic destination seam; pinned once on PostgreSQL" }
mongo: { na: "same engine-agnostic destination seam; pinned once on PostgreSQL" }
- id: state_store_write_fail_loud
what: "an unwritable state store (SQLite rivet_state.db) fails the run LOUD, never a silent success that skips persisting the cursor"
postgres: { test: incremental_export_with_unwritable_state_db_fails_loud_not_silent }
mysql: { na: "the state store is engine-agnostic SQLite (src/state) — pinned once on PostgreSQL" }
mssql: { na: "same engine-agnostic SQLite state store; pinned once on PostgreSQL" }
mongo: { na: "same engine-agnostic SQLite state store; pinned once on PostgreSQL" }