Skip to content

fix(backup): make EasyDash backup callback flow consistent - #481

Open
mrrobot47 wants to merge 3 commits into
EasyEngine:developfrom
mrrobot47:fix/backup-dash-callback-consistency
Open

mrrobot47 wants to merge 3 commits into
EasyEngine:developfrom
mrrobot47:fix/backup-dash-callback-consistency

Conversation

@mrrobot47

@mrrobot47 mrrobot47 commented Jun 29, 2026 •

Copy link
Copy Markdown
Member

Summary

Makes the EasyDash (--dash-auth) backup callback flow consistent, so the command's exit status, the console message, and the callback EasyDash receives all agree with what actually happened.

Bugs fixed

  1. False success after rollback. When the upload succeeded but the EasyDash success callback failed, rollback_failed_backup() deleted the just-uploaded backup, yet the command still printed EE::success('Backup created successfully.') and exited 0. It now captures the error, rolls back, and EE::errors — accurate non-zero exit + message.
  2. Suppressed failure callback. dash_backup_completed was set true before the success callback, so a failed callback also suppressed the shutdown failure callback → EasyDash was told neither success nor failure. It is now set only after a confirmed success callback (and on the non-dash path), so the failure callback fires.
  3. At-most-one terminal callback. New dash_callback_sent guard, set at the real send sites and checked by the shutdown handler — at most one terminal callback (success XOR failure) on every EE::error/exit path. A PHP fatal (E_ERROR) still sends none: EE_Site_Command's shutdown handler exits from rollback() before the dash handler runs (pre-existing, tracked separately).
  4. Orphan signal on purge failure. If the rollback rclone purge also fails (the orphan survives on remote), EasyDash now receives the accurate "manually delete <path>" message (code 4003) instead of the optimistic "rolled back" one — capture_error is first-wins, so the purge-failure branch force-overwrites it.

Also: the new callback-failure uses code 4004 (avoids colliding with the existing 4002 "Database backup failed"); the rollback-success notice is demoted EE::success→EE::log (it always precedes a terminal error). The global backup lock is released before the rollback and the failure callback, so an EasyDash outage (callback retries sleep up to 3×300 s) no longer holds every other queued backup on the server behind this one.

Verification

Against a stub EasyDash endpoint: callback 200 → exit 0, one success callback; success callback 400 → the upload is purged, exit 1, one failure callback with 4004; callback 400 plus a failing purge → exit 1, one failure callback with 4003 and the "manually delete <path>" message; upload failure → one 4001; disabled site → one 1003; no --dash-auth → no callbacks, exit 0. The global lock is free while the failure callback is in flight.

Tested on Ubuntu 26.04 with EasyEngine 4.12.0, on a local rclone remote and on a real rclone remote (the callback-400 case purges only the new upload; earlier backups are untouched).

The --dash-auth backup path could report success even when no backup
remained, and could leave EasyDash with neither a success nor a failure
callback.

- Defer dash_backup_completed = true until after a confirmed success
  callback so the shutdown handler still fires the failure callback when
  the success callback fails and the upload is rolled back.
- On success-callback failure, capture_error + EE::error after rollback
  so the exit code and message reflect that no backup remains, instead of
  falling through to EE::success.
- Add a dash_callback_sent guard set at the actual send sites and checked
  by the shutdown handler so exactly one terminal callback (success XOR
  failure) is ever emitted.
- Surface a failed rollback purge via capture_error + EE::error so the
  orphaned-remote-backup state propagates to the exit code and failure
  callback rather than being swallowed by a warning.
…load

Review follow-up to the dash-callback consistency fix.

- Give the callback-failure rollback its own error_code 4004; 4002 was
  already in use for ERROR_TYPE_DATABASE ("Database backup failed"), and
  error_code is shipped to EasyDash as a machine-readable field.
- When the rollback rclone purge also fails, force-overwrite the captured
  dash error before re-capturing so the accurate FILESYSTEM 4003
  "manually delete <path>" message wins over the caller's first-wins
  optimistic "rolled back" message; otherwise EasyDash was told the
  inverse of reality (rolled back) and never received the manual path.
- Demote the rollback-success notice from EE::success to EE::log since it
  always precedes a terminal EE::error.

Copilot AI 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.

Pull request overview

This PR aligns EasyDash (--dash-auth) backup outcomes so the CLI exit status and console output match what EasyDash is told via callbacks, especially around callback failures and rollback behavior.

Changes:

  • Delays marking dash_backup_completed until after a confirmed EasyDash success callback, ensuring the shutdown failure callback is not accidentally suppressed.
  • Introduces dash_callback_sent as a guard so exactly one terminal callback (success or failure) is emitted.
  • Improves rollback error reporting so a rollback purge failure reports an accurate “manual delete” message/code to EasyDash and avoids misleading success logging during an overall failure.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…lback

The callback-failure path now exits via EE::error, so the explicit lock release is skipped and the global backup lock stays held through the shutdown failure callback, which can retry for up to 15 minutes when EasyDash is unreachable. Release it before the rollback so queued backups are not delayed further.
mrrobot47 added a commit to mrrobot47/site-command that referenced this pull request Sep 24, 2026
3003 and 4003 are already taken by EasyEngine#482 (site app directory not found) and EasyEngine#481 (orphaned remote backup delete failure). Use the next free codes: 3005 for the archive integrity failure and 4005 for the dump staging failure.
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.

2 participants