diff --git a/backend/app/cmd/server.go b/backend/app/cmd/server.go index 382772df..b073a671 100644 --- a/backend/app/cmd/server.go +++ b/backend/app/cmd/server.go @@ -480,18 +480,6 @@ func (a *serverApp) run(ctx context.Context) error { <-ctx.Done() log.Print("[INFO] shutdown initiated") a.restSrv.Shutdown() - if a.devAuth != nil { - a.devAuth.Shutdown() - } - if e := a.dataService.Close(); e != nil { - log.Printf("[WARN] failed to close data store, %s", e) - } - if e := a.avatarStore.Close(); e != nil { - log.Printf("[WARN] failed to close avatar store, %s", e) - } - a.notifyService.Close() - a.imageService.Close() - log.Print("[INFO] shutdown completed") }() a.activateBackup(ctx) // runs in goroutine for each site @@ -502,6 +490,20 @@ func (a *serverApp) run(ctx context.Context) error { go a.imageService.Cleanup(ctx) // pictures cleanup for staging images a.restSrv.Run(a.Port) + + // shutdown procedures after HTTP server is stopped + if a.devAuth != nil { + a.devAuth.Shutdown() + } + if e := a.dataService.Close(); e != nil { + log.Printf("[WARN] failed to close data store, %s", e) + } + if e := a.avatarStore.Close(); e != nil { + log.Printf("[WARN] failed to close avatar store, %s", e) + } + a.notifyService.Close() + a.imageService.Close() + close(a.terminated) return nil } diff --git a/backend/app/store/image/image.go b/backend/app/store/image/image.go index 5767c4fa..4ef37687 100644 --- a/backend/app/store/image/image.go +++ b/backend/app/store/image/image.go @@ -88,9 +88,10 @@ func (s *Service) Submit(idsFn func() []string) { s.wg.Add(1) go func() { defer s.wg.Done() + atomic.StoreInt32(&s.term, 1) for req := range s.submitCh { // wait for TTL expiration with emergency pass on term - for atomic.LoadInt32(&s.term) == 0 && time.Since(req.TS) <= s.TTL/2 { // commit on a half of TTL + for atomic.LoadInt32(&s.term) == 1 && time.Since(req.TS) <= s.TTL/2 { // commit on a half of TTL time.Sleep(time.Millisecond * 10) // small sleep to relive busy wait but keep reactive for term (close) } for _, id := range req.idsFn() { @@ -98,7 +99,7 @@ func (s *Service) Submit(idsFn func() []string) { log.Printf("[WARN] failed to commit image %s", id) } } - atomic.StoreInt32(&s.term, 0) // indicates completion of ids commits + atomic.StoreInt32(&s.term, 1) // indicates completion of ids commits } log.Printf("[INFO] image submitter terminated") }() @@ -150,13 +151,16 @@ func (s *Service) Cleanup(ctx context.Context) { // Close flushes all in-progress submits and enforces waiting commits func (s *Service) Close() { log.Printf("[INFO] close image service ") - atomic.StoreInt32(&s.term, 1) // enforce non-delayed commits for all ids left in submitCh - for { - // set to 0 by Commit goroutine after everything waited on TTL sent - if atomic.LoadInt32(&s.term) == 0 { - break + // terminate commit goroutine using s.term only if it is started + if atomic.LoadInt32(&s.term) == 1 { + atomic.StoreInt32(&s.term, 0) // enforce non-delayed commits for all ids left in submitCh + for { + // set to 1 by commit goroutine after everything waited on TTL sent + if atomic.LoadInt32(&s.term) == 1 { + break + } + time.Sleep(10 * time.Millisecond) } - time.Sleep(10 * time.Millisecond) } if s.submitCh != nil { close(s.submitCh)