fix(iot): готовность consumer по SQS + ограничение wg.Wait + идемпотентный Close (Этап 3)

- consumer.Run получил onReady: /ready теперь false при ошибке ReceiveMessage
  (раньше флаг consumer'а выставлялся до старта и не отражал SQS).
- main.go: wg.Wait заменён на waitWithTimeout (shutdownGrace=15с) — зависшую
  подсистему не ждём бесконечно.
- iotpg.Close идемпотентен (sync.Once) — повторный вызов не паникует.
This commit is contained in:
Repinoid
2026-10-10 19:16:30 +03:00
parent c725676f85
commit f3927fdf11
3 changed files with 57 additions and 16 deletions
+18 -9
View File
@@ -52,6 +52,10 @@ type IoTPostgresStore struct {
batches map[string][]telemetryInsert
stopFlush chan struct{}
flushWG sync.WaitGroup
// closeOnce — Close идемпотентен: повторный вызов не паникует на close(stopFlush)
// (ревью 2026-10-10).
closeOnce sync.Once
}
// telemetryInsert — строка для батч-вставки.
@@ -602,17 +606,22 @@ func isDBNotExistErr(err error) bool {
}
// Close останавливает flusher, дописывает остаток и закрывает все подключения.
// Идемпотентен (closeOnce): повторный вызов не паникует на close(stopFlush).
func (s *IoTPostgresStore) Close() error {
close(s.stopFlush)
s.flushWG.Wait()
_ = s.flushAll(context.Background())
s.tenants.Range(func(_, value any) bool {
if db, ok := value.(*sql.DB); ok {
db.Close()
}
return true
var err error
s.closeOnce.Do(func() {
close(s.stopFlush)
s.flushWG.Wait()
_ = s.flushAll(context.Background())
s.tenants.Range(func(_, value any) bool {
if db, ok := value.(*sql.DB); ok {
db.Close()
}
return true
})
err = s.adminDB.Close()
})
return s.adminDB.Close()
return err
}
// getTenantDB возвращает *sql.DB для tenant DB из кэша или открывает новый.