Skip to content

Add RocksDB managed backup and restore operations#1831

Draft
cb1kenobi wants to merge 7 commits into
mainfrom
rocksdb-backup-operations
Draft

Add RocksDB managed backup and restore operations#1831
cb1kenobi wants to merge 7 commits into
mainfrom
rocksdb-backup-operations

Conversation

@cb1kenobi

@cb1kenobi cb1kenobi commented Jul 16, 2026

Copy link
Copy Markdown
Member

Summary

Adds managed backup/restore for RocksDB databases as Operations API operations — create_backup, list_backups, verify_backup, delete_backup, purge_backups, restore_backup — plus RocksDB support for get_backup (streams a gzipped-by-default tar; gzip=false for plain tar; works against a remote target=). Each is also runnable from the CLI under its operation name, and offline against a stopped server. Managed backups are an incremental, checksum-verified, server-side repository under storage.backupPath (default <rootPath>/backup), one subdirectory per database, capturing the transaction log alongside the data.

Purpose

Give RocksDB first-class server-managed backup/restore (LMDB already had volume-snapshot workflows), without stopping the server for the common case.

Where to focus review

  • Restore safety invariantdataLayer/rocksdbBackup.ts (restoreBackup) + dataLayer/restoreMarker.ts. Online restore writes an fsynced marker + takes a per-db flock, closes the DB across all worker threads, verifies process-wide closure via registryStatus(), then purges + rewrites. A component-held DB (and always system) can't be closed → 409 pointing at offline restore. Worth checking the close→verify→purge ordering and the marker/lock crash-recovery states (in-progress / incomplete / clear).
  • Offline restore lock proberestoreBackupOffline. The offline path is chosen on a PID heuristic, but the PID file is briefly absent during harper restart, so it now probes RocksDB's own lock (RocksDatabase.open) before purging — a lock error aborts, a corrupt/half-restored dir still proceeds (recovery).
  • Job-worker handle releaseserver/jobs/jobProcess.ts + resources/databases.ts (closeDatabase/closeLoadedDatabases, new). Job workers close their process-global RocksDB handles on exit or the closure check can never pass; system is intentionally left open; tableless databases are handled explicitly.
  • CLI transport refactorbin/cliOperations.ts. Extracted target + auth resolution into resolveRequestOptions, now shared by cliOperations and the streaming get_backup download. cliOperations behavior should be unchanged (bin suite green).

Cross-model review (codex + Gemini)

Fixed from review: offline-restore lock probe, CLI content-disposition path traversal, jobProcess cleanup when updateJob rejects, marker-removal fsync, tableless-DB handle leak. Deferred (not blocking):

Docs

Companion docs PR: HarperFast/documentation#590.

Generated by an LLM (Claude Opus 4.8, 1M context).

🤖 Generated with Claude Code

cb1kenobi and others added 2 commits July 16, 2026 01:49
New operations, also runnable from the CLI under their operation name (and offline
against a stopped server): create_backup, list_backups, verify_backup, delete_backup,
purge_backups, restore_backup — plus RocksDB support for get_backup, which streams a
gzipped-by-default tar (gzip=false for a plain tar) and works against a remote target.
Managed backups are an incremental, checksum-verified, server-side repository under
storage.backupPath (default <rootPath>/backup), one subdirectory per database, and
capture the transaction log alongside the data.

Restore closes the database across all worker threads, verifies process-wide closure
(registryStatus), then purges and rewrites the directory — guarded by a per-database
flock plus an fsynced marker so an interrupted restore is detected and not loaded on
restart. A database a loaded component holds open, and always the system database,
cannot be restored online (409 pointing at running it offline with the server stopped);
offline restore additionally probes RocksDB's own lock before purging. Job workers
release their RocksDB handles on exit so the closure check can pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gemini-code-assist[bot]

This comment was marked as resolved.

Comment thread bin/backup.ts
@claude

This comment has been minimized.

…wrapping

- bin/backup.ts: load `.env` at the top of runBackupCommand so useOperationApi /
  resolveRequestOptions see HARPER_CLI_TARGET/CLI_TARGET — otherwise a .env-configured
  remote target was invisible and a destructive backup op could run against local.
- rocksdbBackup.ts: restore into an empty/tableless database no longer fails with
  "no tables to back up" — guard requireRocksRootStore on the database actually having
  tables (validate + online restore paths).
- restoreMarker.ts: directory fsync is now best-effort via a shared fsyncDir helper that
  ignores EPERM/EISDIR/ENOTSUP, so beginRestore/completeRestore work on Windows.
- rocksdbBackup.ts: wrap restore-failure errors in a new Error({cause}) instead of
  mutating error.message (a frozen/library error's message can be non-writable in strict mode).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cb1kenobi added a commit to HarperFast/documentation that referenced this pull request Jul 16, 2026
Companion to HarperFast/harper#1831.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cb1kenobi and others added 3 commits July 16, 2026 09:50
Backup operation responses exposed rocksdb-js's camelCase BackupInfo fields
(backupId, numberFiles) directly, inconsistent with the snake_case Operations API
convention and these operations' own snake_case inputs. Map at the API boundary:
list_backups returns { backup_id, timestamp, size, file_count } (dropping the internal
appMetadata), and create/verify/restore return backup_id (offline restore: restored_to).
listBackupsInDir stays camelCase for internal use; a new listBackupsOffline maps the CLI
offline list to match. Tests updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cb1kenobi added a commit to HarperFast/documentation that referenced this pull request Jul 16, 2026
…_count)

Matches HarperFast/harper#1831, which now returns snake_case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant