Stop waiting for count writes after a request's deadline (closes #224)
check / check (push) Waiting to run

TestService_Get_ReturnsByItsDeadline failed on a busy host because its
request, past its deadline, still waited for its miss count to be
written, a database write with no deadline; in pixad that write waits
for the one database connection every request shares. The hit, miss,
upstream fetch and transform counts are now each written in a goroutine
of their own, which the request waits for only until its deadline; a
count not written by then is written after it returns. Shutdown waits
for those writes within ShutdownTimeout and reports any left unfinished.
The test phase also runs go test with -parallel 4: on a busy host, as
many tests at once as there are CPUs wait so long to be scheduled that
a timed request can fail.

Model: opus-5-5
This commit is contained in:
2026-10-08 13:29:06 +00:00
parent bdde021b45
commit df7fff0ce1
7 changed files with 231 additions and 19 deletions
+20 -5
View File
@@ -29,6 +29,10 @@ const (
// still being processed once ShutdownTimeout has passed.
var errStillProcessing = errors.New("images still being processed at shutdown")
// errStillWritingCounts is returned by the server's stop hook when counts
// are still being written to the database once ShutdownTimeout has passed.
var errStillWritingCounts = errors.New("counts still being written at shutdown")
// Params defines dependencies for Server.
type Params struct {
fx.In
@@ -117,9 +121,11 @@ func (s *Server) enableSentry() error {
}
// cleanShutdown stops the HTTP server, waits for the images still being
// processed, then flushes Sentry. The first two share ShutdownTimeout. It
// returns errStillProcessing when images are still being processed after
// that, as their work is abandoned.
// processed and then for the counts still being written to the database,
// which closes after this hook, then flushes Sentry. The first three share
// ShutdownTimeout. It returns errStillProcessing and errStillWritingCounts
// for the images and counts still unfinished after that, as their work is
// abandoned.
func (s *Server) cleanShutdown(ctx context.Context) error {
s.log.Info("shutting down")
@@ -132,17 +138,26 @@ func (s *Server) cleanShutdown(ctx context.Context) error {
}
stillProcessing := s.h.WaitForProcessing(ctxShutdown)
countsWritten := s.h.WaitForCountWrites(ctxShutdown)
if s.sentryEnabled {
sentry.Flush(SentryFlushTimeout)
}
var unfinished []error
if stillProcessing > 0 {
s.log.Error("images still being processed at shutdown",
"count", stillProcessing)
return errStillProcessing
unfinished = append(unfinished, errStillProcessing)
}
return nil
if !countsWritten {
s.log.Error("counts still being written at shutdown")
unfinished = append(unfinished, errStillWritingCounts)
}
return errors.Join(unfinished...)
}