Commit Graph
18 Commits
Author SHA1 Message Date
Repinoid f99f49bd8e persistence: порядковая нумерация async SaveMessage (старое состояние не перезапишет новое) + очистка при удалении 2026-10-11 09:12:42 +03:00
Repinoid a08d58cba1 SQS: DeletePersist возвращает ошибку (500 при сбое Redis), fail-fast загрузка очередей, дефолты атрибутов при CreateQueue, защита SqsErrors от nil-deref 2026-10-11 08:56:49 +03:00
Repinoid b179ec6de7 persistence: Client → atomic.Pointer (устранение data race при reconnect) 2026-10-11 08:30:58 +03:00
Repinoid 9e0ad2c0a4 persistence: DeleteTenant чистит и tenant_ak (отзыв access key) 2026-10-11 08:27:22 +03:00
Repinoid 9f1242aca3 feat(aws-compat): queue attributes for Terraform (FifoQueue, ContentBasedDeduplication, Policy, real timestamps)
- GetQueueAttributes now returns FifoQueue, ContentBasedDeduplication, Policy and
  real Created/LastModifiedTimestamp (previously missing/stubbed '0000000000')
- Queue: add CreatedAt, LastModifiedAt, Policy, ContentBasedDeduplication
- parse FifoQueue/ContentBasedDeduplication in both protocols (StringToBool)
- Policy/RedriveAllowPolicy: normalize JSON-string form to object (JSON protocol
  sent them as string -> SetQueueAttributes failed with InvalidParameterValue)
- persistence: keep new fields in meta DTO + backfill empty timestamps on load
- FIFO dedup is inherent: IsDuplicate/InitDuplicatation gate on IsFIFO only
  (env flag EnableDuplicates=false disabled dedup for all FIFO queues)
2026-10-10 17:29:58 +03:00
Repinoid d7b3c653e0 feat(ha): leader-election via Redis lock + /ready endpoint (active/passive, off by default)
- app/leader: Elector (SETNX lock + PEXPIRE heartbeat via Lua, IsLeader)
- app/persistence: TryAcquireLock/RefreshLock/ReleaseLock (no-op when Redis absent)
- app/router: /ready -> 200 if ReadyFunc nil/true, else 503 (both planes)
- app/cmd: --leader-election / SHARED_SQS_LEADER_ELECTION, --leader-ttl, --leader-interval;
  ReadyFunc wired only when enabled, lock released on graceful shutdown
- default OFF: single-instance behaviour unchanged
2026-10-10 16:30:15 +03:00
Repinoid a341508b6d fix(batch): SendMessageBatch пишет в Redis синхронно (как SendMessage) + не персистит дубли; SaveMessagesSync 2026-10-10 16:18:54 +03:00
Repinoid 8e22bc4b9b feat(step3): тенанты read-through Redis (индекс accessKey→tenant, fallback в auth, бэкфилл на старте) 2026-10-10 16:09:52 +03:00
Repinoid c5b2c11f5d P1.2: индексация сообщений — tombstone-удаление O(1), receipt/uuid-индексы, tick по in-flight
- models.Queue: deadIdx/receiptIdx/uuidIdx/liveCount/deadCount + примитивы
  (AppendMessage/RemoveIndex/Compact/CompactIfNeeded/Reset/EnsureIndexes/
  IndexOfReceipt/IndexOfUUID/MarkInFlight/ClearInFlight/InFlightIndexes/LiveCount).
  Удаление — tombstone за O(1), физическая чистка амортизированная.
- DeleteMessage/ChangeMessageVisibility(±Batch): поиск по индексу вместо скана
  среза; удаление без сдвига остатка.
- DeleteMessageBatch: tombstone вместо полной пересборки среза.
- processQueueTick: visibility/DLQ по индексу in-flight (O(in-flight)),
  retention — tombstone, в конце — CompactIfNeeded.
- send-пути: AppendMessage + LiveCount (OOM-лимит по живым).
- admin/metrics/persistence: учёт живых сообщений, индексы после загрузки из Redis.
- Redis-схема не менялась (сообщения и так в per-message HASH).
2026-10-07 08:01:49 +03:00
Repinoid 31840b9756 fix: DLQ-релинк после загрузки из Redis + безопасная эвикция retention + ParseForm
1. DLQ больше не сериализуется вложенным объектом (была detached-копия после
   загрузки + неограниченная рекурсия при цикле): в метаданных хранится только
   имя (dead_letter_queue_name), после LoadAllQueues указатель релинкуется на
   объект из map. Закрывает потерянные переносы в DLQ и чужой мьютекс.
2. Retention-эвикция: компакция НА МЕСТЕ (чтение value в i, запись в n<=i)
   вместо kept := Messages[:0] — устранён алиасинг на переиспользуемом срезе.
3. countBatchEntries: явный req.ParseForm() — корректный msg_count для батчей.
Тесты: +DLQ-перенос, +эвикция с сохранением порядка; go test -race зелёный.
2026-10-07 07:18:31 +03:00
Repinoid fd8ffc329d P1.1: per-queue блокировки вместо глобального лока на операции с очередью
Все операции с содержимым очереди (send/receive/delete/visibility/purge/attributes/
tags/admin/gauge/tick) переведены на per-queue RWMutex (QueueStore.GetLocked/
GetRLocked + queue.LockMu). Глобальный SyncQueues-лок остался только для map и
неизменяемых полей. DLQ-переносы берут лок DLQ отдельно (порядок main→DLQ).
marshalQueueMeta больше не мутирует очередь (DTO-снапшот). Устранён дедлок
create_queue (setQueueAttributesV1 вызывается вне глобального лока). Добавлены
конкурентные тесты; go test -race зелёный. Снимает боттлнек: синхронный Redis-I/O
больше не держит глобальный лок.
2026-10-06 18:58:16 +03:00
Repinoid 07eace3c6b P2.8: Redis reconnect/health-check
Connect сохраняет параметры подключения и запускает фоновую проверку (ping каждые
30с). При обрыве Redis-клиент оставался не-nil и записи молча падали в лог; теперь
соединение восстанавливается автоматически через reconnect().
2026-10-06 18:18:06 +03:00
Repinoid c19a056de3 P0.3: синхронный персист SendMessage до ответа 200
Добавлен persistence.SaveMessageSync (синхронный HSet, возвращает ошибку).
SendMessage теперь пишет сообщение в Redis ДО возврата клиенту; при ошибке Redis
сообщение откатывается из памяти и возвращается InternalError (новая ошибка в
models/errors.go). Устраняет окно потери подтверждённого сообщения при краше пода
между 200 OK и асинхронной записью.
2026-10-06 18:04:22 +03:00
“Naeel” 9f69262b8c v0.1.35: фиксы — синхронные удаления в Redis (воскрешение очередей) + RedrivePolicy tenant-scoped DLQ 2026-08-15 08:57:25 +04:00
Naeel 4a83575491 feat: persist messages separately and update ingress docs 2026-04-12 08:44:46 +03:00
Naeel 3b4fe0bb3a security: address medium risks in jwt, redis ordering and body limit 2026-04-10 19:44:34 +03:00
Naeel e9a26f7975 v0.1.17: security hardening — 18/20 vulnerabilities fixed
Phase 1 (Critical):
- #1 JWT auth (done in v0.1.16)
- #2 Batch message size validation in send_message_batch.go
- #10 RLock in GetQueueUrlV1 (data race fix)

Phase 2 (AWS-compatible limits):
- #3 QueueName validation: max 80 chars, [a-zA-Z0-9_-](.fifo)?
- #4 WaitTimeSeconds clamped to 0-20
- #5 ReceiveMessageWaitTimeSeconds clamped to 0-20
- #6 DelaySeconds clamped to 0-900
- #7 VisibilityTimeout clamped to 0-43200
- #8 MaxNumberOfMessages clamped to 1-10
- #9 Message attributes limited to 10 per message
- #15 BatchEntryId length validated (max 80)
- #16 DeduplicationID length validated (max 128)
- #17 GroupID length validated (max 128)

Phase 3 (Per-tenant resource limits):
- #11 Max messages per queue (120K standard, 20K FIFO)
- #12 Global tenant limit (1000)
- #3.5 HTTP request body size limit (1MB via MaxBytesReader)

Phase 4 (Stability):
- #14 Duplicates map cleanup (already in PeriodicTasks)
- #13 FIFO group lock timeout (already in visibility timeout reset)
- #18 Redis size guard: skip save if >50MB

Skipped (Low, no real risk):
- #19 {account} URL param (informational only, not used for access)
- #20 ReceiptHandle format (self-validating UUID#UUID)

New file: app/gosqs/validation.go — centralized AWS SQS limits and validators
2026-04-10 18:58:40 +03:00
Naeel c3ba2dcae4 chore: initial import from sless/shared-sqs (v0.1.14)
- Standalone SQS-service repository
- Multi-tenant message queue service, AWS SQS compatible
- Based on GoAws, with mutable tenants, auth, WebUI, Redis persistence
- Ready for independent development and deployment
- See doc/ and README.md for architecture and usage
2026-04-10 16:47:27 +03:00