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
+12 -2
View File
@@ -32,8 +32,9 @@ const maxProcessBackoff = 60 * time.Second
// уходит туда на первом же приёме.
const maxReceiveCount = 5
// Run — бесконечный long-poll цикл потребителя.
func Run(ctx context.Context, cfg *config.Config, sqsClient *sqs.Client, store *iotpg.IoTPostgresStore, log *slog.Logger) error {
// Run — бесконечный long-poll цикл потребителя. onReady — колбэк готовности:
// true после успешного ReceiveMessage, false при ошибке SQS (отражается в /ready).
func Run(ctx context.Context, cfg *config.Config, sqsClient *sqs.Client, store *iotpg.IoTPostgresStore, log *slog.Logger, onReady func(bool)) error {
queueURL, err := sqsclient.ResolveQueueURLWithRetry(ctx, sqsClient, cfg.SQSQueueName)
if err != nil {
return err
@@ -80,11 +81,13 @@ func Run(ctx context.Context, cfg *config.Config, sqsClient *sqs.Client, store *
break
}
log.Error("consumer: ReceiveMessage failed", "err", err)
setReady(onReady, false)
if !sleepCtx(ctx, errorBackoff) {
break
}
continue
}
setReady(onReady, true)
processBackoff := time.Second
// Копим подтверждения, но НЕ удаляем из SQS сразу: InsertTelemetry лишь
@@ -205,6 +208,13 @@ func receiveCount(msg sqstypes.Message) int {
return n
}
// setReady — nil-safe вызов колбэка готовности.
func setReady(fn func(bool), v bool) {
if fn != nil {
fn(v)
}
}
// sleepCtx — ожидание с прерыванием по ctx. false = ctx завершён.
func sleepCtx(ctx context.Context, d time.Duration) bool {
select {