AiHummer
Русский
ВойтиЛичный кабинет
v1.1.x
{ }Swagger

Мультиарендность и идемпотентность

v1.1.x · обновлено 2026-07-21

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 может предлагать надёжную доставку с повторами и автоматическое восстановление обработки без обычного риска дублей — идемпотентность и есть фундамент, на котором строится доставка.

Куда дальше