LibrePortal/scripts/backup/engine/restic_check.sh
librelad 71a02374d1 perf(backup): raw-data stats, dedupe repo stats, SSH connection reuse
Follow-up to the backup-refresh throttle/dedupe, cutting the cost of the
remote pulls that do still happen.

* restic stats now runs in --mode raw-data (restic_check.sh). The default
  restore-size mode walks every snapshot's tree to sum logical file sizes —
  the slowest restic op — just to fill a size readout. raw-data reads the
  index only and reports the repository's actual deduplicated on-disk size,
  which is exactly what the dashboard already labels "deduplicated,
  encrypted". raw-data omits total_file_count, so the per-location card now
  shows that location's snapshot count (already loaded client-side, and more
  useful for a backup repo) instead of a file count.

* engineLocationStats now shares the same per-refresh memoiser as
  engineSnapshotsJson (engine_dispatch.sh). Both the locations and dashboard
  generators call it per location, so repo stats went from two restic calls
  per location per refresh to one. Factored the cache into _engineCachedPull.

* SSH connection reuse for SFTP locations (backup_ssh.sh): ControlMaster=auto
  with a self-reaping ControlPersist master, so the several restic
  subprocesses a refresh/backup spawns against one location share a single
  authenticated connection instead of a fresh handshake each — the dominant
  per-call cost on a high-latency link. Toggle via CFG_BACKUP_SSH_MULTIPLEX.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-07-17 21:56:55 +01:00

56 lines
1.6 KiB
Bash

#!/bin/bash
resticCheckLocation()
{
local idx="$1"
local read_data="$2"
resticEnvExport "$idx" || return 1
local args=(check)
if [[ "$read_data" == "full" ]]; then
args+=(--read-data)
elif [[ -n "$read_data" ]]; then
args+=(--read-data-subset "${read_data}%")
fi
isNotice "Checking $(resticLocationName "$idx")${read_data:+ (sample: ${read_data}%)}"
runBackupOp restic "${args[@]}"
local rc=$?
resticEnvUnset
if [[ $rc -eq 0 ]]; then
isSuccessful "$(resticLocationName "$idx") integrity OK"
else
isError "$(resticLocationName "$idx") integrity FAILED"
fi
return $rc
}
resticCheckAllLocations()
{
local read_data="$1"
local idx
local failed=0
while IFS= read -r idx; do
[[ -z "$idx" ]] && continue
resticCheckLocation "$idx" "$read_data" || failed=$((failed + 1))
done < <(resticEnabledLocations)
return $failed
}
resticLocationStats()
{
local idx="$1"
resticEnvExport "$idx" || return 1
# raw-data mode reads the index only and reports the repository's actual
# deduplicated on-disk size — fast, and the number the dashboard already
# labels "deduplicated, encrypted". The default restore-size mode instead
# walks every snapshot's tree to sum logical file sizes: the slowest restic
# op, and pointless for a size readout. (raw-data omits total_file_count;
# the dashboard shows snapshot count for that slot instead.)
runBackupOp restic stats --json --no-lock --mode raw-data 2>/dev/null
local rc=$?
resticEnvUnset
return $rc
}