Skip to content

delete_transaction_logs_before with a table on RocksDB now returns an error instead of deleting the entire database's transaction log - #2064

Merged
cb1kenobi merged 1 commit into
mainfrom
fix/2049-reject-table-scoped-rocksdb-log-purge
Aug 3, 2026
Merged

delete_transaction_logs_before with a table on RocksDB now returns an error instead of deleting the entire database's transaction log#2064
cb1kenobi merged 1 commit into
mainfrom
fix/2049-reject-table-scoped-rocksdb-log-purge

Conversation

@cb1kenobi

@cb1kenobi cb1kenobi commented Aug 3, 2026

Copy link
Copy Markdown
Member

Fixes #2049 (RocksDB: table-scoped delete_transaction_logs_before destroys the entire database's transaction log).

What changed

On RocksDB, all tables in a database share one transaction log, and rocksdb-js's purgeLogs() has no table dimension (whole-file purges, logs partitioned per origin node). The bridge previously ignored a table scope and purged the whole database's log — reporting success. Now, in ResourceBridge.deleteTransactionLogsBefore:

  • table naming a RocksDB table → 400, with a message pointing at the supported database-wide form (delete_transaction_logs_before with only database and timestamp).
  • table naming a nonexistent table → 404 on either engine. The guard sits before the engine branch, so this is a behavior change on LMDB too: previously a typo'd name fell into the no-table branch — the whole-database purge on RocksDB, a silent entries_deleted: 0 no-op on LMDB.
  • The table checks use presence (!= null), not truthiness, in both the guard and getTable(), so a table named "0" addressed numerically stays table-scoped instead of widening to a database purge (found by cross-model review).
  • No table → database-wide purge, unchanged. LMDB table-scoped deleteHistory → unchanged.

Deliberate design consequence — reviewer attention here

The deprecated delete_audit_logs_before op requires table and funnels into the same bridge method, so on RocksDB it now always errors with the migration message. There is no way to honor its per-table contract on RocksDB without the silent widening this PR removes. Three integration tests that previously asserted job success for table-scoped calls were updated to assert the rejection (transaction-logs.test.mjs, transactions.test.mjs, terminology.test.mjs — the last now verifies database-param resolution via the database name echoed in the error).

Not addressed (same silent-ignore shape, but inert rather than destructive): cleanup_deleted_records is still silently ignored on the RocksDB no-table path — flagged in #2049 as a decide-alongside; can be a follow-up.

Testing

  • New unit tests (unitTests/resources/deleteTransactionLogsBeforeRocks.test.js, 5 passing): 400 on table-scoped, 404 on missing table/database, falsy-table-name regression, database-wide purge still succeeds. Skipped under HARPER_STORAGE_ENGINE=lmdb.
  • test:unit:resources full run green (1365 passing); the three touched integration files green (75 passing).
  • test:integration:all full run: 1624/1645 passing; the 3 failures (shutdown-drain-e2e.test.ts, rolling-restart.test.ts) reproduce identically on origin/main — pre-existing local-environment failures, unrelated to this change.
  • Local test:unit:main hangs in unitTests/components/applicationSpawn.test.js on this machine with and without this change (verified A/B against main's ResourceBridge.ts) — known local-environment issue; relying on CI for that suite.

Docs

Companion docs PR: HarperFast/documentation#618 — documents database-wide-only deletion on RocksDB and the deprecated op's behavior.

Review

Cross-model review (thorough): author Claude (Fable 5); coverage: Codex ✓ (two findings — the falsy-table-name blocker and the dead-end error remediation — both fixed, then a final-artifact re-check ✓); Gemini ✗ (agy failing locally with a model/location config error; no Gemini coverage).

🤖 Generated with Claude Code

…stead of purging the whole database's log

On RocksDB all tables in a database share one transaction log with no
per-table purge granularity, so a table-scoped request silently purged
every sibling table's history; a nonexistent (e.g. typo'd) table name
fell through to the same whole-database purge. Table-scoped requests on
RocksDB now fail with a 400 naming the database-wide alternative, and a
nonexistent table 404s before any purge. The table/no-table checks use
presence (!= null) rather than truthiness so a table named "0" addressed
numerically stays table-scoped.

Consequence: the deprecated delete_audit_logs_before op requires table,
so on RocksDB it now always errors with the migration message.

Fixes #2049

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request prevents table-scoped transaction log purges on RocksDB, which previously resulted in silent database-wide purges because RocksDB tables share a single transaction log. It introduces a 400 Bad Request error for table-scoped purge requests on RocksDB, returns a 404 Not Found error for nonexistent tables, and ensures that falsy table names (like '0') are correctly treated as table-scoped. Additionally, comprehensive integration and unit tests have been added to verify these behaviors. There are no review comments, so I have no further feedback to provide.

@claude

claude Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found.

@cb1kenobi
cb1kenobi marked this pull request as ready for review August 3, 2026 20:09
@cb1kenobi cb1kenobi changed the title delete_transaction_logs_before with a table on RocksDB now returns an error instead of deleting the entire database's transaction log delete_transaction_logs_before with a table on RocksDB now returns an error instead of deleting the entire database's transaction log Aug 3, 2026

@kriszyp kriszyp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!
🤖 Reviewed with Codex

@cb1kenobi
cb1kenobi merged commit dc8fa30 into main Aug 3, 2026
69 of 71 checks passed
@cb1kenobi
cb1kenobi deleted the fix/2049-reject-table-scoped-rocksdb-log-purge branch August 3, 2026 22:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RocksDB: table-scoped delete_transaction_logs_before destroys the entire database's transaction log

2 participants