Skip to content

fix(backup): attach reconnecting restore subscriptions to the in-flight job instead of re-running the restore - #4968

Open
Siumauricio wants to merge 1 commit into
canaryfrom
fix/restore-dedupe-inflight
Open

fix(backup): attach reconnecting restore subscriptions to the in-flight job instead of re-running the restore#4968
Siumauricio wants to merge 1 commit into
canaryfrom
fix/restore-dedupe-inflight

Conversation

@Siumauricio

@Siumauricio Siumauricio commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Closes #3388

restoreBackupWithLogs starts the restore inside the subscription handler, and the websocket client (createWSClient with retryDelayMs: 3000) re-subscribes automatically whenever the connection drops. For large backups the socket sits idle for minutes (proxies like Cloudflare cut idle connections), so every reconnect re-invoked the handler and launched another full pg_restore/mariadb run — the concurrent duplicate restores reported in the issue.

Restores are now tracked in an in-flight job map keyed by backup type, service, database name, backup file and destination. The first subscription starts the restore; any re-subscription with the same key attaches to the running job and replays its log buffer instead of starting a new process. Jobs are evicted 5s after completion so a genuine re-run later starts fresh.

Greptile Summary

The PR prevents reconnecting WebSocket subscriptions from launching duplicate database restores by retaining in-flight jobs and replaying their logs.

  • Adds a process-local restore-job map.
  • Keys jobs by restore target and backup details.
  • Retains completed jobs for five seconds before eviction.

Confidence Score: 4/5

The PR appears safe to merge, with a non-blocking key-serialization edge case that can conflate distinct restore requests containing pipe characters.

The reconnect deduplication works in the supported single-process server architecture, but the unescaped delimiter-based key is ambiguous for two unrestricted input fields.

Files Needing Attention: apps/dokploy/server/api/routers/backup.ts

Reviews (1): Last reviewed commit: "fix(backup): attach reconnecting restore..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used:

@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. bug Something isn't working labels Aug 4, 2026
Comment on lines +592 to +599
const jobKey = [
input.backupType,
input.databaseId,
input.databaseType,
input.databaseName,
input.backupFile,
input.destinationId,
].join("|");

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.

P2 Ambiguous restore job keys

Because databaseName and backupFile accept pipe characters, distinct restore requests can produce the same delimiter-joined key; the second request then skips its own restore and replays the first job's logs.

Suggested change
const jobKey = [
input.backupType,
input.databaseId,
input.databaseType,
input.databaseName,
input.backupFile,
input.destinationId,
].join("|");
const jobKey = JSON.stringify([
input.backupType,
input.databaseId,
input.databaseType,
input.databaseName,
input.backupFile,
input.destinationId,
]);

Knowledge Base Used: Backups and Schedules

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: PostgreSQL restore executes multiple times for large backups

1 participant