feat: BackupRunner helper — unify backup run/status/notification #214

Merged
jmiller merged 2 commits from feat/backup-runner-helper into main 2026-07-05 22:29:41 +00:00
Owner

Why

Every non-interactive backup trigger used a slightly different path, so final status and notification gating behaved inconsistently depending on what started the backup. This is the root cause of the "pre-update backup notification gating not working" report: runPreActionBackup() runs its own BackupEngine call, separate from the dashboard's "Backup Now" (stepped/AJAX) flow, with no shared seam for status/notification behavior.

What

Adds com_mokosuitebackup/src/Service/BackupRunner.php — the single synchronous entry point for a backup.

  • One notification layer: it delegates to BackupEngine, which already sends notifications gated by the profile's notify_on_success / notify_on_failure and applies retention. BackupRunner does not re-notify (no double-send).
  • Normalized result: returns {success, status, message, record_id, warnings} — including the real complete / warning / fail status the engine writes to the record but never returned, so callers can finally distinguish a warning (archive made, remote upload failed) from a clean success.
  • Self-loading: BackupRunner lazy-loads BackupEngine, so each caller requires just one file.

Routed through BackupRunner (previously each did new BackupEngine() directly):

Caller Origin
plg_system runPreActionBackup() preaction
plg_system web-cron handler webcron
plg_content triggerAutoBackup() backend (pre-install)
plg_task scheduled run scheduled
plg_console RunCommand cli

Deferred / not in scope

  • Dashboard "Backup Now" (AJAX SteppedBackupEngine + progress modal) is unchanged — it's the interactive equivalent.
  • Installer progress popup for pre-update backups is deferred to #196: the extension install/update request runs server-side and can't drive the AJAX progress modal. A // TODO(#196) marks the seam in BackupRunner::run().

Verification

php -l clean on all changed files. plg_task's separate SnapshotEngine guard is intentionally left untouched.

https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i

## Why Every non-interactive backup trigger used a slightly different path, so **final status and notification gating behaved inconsistently** depending on what started the backup. This is the root cause of the "pre-update backup notification gating not working" report: `runPreActionBackup()` runs its own `BackupEngine` call, separate from the dashboard's "Backup Now" (stepped/AJAX) flow, with no shared seam for status/notification behavior. ## What Adds **`com_mokosuitebackup/src/Service/BackupRunner.php`** — the single synchronous entry point for a backup. - **One notification layer:** it *delegates* to `BackupEngine`, which already sends notifications gated by the profile's `notify_on_success` / `notify_on_failure` and applies retention. BackupRunner does **not** re-notify (no double-send). - **Normalized result:** returns `{success, status, message, record_id, warnings}` — including the real **complete / warning / fail** status the engine writes to the record but never returned, so callers can finally distinguish a warning (archive made, remote upload failed) from a clean success. - **Self-loading:** BackupRunner lazy-loads `BackupEngine`, so each caller requires just one file. Routed through BackupRunner (previously each did `new BackupEngine()` directly): | Caller | Origin | |---|---| | `plg_system` `runPreActionBackup()` | `preaction` | | `plg_system` web-cron handler | `webcron` | | `plg_content` `triggerAutoBackup()` | `backend` (pre-install) | | `plg_task` scheduled run | `scheduled` | | `plg_console` `RunCommand` | `cli` | ## Deferred / not in scope - **Dashboard "Backup Now"** (AJAX `SteppedBackupEngine` + progress modal) is unchanged — it's the interactive equivalent. - **Installer progress popup** for pre-update backups is deferred to **#196**: the extension install/update request runs server-side and can't drive the AJAX progress modal. A `// TODO(#196)` marks the seam in `BackupRunner::run()`. ## Verification `php -l` clean on all changed files. `plg_task`'s separate `SnapshotEngine` guard is intentionally left untouched. https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
Author
Owner

Wiki reminder: docs are wiki-first -- if this PR changes behavior, usage, config, or standards, please update the repo wiki before/after merge. (non-blocking)

<!-- wiki-reminder --> **Wiki reminder:** docs are wiki-first -- if this PR changes behavior, usage, config, or standards, please update the repo wiki before/after merge. _(non-blocking)_
jmiller added 2 commits 2026-07-05 22:29:33 +00:00
Every non-interactive backup trigger used a slightly different path, so
final status and notification gating behaved inconsistently depending on
what started the backup (this is why pre-update backups did not gate
notifications the way "Backup Now" does).

Add src/Service/BackupRunner.php as the single synchronous entry point.
It delegates to BackupEngine (which already sends notifications gated by
the profile's notify_on_success/notify_on_failure and applies retention —
so there is exactly ONE notification layer), and normalises the result,
including the real complete/warning/fail status the engine records but did
not return. BackupRunner self-loads BackupEngine so callers require one file.

Routed through BackupRunner:
- plg_system  runPreActionBackup() (preaction) + web-cron handler (webcron)
- plg_content triggerAutoBackup() (pre-install)
- plg_task    scheduled task run
- plg_console RunCommand (cli)

The dashboard AJAX/stepped "Backup Now" flow is unchanged (it is the
interactive equivalent). The installer progress popup is deferred — the
installer request cannot drive the AJAX modal (TODO(#196) noted in code).

php -l clean on all changed files.

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
docs(changelog): add BackupRunner entry (#214)
Universal: PR Check / Branch Policy (pull_request) Failing after 4s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 7s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 11s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Failing after 8s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 3s
Universal: PR Check / Secret Scan (pull_request) Successful in 11s
Branch Cleanup / Delete merged branch (pull_request) Successful in 4s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 15s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 15s
Generic: Project CI / Lint & Validate (pull_request) Successful in 1m3s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 51s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
28ca110d7b
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
jmiller force-pushed feat/backup-runner-helper from 1bc01c08bc to 28ca110d7b 2026-07-05 22:29:33 +00:00 Compare
jmiller merged commit 99d8e954bd into main 2026-07-05 22:29:41 +00:00
jmiller deleted branch feat/backup-runner-helper 2026-07-05 22:29:48 +00:00
Sign in to join this conversation.