mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-20 14:17:07 +00:00
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>
31 lines
1.1 KiB
Go
31 lines
1.1 KiB
Go
package replication
|
|
|
|
// HandshakeResult captures what the reconnect handshake reveals about
|
|
// a replica's state relative to the primary's lineage-safe boundary.
|
|
type HandshakeResult struct {
|
|
ReplicaFlushedLSN uint64 // highest LSN durably persisted on replica
|
|
CommittedLSN uint64 // lineage-safe recovery target
|
|
RetentionStartLSN uint64 // oldest LSN still available in primary WAL
|
|
}
|
|
|
|
// RecoveryOutcome classifies the gap between replica and primary.
|
|
type RecoveryOutcome string
|
|
|
|
const (
|
|
OutcomeZeroGap RecoveryOutcome = "zero_gap"
|
|
OutcomeCatchUp RecoveryOutcome = "catchup"
|
|
OutcomeNeedsRebuild RecoveryOutcome = "needs_rebuild"
|
|
)
|
|
|
|
// ClassifyRecoveryOutcome determines the recovery path from handshake data.
|
|
// Zero-gap requires exact equality (FlushedLSN == CommittedLSN).
|
|
func ClassifyRecoveryOutcome(result HandshakeResult) RecoveryOutcome {
|
|
if result.ReplicaFlushedLSN == result.CommittedLSN {
|
|
return OutcomeZeroGap
|
|
}
|
|
if result.RetentionStartLSN == 0 || result.ReplicaFlushedLSN+1 >= result.RetentionStartLSN {
|
|
return OutcomeCatchUp
|
|
}
|
|
return OutcomeNeedsRebuild
|
|
}
|