Evict expired candidate offers on a timer
CI / ci (push) Successful in 2m47s
CI / ci (pull_request) Successful in 2m51s

Each dinner's offered candidates now carry a time.AfterFunc expiry that
drops them from the service once offerLifetime passes, so token-bearing
candidate URLs are no longer held until some later search sweeps them.
Storing new offers or clearing a dinner's offers stops the old timer; the
timer drops only the set it was armed for. The expiry runs no goroutine
until it fires and touches only the in-memory map.

TestCandidatesExpire now waits for the eviction with no further search
and checks the candidate no longer grounds; TestExpiredCandidatesNotHeld
checks no dinner's expired offers remain held.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 22:50:47 -04:00
co-authored by Claude Opus 5.5
parent 515919088a
commit bef3f3fd5c
4 changed files with 77 additions and 29 deletions
+7
View File
@@ -31,6 +31,13 @@ func (s *Service) HasOffers(id string) bool {
return ok
}
// OfferCount is the number of dinners whose candidates the service holds.
func (s *Service) OfferCount() int {
s.offersMu.Lock()
defer s.offersMu.Unlock()
return len(s.offers)
}
// RunGroundJob runs the KindGroundDinner handler for p in the caller's
// goroutine, as the job runner would, and returns the grounding status it
// reports.