Мультиарендность и идемпотентность
AiHummer мультиарендный (multitenant): один шлюз может обслуживать много рабочих пространств из одной базы данных, сохраняя их данные раздельно. Арендатор (tenant) здесь — изолированное рабочее пространство со своими данными. Это безопасно благодаря двум механизмам — Postgres Row-Level Security (RLS) для изоляции чтения/записи и слою идемпотентности, чтобы повторы и восстановление обработки не дублировали реальный побочный эффект.
Тариф: изоляция арендаторов через Row-Level Security предоставляется в платном тарифе Enterprise — она не входит в бесплатную/Community-платформу; слой идемпотентности входит в ядро.
Изоляция арендаторов через Row-Level Security
Изоляция обеспечивается на уровне базы данных, а не только в коде приложения.
AiHummer выполняет запросы через ограниченную роль Postgres (aihummer_app),
к которой применены политики RLS, так что сама база отклоняет строки, не
принадлежащие активному арендатору.
RLS подключается опционально. Вы активируете его, передав шлюзу вторую строку подключения для ограниченной роли:
# gateway.env
# Owner-пул — выполняет миграции и привилегированное обслуживание
AIHUMMER_DATABASE_URL=postgres://aihummer:***@localhost:5432/aihummer?sslmode=disable
# Ограниченная роль — активирует RLS для обычного трафика запросов
AIHUMMER_DB_APP_URL=postgres://aihummer_app:***@localhost:5432/aihummer?sslmode=disable
[!NOTE] Для установок без контейнеров установщик задаёт
AIHUMMER_DB_APP_URLавтоматически, поэтому в стандартном развёртывании RLS включён по умолчанию. Если переменной нет, шлюз работает только на owner-пуле, и RLS не активен.
Ограничение по арендатору
В рамках ограниченной роли каждый запрос ограничивается своим арендатором:
шлюз выставляет контекст текущего арендатора для соединения, чтобы политики
RLS разрешались относительно нужного рабочего пространства. Фильтры
WHERE tenant_id = … не расставляются вручную повсюду — политика обеспечивает
это централизованно, а значит пропущенный фильтр не сможет утечь строки другого
арендатора.
Системный / bypass-режим
Часть работы законно межарендаторная — фоновые воркеры, планировщики и задачи обслуживания, действующие на уровне всего инстанса. Они работают в системном / bypass-режиме, чтобы видеть нужное. Bypass зарезервирован для доверенных внутренних воркеров, а не для путей обработки запросов.
[!WARNING] Миграции всегда выполняются на owner-пуле, никогда под ограниченной ролью. Owner-соединение имеет привилегии менять схему и применять политики RLS; ограниченная роль намеренно их не имеет. Держите две строки подключения раздельными и выдавайте роли
aihummer_appтолько необходимое.
Идемпотентные побочные эффекты
Обработка запроса (turn) может порождать реальные побочные эффекты: отправку почты, отправку сообщения обратно в канал. Если обработка повторяется — из-за временной ошибки или из-за того, что шлюз перезапустился посреди обработки и восстановление её переигрывает, — эти эффекты не должны произойти дважды. AiHummer обеспечивает это двумя взаимодействующими элементами.
Стабильный ключ реестра, сохраняющийся при возобновлении
Каждый побочный эффект записывается под стабильным ключом реестра, сохраняющимся при возобновлении: ключ детерминированно выводится из обрабатываемого запроса, поэтому переигрывание того же запроса вычисляет тот же ключ, а не новый. Реестр помнит, какие ключи уже были отработаны.
Барьер побочных эффектов
Прежде чем будет выполнен эффект вроде почты или отправки в канал, он проходит через барьер побочных эффектов, который сверяется с реестром. Если этот ключ уже срабатывал, барьер обнаруживает уже выполненное действие и не запускает его повторно; если нет — эффект выполняется, а ключ фиксируется.
запрошен побочный эффект
└─▶ вычислить стабильный ключ реестра
└─▶ барьер: ключ уже зафиксирован?
├─ да ─▶ пропустить (без двойной отправки)
└─ нет ─▶ выполнить эффект ─▶ зафиксировать ключ
В итоге внешнее поведение — выполнение не более одного раза для одного стабильного ключа, хотя внутренняя доставка работает с повторами до подтверждения. В пределах одного ledger и стабильного ключа повторное выполнение блокируется; внешняя система всё равно должна поддерживать идемпотентность, если подтверждение результата может потеряться. Повторы безопасны по построению — именно это позволяет восстановлению обработки (см. Надёжную доставку и восстановление) переиграть прерванный запрос без того, чтобы клиент получил то же письмо или тот же ответ дважды.
[!TIP] Поэтому AiHummer может предлагать надёжную доставку с повторами и автоматическое восстановление обработки без обычного риска дублей — идемпотентность и есть фундамент, на котором строится доставка.
Куда дальше
- Движок, ведущий обработку запроса: Шлюз и движок обработки запросов.
- Как ответы возвращаются без дублей: Надёжная доставка и восстановление.