diff --git a/HISTORY/2026-10-11-session-log.md b/HISTORY/2026-10-11-session-log.md index a5adbc6..ba18520 100644 --- a/HISTORY/2026-10-11-session-log.md +++ b/HISTORY/2026-10-11-session-log.md @@ -54,11 +54,15 @@ | 🟢 | `app/utils/utils.go` | `SqsErrors[errKey]` без проверки → nil-deref на неизвестном ключе | `5d38118` | | (🟡 new) | `app/gosqs/create_queue.go` | Очередь из API получала `VisibilityTimeout=0` и пр. (дефолты не подставлялись) | `5d38118` | -### Осознанно НЕ менялось (решения владельца/архитектуры) +### Осознанно НЕ менялось — РЕШЕНИЯ (2026-10-11) -- 🟡34 (атрибуты «0 = не передано») — не менять совместимость. -- 🟡37 (дефолт `SHARED_SQS_MAX_HEAP_MB`) — число зависит от RAM ВМ, решает владелец. -- 🟡28 (не держать `queue.mu` во время сетевых вызовов) — **не сделано**: см. п.4. +- 🟡34 (атрибуты «0 = не передано»): **решение — не менять** совместимость. + Различать «не передано» и явный 0 потребовало бы перевести `QueueAttributes` + на указатели — ломает JSON-протокол и Terraform-drift. Явный 0 — редкий сценарий. +- 🟡37 (дефолт `SHARED_SQS_MAX_HEAP_MB`): **решение — оставить выключенным (0)**. + Безопасное число зависит от RAM конкретной ВМ и числа тенантов — выбор владельца, + не хардкод в коде. +- 🟡28 (сеть под `queue.mu`): **решение — оставить как есть (вариант A)**. См. п.4. ## 3. Уточнение выводов ревьюера @@ -80,14 +84,21 @@ `Duplicates` (🟡33) фактически не воспроизводился в текущем коде — но защита добавлена как дешёвая страховка. -## 4. Осталось (требует решения/отдельного захода) +## 4. 🟡28 — РЕШЕНИЕ (2026-10-11) -- **🟡28** (`send_message.go:150`, `delete_message.go`, `gosqs.go`): синхронный - `SaveMessageSync` (до 3 с) выполняется под `queue.mu`. Простой вынос сети за - `mu` **вносит регрессию**: между `Unlock` и повторным `Lock` появляется окно, - в котором два конкурентных `SendMessage` с одним `deduplicationId` оба пройдут - `IsDuplicate` (дубль), либо при откате `dedup` теряется. Корректное решение - требует более сложной синхронизации — отложено до отдельного захода. +- **Проблема**: синхронный `SaveMessageSync` (до 3 с) выполняется под `queue.mu` + (`send_message.go:150`, `delete_message.go`, `admin.go`). Медленный Redis блокирует + всю очередь. +- **Варианты**: A) оставить; B) укоротить таймаут Redis-записи; C) полный рефакторинг + с per-message синхронизацией. +- **Выбрано A — оставить.** Обоснование: + 1. in-memory ядро очередей — одиночка, блокировка `queue.mu` локальна (одна очередь). + 2. Синхронный персист под `mu` = гарантия «нет потери подтверждённого сообщения + при крахе пода» — приоритет проекта (надёжность, а не масштабирование). + 3. Вынос сети за `mu` вносит окно между `Unlock`/`Lock`: два конкурентных + `SendMessage` с одним `deduplicationId` оба пройдут `IsDuplicate` (дубль), + либо при откате `dedup` теряется сообщение — хуже кратковременной блокировки. + 4. Redis-авария — глобальная: деградирует всё, 2–3 с на очередь не критично. - 🟡34/🟡37 — см. п.2. ## 5. Верификация