Files
seaweedfs/sw-block/engine/replication/budget.go
T
pingqiuandClaude Opus 4.6 20d70f9fb6 feat: add V2 engine replication core (Phase 05 Slice 1)
Creates sw-block/engine/replication/ — the real V2 engine ownership core,
promoted from sw-block/prototype/enginev2/ with all accepted invariants.

Files:
- types.go: Endpoint, ReplicaState, SessionKind, SessionPhase, FSM transitions
- sender.go: per-replica Sender with full execution + rebuild APIs
- session.go: Session with identity, phases, frozen target, truncation, budget
- registry.go: Registry with reconcile + assignment intent + epoch invalidation
- budget.go: CatchUpBudget (duration, entries, stall detection)
- rebuild.go: RebuildState FSM (snapshot+tail vs full base)
- outcome.go: HandshakeResult + ClassifyRecoveryOutcome

Tests (ownership_test.go, 13 tests):
- Changed-address invalidation (A10)
- Stale session ID rejected at all APIs (A3)
- Stale completion after supersede (A3)
- Epoch bump invalidates all sessions (A3)
- Stale assignment epoch rejected
- Rebuild exclusivity (catch-up APIs rejected)
- Rebuild full lifecycle
- Frozen target rejects chase (A5)
- Budget violation escalates (A5)
- E2E: 3 replicas, 3 outcomes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:51:01 -07:00

47 lines
1.6 KiB
Go

package replication
// CatchUpBudget defines the bounded resource contract for a catch-up session.
// When any limit is exceeded, the session escalates to NeedsRebuild.
// A zero value for any field means "no limit" for that dimension.
//
// Note: the frozen catch-up target is on Session.FrozenTargetLSN, not here.
// FrozenTargetLSN is set unconditionally by BeginCatchUp and enforced by
// RecordCatchUpProgress regardless of budget presence.
type CatchUpBudget struct {
MaxDurationTicks uint64 // hard time limit
MaxEntries uint64 // max WAL entries to replay
ProgressDeadlineTicks uint64 // stall detection window
}
// BudgetCheck tracks runtime budget consumption.
type BudgetCheck struct {
StartTick uint64
EntriesReplayed uint64
LastProgressTick uint64
}
// BudgetViolation identifies which budget limit was exceeded.
type BudgetViolation string
const (
BudgetOK BudgetViolation = ""
BudgetDurationExceeded BudgetViolation = "duration_exceeded"
BudgetEntriesExceeded BudgetViolation = "entries_exceeded"
BudgetProgressStalled BudgetViolation = "progress_stalled"
)
// Check evaluates the budget against the current tick.
func (b *CatchUpBudget) Check(tracker BudgetCheck, currentTick uint64) BudgetViolation {
if b.MaxDurationTicks > 0 && currentTick-tracker.StartTick > b.MaxDurationTicks {
return BudgetDurationExceeded
}
if b.MaxEntries > 0 && tracker.EntriesReplayed > b.MaxEntries {
return BudgetEntriesExceeded
}
if b.ProgressDeadlineTicks > 0 && tracker.LastProgressTick > 0 &&
currentTick-tracker.LastProgressTick > b.ProgressDeadlineTicks {
return BudgetProgressStalled
}
return BudgetOK
}