package console import ( "context" "errors" "log" "os" "time" "github.com/carlosframework/platform/internal/hostclaim" "github.com/carlosframework/platform/internal/hostops" "github.com/carlosframework/platform/internal/provision" ) func (s *Server) retireHostRecord(ctx context.Context, ref provision.RetireRef) error { if s.cfg.HostClaim { return s.retireClaimHostRecord(ctx, ref) } var claims provision.ClaimRetirer if s.cfg.HostClaimOps != nil { claims = s.cfg.HostClaimOps } return provision.RetireRecord(ctx, s.cfg.Releases, ref, provision.RetireOptions{HostClaim: s.cfg.HostClaim, Claims: claims}) } func (s *Server) adoptHostRecord(ctx context.Context, key string) (hostclaim.Observed, error) { if !s.cfg.HostClaim || s.cfg.HostClaimOps == nil { return hostclaim.Observed{}, hostops.ErrContract } rec, err := hostops.ReadRecord(ctx, s.cfg.Releases, key) if err != nil { return hostclaim.Observed{}, err } return s.cfg.HostClaimOps.Adopt(ctx, rec) } const claimRecoveryInterval = 2 * time.Minute // Called by serve, never NewServer. Tests can invoke the one-pass method. func (s *Server) StartClaimRecoveryPass(ctx context.Context) { if !s.cfg.HostClaim { return } if s.cfg.HostClaimOps == nil { log.Printf("console: claim recovery: %v", hostops.ErrContract) return } // The eligible-capacity metric (region HA spec 2 §4, regioncapacity.go) // runs beside claim recovery, on a host-claim console with region HA // on and a metrics adapter armed. if s.cfg.RegionHA { if pub := capacityPublisherFromEnv(ctx, os.Getenv); pub != nil { go s.runCapacityPass(ctx, pub) } // Automatic enrollment of the boxes regions' groups launch // (region HA spec 2 §5 step 5, enrollpass.go). s.startEnrollPass(ctx) } t := time.NewTicker(claimRecoveryInterval) defer t.Stop() for { if err := s.RunClaimRecoveryPass(ctx); err != nil { log.Printf("console: claim recovery: %v", err) } select { case <-ctx.Done(): return case <-t.C: } } } func (s *Server) claimRecoveryPass(ctx context.Context) error { if !s.cfg.HostClaim { return nil } if s.cfg.HostClaimRecovery == nil { return hostops.ErrContract } if a := s.cfg.ClaimAuthority; a != nil && a.Control != nil { return errors.Join(a.Control.RecoveryPass(ctx, *s.cfg.HostClaimRecovery), a.Control.SweepWakeResets(ctx, hostops.WakeResetTransport{Store: a.Store, Directory: a.Directory, Now: a.Now})) } return s.cfg.HostClaimRecovery.Pass(ctx) }