What is wrong. Three goroutines in internal/routewatch can start a database write after the stop deadline:
the AS handler's flush goroutine (ASHandler.flushLoop);
the peer handler's flush goroutine (PeerHandler.flushLoop);
the peering handler's processing goroutine (PeeringHandler.processLoop).
Each waits in one select on its timer, on Stop's context and, in the AS and peer handlers, on a full batch's wake-up. A write can run past the stop deadline while a tick or a wake-up waits beside Stop's context. Go then picks one ready case at random, so about half the time the goroutine starts another write after the deadline. That breaks the rule of #100.
The fix for #188 changes the prefix handler only. Its flush goroutine now takes a waiting stop before anything else. The same change in the AS and peer handlers makes the duplicate-code linter (dupl) flag the three flush loops, which were near-copies already. Their tests do not hit the race in practice.
What acceptable looks like. None of the three goroutines starts a write once the stop deadline has passed. Each has a test that fails on the current code.
Model: opus-5-5
**What is wrong.** Three goroutines in `internal/routewatch` can start a database write after the stop deadline:
- the AS handler's flush goroutine (`ASHandler.flushLoop`);
- the peer handler's flush goroutine (`PeerHandler.flushLoop`);
- the peering handler's processing goroutine (`PeeringHandler.processLoop`).
Each waits in one `select` on its timer, on Stop's context and, in the AS and peer handlers, on a full batch's wake-up. A write can run past the stop deadline while a tick or a wake-up waits beside Stop's context. Go then picks one ready case at random, so about half the time the goroutine starts another write after the deadline. That breaks the rule of https://git.eeqj.de/sneak/routewatch/issues/100.
The fix for https://git.eeqj.de/sneak/routewatch/issues/188 changes the prefix handler only. Its flush goroutine now takes a waiting stop before anything else. The same change in the AS and peer handlers makes the duplicate-code linter (`dupl`) flag the three flush loops, which were near-copies already. Their tests do not hit the race in practice.
**What acceptable looks like.** None of the three goroutines starts a write once the stop deadline has passed. Each has a test that fails on the current code.
Model: opus-5-5
Also in scope: the AS and peer handler tests can fail the same way through their two-second flush timer, as the review of #190 found for the prefix handler's tests. The fix there lets a test set the flush interval; the same treatment here keeps every test in the package independent of the timer.
Model: opus-5-5
Also in scope: the AS and peer handler tests can fail the same way through their two-second flush timer, as the review of https://git.eeqj.de/sneak/routewatch/pulls/190 found for the prefix handler's tests. The fix there lets a test set the flush interval; the same treatment here keeps every test in the package independent of the timer.
Model: opus-5-5
Built in #191. The AS, peer and peering handlers take a waiting stop request before anything else, so none starts a write once the stop deadline has passed. The flush loops of the prefix, AS and peer handlers are now one function. The AS and peer handler tests give the flush timer an interval longer than the test, so they no longer depend on it.
Model: opus-5-5
Built in https://git.eeqj.de/sneak/routewatch/pulls/191. The AS, peer and peering handlers take a waiting stop request before anything else, so none starts a write once the stop deadline has passed. The flush loops of the prefix, AS and peer handlers are now one function. The AS and peer handler tests give the flush timer an interval longer than the test, so they no longer depend on it.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What is wrong. Three goroutines in
internal/routewatchcan start a database write after the stop deadline:ASHandler.flushLoop);PeerHandler.flushLoop);PeeringHandler.processLoop).Each waits in one
selecton its timer, on Stop's context and, in the AS and peer handlers, on a full batch's wake-up. A write can run past the stop deadline while a tick or a wake-up waits beside Stop's context. Go then picks one ready case at random, so about half the time the goroutine starts another write after the deadline. That breaks the rule of #100.The fix for #188 changes the prefix handler only. Its flush goroutine now takes a waiting stop before anything else. The same change in the AS and peer handlers makes the duplicate-code linter (
dupl) flag the three flush loops, which were near-copies already. Their tests do not hit the race in practice.What acceptable looks like. None of the three goroutines starts a write once the stop deadline has passed. Each has a test that fails on the current code.
Model: opus-5-5
Also in scope: the AS and peer handler tests can fail the same way through their two-second flush timer, as the review of #190 found for the prefix handler's tests. The fix there lets a test set the flush interval; the same treatment here keeps every test in the package independent of the timer.
Model: opus-5-5
Built in #191. The AS, peer and peering handlers take a waiting stop request before anything else, so none starts a write once the stop deadline has passed. The flush loops of the prefix, AS and peer handlers are now one function. The AS and peer handler tests give the flush timer an interval longer than the test, so they no longer depend on it.
Model: opus-5-5