mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-18 18:46:17 +00:00
a5800033bd
* feat(heal): incremental heal status cursors and typed overlap policy (HS-06) Incremental results: every retained result item now carries a monotonic sequence number. The status query accepts a client cursor (sinceSeq on the admin wire, Option<u64> internally) and returns only newer items, plus nextSeq (the next cursor) and minSeq (the oldest retained sequence). A cursor that fell behind the 1024-item retention window is flagged through the existing truncated signal together with minSeq so the client can restart from it. Sequencing survives task completion: the completion archive stores the seq-stamped window. None keeps the exact legacy full-snapshot behavior, so existing clients see no change. Typed overlap handling for admin starts: RUSTFS_HEAL_OVERLAP_POLICY (merge default | minio_error). Under minio_error, an admin start whose path overlaps an active or queued task rejects with typed already-running / overlapping-paths admission reasons (surfaced through reason_label in the admin error body, sharing the existing OperationAborted site because the s3s footprint ratchet forbids new s3_error! sites); an exact duplicate start rejects with already-running instead of silently merging. Scanner/autoheal/ read-repair sources never take the rejection path. forceStart semantics now match MinIO for admin requests: an admin forceStart first cancels the overlapping active admin task, then admits the replacement. Wire: the heal-control Query command grows an optional sinceSeq (defaulted and skipped when absent, so older peers stay compatible); the admin handler accepts the sinceSeq query parameter; the local channel query gains the same cursor. Tests: seq monotonicity and incremental slicing, window slide moving minSeq with lagging-cursor flags, overlap matrix (same/containing/ contained/disjoint x policy x source), forceStart cancel-then-admit, and the completion-archive window handoff. Co-Authored-By: heihutu <heihutu@gmail.com> * style: fmt after main merge --------- Co-authored-by: heihutu <heihutu@gmail.com> Co-authored-by: zhi22915 <qiuzgang@gmail.com>
91 lines
3.5 KiB
Bash
Executable File
91 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Ratchet guard freezing the s3s dependency footprint ahead of the
|
||
# s3gate/gateway migration (rustfs/backlog#1677, review finding F1;
|
||
# acceptance criteria recorded in rustfs/backlog#1733).
|
||
#
|
||
# The migration's goal is to shrink the direct s3s surface, so new code must
|
||
# not grow it. Two counters are ratcheted, baselines verified on 2026-08-05:
|
||
#
|
||
# - files referencing s3s paths: rg -l "$S3S_PATH_PATTERN" --type rust (files)
|
||
# - s3_error! invocation lines: rg -c 's3_error!' --type rust (summed)
|
||
#
|
||
# Either count exceeding its baseline fails the check with the offending
|
||
# delta. Baselines are LOWER-ONLY: when a PR shrinks the footprint, lower the
|
||
# matching baseline in the same PR so the ratchet stays tight. Never raise a
|
||
# baseline to get green (AGENTS.md, Verification Before PR) — route new S3
|
||
# API code through the gateway abstractions instead of importing s3s
|
||
# directly.
|
||
#
|
||
# Usage: scripts/check_s3s_footprint.sh
|
||
|
||
set -euo pipefail
|
||
|
||
cd "$(dirname "$0")/.."
|
||
|
||
# Baselines verified on 2026-08-11. Lower-only; see header.
|
||
# Excludes crates/e2e_test/ — test infrastructure legitimately uses s3s
|
||
# to verify S3 behavior and does not widen the production s3s surface.
|
||
S3S_IMPORT_FILES_BASELINE=211
|
||
S3_ERROR_LINES_BASELINE=1620
|
||
S3S_PATH_PATTERN='(^|[^"[:alnum:]_])s3s::'
|
||
E2E_TEST_GLOB='--glob=!crates/e2e_test/**'
|
||
|
||
TMP_DIR="$(mktemp -d)"
|
||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||
|
||
# rg exits 1 on zero matches (a legitimate count of 0 at the end of the
|
||
# migration) and >1 on real errors; only the latter may abort the check.
|
||
run_rg_to() {
|
||
local out="$1" rg_status=0
|
||
shift
|
||
rg "$@" >"$out" || rg_status=$?
|
||
if ((rg_status > 1)); then
|
||
echo "error: 'rg $*' failed with status $rg_status" >&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
run_rg_to "$TMP_DIR/import_files" -l "$S3S_PATH_PATTERN" --type rust $E2E_TEST_GLOB
|
||
run_rg_to "$TMP_DIR/error_lines" -c 's3_error!' --type rust $E2E_TEST_GLOB
|
||
|
||
s3s_import_files="$(grep -c . "$TMP_DIR/import_files" || true)"
|
||
s3_error_lines="$(awk -F: '{sum += $NF} END {print sum + 0}' "$TMP_DIR/error_lines")"
|
||
|
||
for value in "$s3s_import_files" "$s3_error_lines"; do
|
||
if ! [[ "$value" =~ ^[0-9]+$ ]]; then
|
||
echo "error: could not compute s3s footprint counts (got: '$value')" >&2
|
||
exit 1
|
||
fi
|
||
done
|
||
|
||
status=0
|
||
|
||
check_ratchet() {
|
||
local label="$1" count="$2" baseline="$3" inspect_cmd="$4"
|
||
|
||
if ((count > baseline)); then
|
||
echo "❌ s3s footprint ratchet violation: $label is $count, baseline is $baseline (+$((count - baseline)))" >&2
|
||
echo " New code must not widen the s3s surface being removed by the s3gate migration" >&2
|
||
echo " (rustfs/backlog#1677 F1, rustfs/backlog#1733). Use the gateway abstractions" >&2
|
||
echo " instead of importing s3s directly. To find the offenders, compare" >&2
|
||
echo " '$inspect_cmd' against origin/main." >&2
|
||
status=1
|
||
elif ((count < baseline)); then
|
||
echo "ℹ️ s3s footprint shrank: $label is $count, baseline is $baseline ($((count - baseline)))." >&2
|
||
echo " Lower the baseline in scripts/check_s3s_footprint.sh in this PR to keep the ratchet tight." >&2
|
||
else
|
||
echo "s3s footprint OK: $label is $count (baseline: $baseline)"
|
||
fi
|
||
}
|
||
|
||
check_ratchet "files importing s3s" "$s3s_import_files" "$S3S_IMPORT_FILES_BASELINE" \
|
||
"rg -l '$S3S_PATH_PATTERN' --type rust $E2E_TEST_GLOB"
|
||
check_ratchet "s3_error! invocation lines" "$s3_error_lines" "$S3_ERROR_LINES_BASELINE" \
|
||
"rg -c 's3_error!' --type rust $E2E_TEST_GLOB"
|
||
|
||
if ((status != 0)); then
|
||
exit 1
|
||
fi
|
||
|
||
echo "✅ s3s footprint ratchet check passed"
|