package console import ( "context" "errors" "sort" "github.com/carlosframework/platform/internal/hostclaim" "github.com/carlosframework/platform/internal/hostops" ) // SweepClaimHolds recovers the directory half even after an operation's // claim intent has been cleared by successful completion or freeing. func (s *Server) SweepClaimHolds(ctx context.Context) error { if !s.cfg.HostClaim { return nil } a := s.cfg.ClaimAuthority if a == nil { return hostops.ErrContract } roster, err := a.Directory.Read(ctx) if err != nil { return err } ids := make([]string, 0, len(roster.Roster.Holds)) for id := range roster.Roster.Holds { ids = append(ids, id) } sort.Strings(ids) var all []error for _, id := range ids { hold := roster.Roster.Holds[id] claim, err := hostclaim.Read(ctx, a.Store, hold.Host) if err != nil { all = append(all, err) continue } if !claim.Absent && claim.ETag != hold.ExpectedClaimETag && (claim.Claim.Free() || claim.Claim.Op.Kind == hostclaim.KindServing) { err = a.Directory.ReleaseFinishedHold(ctx, a.Signer, id) } else if !claim.Absent && claim.Claim.Op.Intent["actors_hold"] == id { continue } else { // CancelHold first invalidates the reserved claim revision, rereads both // objects, and refuses if an uncertain Start actually attached this hold. err = a.Directory.CancelHold(ctx, a.Signer, id) } if err != nil { all = append(all, err) } } return errors.Join(all...) }