You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat(core): pre/post backup shell hooks
Run optional user-configured shell commands around each backup cycle
(V2 pre/post backup hooks, DESIGN s17).
Core: a new I/O-free `CommandRunner` seam (`hooks` module) with an inert
`NoopCommandRunner` default and a `with_command_runner` builder (mirrors
`with_vss`, so none of the existing constructors churn). The orchestrator
runs the pre-hook before the per-cycle source loop - a non-zero / timed
out / unspawnable pre-hook ABORTS that cycle's backup - and the post-hook
after the loop with `DRIVEN_RESULT` = ok/error. Each run is recorded as a
`hook.<kind>` activity row. Hook commands + a kill timeout live in
`OrchestratorConfig`. Pre/post success/abort and env passing are tested
with a fake runner.
App: a real `TokioCommandRunner` (sh -c / cmd /C, env, kill-on-timeout)
wired in `assembly`, with unix tests for exit code / env / timeout.
Settings: threaded through the SPEC s22 `global` group (DTO, patch with
null-clears semantics, snake_case storage with serde(default), default,
and `load_orchestrator_config`).
UI: a "Backup hooks" Settings section (before/after command + timeout),
wired through the store with TS types, i18n, and a component test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WvXMHHbYGddVPpmQR2XmK1
* feat(core): metered network pause-or-throttle toggle
Make `skip_on_metered` configurable to either PAUSE (the V1 behaviour)
or THROTTLE - keep syncing on a metered network at a reduced bandwidth
cap (V2, DESIGN s17).
Pacer: the optional bandwidth bucket becomes runtime-swappable via a new
`Pacer::set_bandwidth_cap` (a default no-op on the trait, so the six
NoopPacer impls need no change; AimdPacer overrides it). The bucket +
its effective rate live behind one `Mutex<ByteGate>`; `permit_bytes`
clones the bucket Arc out under a brief lock so the async acquire never
holds the lock across an await, and a concurrent cap swap is safe.
set_bandwidth_cap is idempotent. Install / lift / idempotency are tested.
Orchestrator: holds the executor's pacer (shared via a new `with_pacer`
builder, no-op default like `with_command_runner`). When the gates are
open it applies the effective cap for the current network: on a metered
network in Throttle mode the metered cap, otherwise the base cap. The
metered gate no longer pauses in Throttle mode. A pure
`effective_bandwidth_cap_mbps` + two gate tests (throttle caps + does not
pause; pause still pauses + skips the cap) cover it.
Settings: `metered_mode` (pause|throttle) + `metered_bandwidth_cap_mbps`
threaded through the SPEC s22 `global` group; assembly shares the pacer.
UI: a metered mode selector (shown when "limit on metered" is on) + a
throttle bandwidth cap input, with i18n and a component test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WvXMHHbYGddVPpmQR2XmK1
---------
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments