Start no AS, peer or peering write after the stop deadline (closes #189)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
A write can run past the stop deadline while a full batch's wake-up or a tick waits beside Stop's context. The select picked one at random, so about half the time the AS, peer or peering handler started another write after the deadline. Each loop now takes a waiting stop first, as the prefix handler's does. The prefix, AS and peer handlers' flush loops were near-copies, so they are now one function, flushLoop. A new test for each handler fails about half its runs on the old code. The AS and peer handler tests give the flush timer an interval longer than the test. A timer flush during the fill can no longer hang TestPeerHandlerWaitsAtTheMaximumBatchSize. Model: opus-5-5
This commit was merged in pull request #191.
This commit is contained in:
1 parent
ce19b14275
commit
05b39eee7a
9 files changed
+232
-136
No files matched your search
@@ -62,6 +62,15 @@ type PeeringHandler struct {
|
||||
// periodically processes accumulated AS paths into peering records. The
|
||||
// handler begins processing immediately upon creation.
|
||||
func NewPeeringHandler(db database.Store, logger *logger.Logger) *PeeringHandler {
|
||||
return newPeeringHandler(db, logger, peeringProcessInterval)
|
||||
}
|
||||
|
||||
// newPeeringHandler is NewPeeringHandler with the processing timer's interval,
|
||||
// processInterval, in place of peeringProcessInterval. A test gives a short
|
||||
// one to have the timer start a write.
|
||||
func newPeeringHandler(
|
||||
db database.Store, logger *logger.Logger, processInterval time.Duration,
|
||||
) *PeeringHandler {
|
||||
h := &PeeringHandler{
|
||||
db: db,
|
||||
logger: logger,
|
||||
@@ -71,7 +80,7 @@ func NewPeeringHandler(db database.Store, logger *logger.Logger) *PeeringHandler
|
||||
}
|
||||
|
||||
// Start the periodic processing goroutine
|
||||
go h.processLoop()
|
||||
go h.processLoop(processInterval)
|
||||
|
||||
return h
|
||||
}
|
||||
@@ -163,15 +172,29 @@ func (h *PeeringHandler) Stop(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// processLoop runs periodically to process AS paths into peerings, and once
|
||||
// processLoop processes AS paths into peerings every processInterval, and once
|
||||
// more on Stop.
|
||||
func (h *PeeringHandler) processLoop() {
|
||||
func (h *PeeringHandler) processLoop(processInterval time.Duration) {
|
||||
defer close(h.done)
|
||||
|
||||
ticker := time.NewTicker(peeringProcessInterval)
|
||||
ticker := time.NewTicker(processInterval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
// Stop goes first. A write can run past the stop deadline while a
|
||||
// tick waits beside Stop's context. The select below picks one of
|
||||
// them at random, but past the deadline no write may start.
|
||||
select {
|
||||
case ctx := <-h.stopCh:
|
||||
// Final processing, unless the stop deadline has passed
|
||||
if ctx.Err() == nil {
|
||||
h.processPeerings()
|
||||
}
|
||||
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ticker.C:
|
||||
h.processPeerings()
|
||||
|
||||
Reference in new issue
Block a user