Bound each shutdown stage by the stop deadline (closes #100)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
Shutdown passes its context to every stage: the streamer, the four handlers, the WHOIS fetcher, the database maintainer and the HTTP server each stop waiting when it ends. A handler then skips its last write and logs how many updates it did not write, and the HTTP server closes the connections still open. The database is checkpointed and closed last, and left open once the deadline has passed, since a write may still hold it. The stop hook gives Shutdown 8 seconds and fx 9, inside the 10 seconds upaas and docker stop allow, so a stop signal exits 0. Model: opus-5-5
This commit was merged in pull request #130.
This commit is contained in:
@@ -43,7 +43,7 @@ type ASNFetcher struct {
|
||||
logger *slog.Logger
|
||||
immediateQueue chan int
|
||||
stopCh chan struct{}
|
||||
wg sync.WaitGroup
|
||||
done chan struct{} // closed when the fetcher goroutine returns
|
||||
|
||||
// fetchMu ensures only one fetch runs at a time
|
||||
fetchMu sync.Mutex
|
||||
@@ -67,6 +67,7 @@ func NewASNFetcher(db database.Store, logger *slog.Logger) *ASNFetcher {
|
||||
logger: logger.With("component", "asn_fetcher"),
|
||||
immediateQueue: make(chan int, immediateQueueSize),
|
||||
stopCh: make(chan struct{}),
|
||||
done: make(chan struct{}),
|
||||
currentInterval: baseInterval,
|
||||
successTimes: make([]time.Time, 0),
|
||||
errorTimes: make([]time.Time, 0),
|
||||
@@ -76,8 +77,6 @@ func NewASNFetcher(db database.Store, logger *slog.Logger) *ASNFetcher {
|
||||
// Start begins the background ASN fetcher goroutine. It runs until Stop:
|
||||
// the end of ctx does not stop it.
|
||||
func (f *ASNFetcher) Start(ctx context.Context) {
|
||||
f.wg.Add(1)
|
||||
|
||||
go f.run(context.WithoutCancel(ctx))
|
||||
|
||||
f.logger.Info("ASN fetcher started",
|
||||
@@ -87,11 +86,17 @@ func (f *ASNFetcher) Start(ctx context.Context) {
|
||||
)
|
||||
}
|
||||
|
||||
// Stop gracefully shuts down the fetcher.
|
||||
func (f *ASNFetcher) Stop() {
|
||||
// Stop stops the fetcher and waits, until ctx ends, for a lookup in progress to
|
||||
// finish.
|
||||
func (f *ASNFetcher) Stop(ctx context.Context) {
|
||||
close(f.stopCh)
|
||||
f.wg.Wait()
|
||||
f.logger.Info("ASN fetcher stopped")
|
||||
|
||||
select {
|
||||
case <-f.done:
|
||||
f.logger.Info("ASN fetcher stopped")
|
||||
case <-ctx.Done():
|
||||
f.logger.Warn("Stop deadline passed before the ASN fetcher stopped")
|
||||
}
|
||||
}
|
||||
|
||||
// QueueImmediate queues an ASN for immediate WHOIS lookup.
|
||||
@@ -197,7 +202,7 @@ func (f *ASNFetcher) recordFailure() {
|
||||
|
||||
// run is the main background loop.
|
||||
func (f *ASNFetcher) run(ctx context.Context) {
|
||||
defer f.wg.Done()
|
||||
defer close(f.done)
|
||||
|
||||
timer := time.NewTimer(f.getInterval())
|
||||
defer timer.Stop()
|
||||
|
||||
Reference in New Issue
Block a user