package hostclaim import ( "context" "github.com/carlosframework/platform/internal/release" ) // PendingMoveFenceLoss selects the frozen target writer until its first recovery admission. func PendingMoveFenceLoss(c *Claim) (LossRecord, bool) { ref, ok := ConsumedMoveTargetFence(c) if !ok { return LossRecord{}, false } for _, l := range c.EvidenceRefs { if l.Op != c.Op.ID || l.Box != c.Op.Intent["target"] || l.Fence != ref || l.Session == 0 || c.Op.Journal["fence_admitted."+l.ID] != "" { continue } region := c.Op.Intent["to"] return LossRecord{ID: l.ID, Host: c.Host, OpID: l.Op, OpKind: l.Kind, OpPhase: l.Phase, HolderIncarnation: l.Incarnation, HolderStamp: l.Stamp, HolderSession: l.Session, Box: l.Box, Enrollment: l.Enrollment, Automatic: &l, WriteSources: []WriteSource{{Reason: "target", Box: l.Box, Session: l.Session, Generation: l.Generation, Region: region, Baseline: "replica:" + region + "/" + l.Generation}}}, true } return LossRecord{}, false } // AdmitWriterWithFencedTargetLoss binds the frozen target maximum independently of restore. func AdmitWriterWithFencedTargetLoss(ctx context.Context, s release.Store, o Observed, in Admission, sources []ValidatedWriteSource) (Observed, error) { record, ok := PendingMoveFenceLoss(o.Claim) if !ok || o.Claim.Op.Phase != PhaseProbing || len(sources) != 1 || in.Coverage != "" || in.Mode != "cold" || in.KeepStamp || in.PredecessorCertified || in.LossID != "" || len(in.AdditionalWritesLost) != 0 { return Observed{}, ErrFence } want, got := record.WriteSources[0], sources[0] if got.Reason != want.Reason || got.Box != want.Box || got.Session != want.Session || got.Generation != want.Generation || got.Region != want.Region || got.Baseline != want.Baseline || in.RemoteMaxTXID != got.RemoteMaxTXID { return Observed{}, ErrFence } h := o.Claim.Holder p := AdmissionRecord{Box: h.WriterBox, Session: h.Session, Generation: h.Generation} if len(h.Admissions) > 0 { p = h.Admissions[len(h.Admissions)-1] } if p.Box != want.Box || p.Session != want.Session || p.Generation != want.Generation { return Observed{}, ErrFence } in.fenceVerified = true return Update(ctx, s, o, func(c *Claim) error { if err := AdmitWriter(in)(c); err != nil { return err } setJournal(c, "fence_admitted."+record.ID, "true") return nil }) }