diff --git a/internal/storage/iotpg/iot_telemetry_store.go b/internal/storage/iotpg/iot_telemetry_store.go index 574805b..be00cba 100644 --- a/internal/storage/iotpg/iot_telemetry_store.go +++ b/internal/storage/iotpg/iot_telemetry_store.go @@ -20,6 +20,7 @@ import ( "context" "database/sql" "encoding/json" + "errors" "fmt" "log/slog" "os" @@ -28,7 +29,7 @@ import ( "time" "github.com/google/uuid" - _ "github.com/lib/pq" + "github.com/lib/pq" ) // IoTPostgresStore управляет per-tenant Postgres databases для IoT телеметрии. @@ -175,6 +176,7 @@ func (s *IoTPostgresStore) InsertTelemetry(ctx context.Context, namespace, devic // QueryTelemetry читает телеметрию из tenant DB (ts DESC). // deviceID — фильтр (пустая строка = все устройства). limit — max записей (50..1000). +// Если tenant DB не существует (данных ещё нет) — возвращает пустой срез без ошибки. func (s *IoTPostgresStore) QueryTelemetry(ctx context.Context, namespace, deviceID string, limit int) ([]TelemetryRow, error) { if limit <= 0 { limit = 50 @@ -184,6 +186,10 @@ func (s *IoTPostgresStore) QueryTelemetry(ctx context.Context, namespace, device } tenantDB, err := s.getTenantDB(ctx, namespace) if err != nil { + // Если DB не существует — тенант ещё не отправлял данные, это нормально + if isDBNotExistErr(err) { + return []TelemetryRow{}, nil + } return nil, fmt.Errorf("iotpg: get tenant DB for query: %w", err) } @@ -219,6 +225,17 @@ func (s *IoTPostgresStore) QueryTelemetry(ctx context.Context, namespace, device return result, rows.Err() } +// isDBNotExistErr проверяет что ошибка — «database does not exist» (PostgreSQL code 3D000). +// Используется в QueryTelemetry: если DB нет — просто нет данных, не ошибка системы. +func isDBNotExistErr(err error) bool { + var pqErr *pq.Error + if errors.As(err, &pqErr) { + // 3D000 = invalid_catalog_name (база данных не существует) + return pqErr.Code == "3D000" + } + return false +} + // Close закрывает все подключения (admin + tenant кэш). func (s *IoTPostgresStore) Close() error { s.tenants.Range(func(_, value any) bool {