Correct Fallback tier variable naming and document rsync merge-run

The fallback docs used an older COVERS naming in the wrong conf file, and rsync's merge-run
mode — the only path that carries --delete — was undocumented entirely.
This commit is contained in:
Gmer4Lfe
2026-08-01 23:05:30 -04:00
parent 8a2707ee37
commit 53aa72d38c
3 changed files with 115 additions and 28 deletions
+70 -1
View File
@@ -607,7 +607,7 @@ DEFAULT_RSYNC_OPTS="-az --no-perms --no-owner --no-group --inplace"
BW_LIMIT=0 # KB/s, 0 = unlimited
RETRY_COUNT=3
SLEEP=60 # seconds between retries
ROOTFS_WARN_PCT=75 # abort if remote rootfs above this %
ROOTFS_WARN=75 # abort if remote rootfs above this %
# Shared with Monitors/
BANDWIDTH_LOG="$DATA_DIR/bandwidth_history.db"
@@ -696,3 +696,72 @@ name doesn't match any profile key, or when testing a specific profile.
rsync.sh /mnt/user/appdata-Fallback/Critical-Data --profile=critical-data
rsync.sh /mnt/user/Media_Server/Emby --profile=emby
```
### --seed
Skip the empty-remote-share guard. Normally `check_remote_share()` aborts when the target
directory on the remote is missing or empty, because that usually means the array is not
mounted and syncing into it would write onto the underlying root filesystem. `--seed` is the
deliberate exception, for the first push of a genuinely new share.
```bash
rsync.sh /mnt/user/New_Share --seed
```
### --merge-run
Bidirectional merge. Two passes:
```
Pass 1 pull remote → local, with --ignore-existing
Pass 2 push local → remote, with --delete
```
Local ends up authoritative: the remote may contribute files the local lacks, but never a
competing version of a file the local already has. Also triggered automatically when the
pre-scan detects ≥75% directory overlap with the remote.
**`--delete` is applied only if pass 1 completed.** Its entire justification is "local is now
the authoritative superset", and a pull that was capped by `RSYNC_MAX_RUNTIME_HOURS` or failed
outright means it is not — the remote still holds content the local never received. On an
incomplete pull the push runs **without** `--delete`, warns, and notifies. Local content still
propagates; nothing remote-unique is destroyed; the delete happens on a later run whose pull
actually succeeded.
> This was a real defect, fixed 2026-08-01. `--delete` used to be unconditional, so a capped
> or failed pull would permanently delete remote content the pull had not yet retrieved — and
> the timeout branch's own comment promised it would "resume the pull next run", which was
> impossible once the data was gone. If you are changing this function, that interlock is the
> part that matters.
---
## ━━━ SOURCE PATH GUARDS ━━━
`rsync.sh` pushes to `root@remote` at the **same absolute path**, and `--merge-run` adds
`--delete`. The source argument is therefore a remote-side hazard, not just a local one, so
two guards run before anything else:
| Guard | Rejects |
|-------|---------|
| Absolute path, ≥3 components | `/`, `/mnt`, `/mnt/user`, empty |
| Directory must exist locally | typo'd paths |
Every real job path clears both — see `HOST*_DAILY_SYNC_SHARES` and friends, all of which are
`/mnt/user/<Share>` or deeper.
Without the existence check, a mistyped path under `--merge-run` would be *created* locally by
the pull pass, filled from the remote, then pushed back with `--delete`.
---
## ━━━ RUNTIME CEILING ━━━
No single transfer attempt may exceed `RSYNC_MAX_RUNTIME_HOURS` (default 23). On timeout the
transfer is terminated and resumes on the next scheduled run.
This is only safe because `--partial` is in `DEFAULT_RSYNC_OPTS` — a terminated transfer picks
up where it left off rather than restarting. The cap exists so one huge or stuck transfer
cannot hold its per-profile lock indefinitely and starve every other profile of a turn.
Both `--merge-run` passes are capped independently.