Files
obsidian-vault/personal/projects/zulip-router.md
T

3.5 KiB

tags, status, created
tags status created
project
hermes
zulip
go
infra
deployed 2026-06-16

Zulip Router

Цель

Event-роутер между Zulip и несколькими Hermes-инстансами. Решает проблему конкурентного получения событий (Валера, Клавдий и другие боты видели все сообщения одновременно, reset срабатывал у всех).

Проблема (root cause)

  • Каждый Hermes-инстанс в polling-режиме регистрирует собственную event queue в Zulip
  • reset — системная команда Hermes, обрабатывается до хука whale-thread-guard
  • Нет механизма ownership топика между инстансами

Архитектура

Zulip Event Queue
    ↓ poll (valera-bot credentials)
[zulip-router]
    ├── @Валера → http://hermes-valera:8765/zulip-webhook
    └── @Клавдий → http://hermes-klavdiy:8765/zulip-webhook
         ↕ ownership: stream+topic → bot (TTL 24h, persisted to /data/ownership.json)

Hermes/Орёл — не трогаем, остаётся в polling-режиме.

Правила маршрутизации

  1. @Валера или @Valera в тексте → Валера (+ ownership обновляется)
  2. @Клавдий или @Klavdiy в тексте → Клавдий (+ ownership обновляется)
  3. Топик уже у кого-то → туда же (TTL refreshed)
  4. Новый топик без @mention → Валера (default)
  5. reset без @mention → уходит только к владельцу топика ✓

Код

~/docker/zulip-router/ — Go, ~260 LOC

Файл Назначение
main.go Poll loop, routing, dispatch
config.go Config struct + YAML loading + env var expansion
zulip.go Zulip API client (register_queue, get_events, long-poll)
ownership.go Topic ownership store (RW mutex + JSON persistence)
forwarder.go HTTP POST к Hermes webhook endpoints

Deployment

Compose: ~/docker/hermes/docker-compose.yml — сервис zulip-router

Env vars (~/docker/hermes/.env):

ZULIP_ROUTER_API_KEY=<valera-bot api key из ~/.hermes/profiles/valera/config.yaml>
ZULIP_WEBHOOK_TOKEN=zr-secret-2026

Запуск после заполнения .env:

cd ~/docker/hermes
docker compose up -d --force-recreate

Перезапуск после изменений в профилях:

docker compose restart hermes-valera hermes-klavdiy

Hermes профили

Валера и Клавдий переведены в webhook-режим:

platforms:
  zulip:
    webhook_port: 8765
    webhook_path: /zulip-webhook
    webhook_token: 'zr-secret-2026'

Токен должен совпадать с ZULIP_WEBHOOK_TOKEN в .env.

TODO

  • Заполнить ZULIP_ROUTER_API_KEY в ~/docker/hermes/.env
  • docker compose up -d --force-recreate
  • Проверить логи: docker compose logs -f zulip-router
  • Протестировать: написать @Клавдий и @Валера в отдельных топиках
  • Проверить ownership: обратиться в топик без @mention — должен отвечать последний бот
  • При необходимости: добавить Hermes/Орёл в роутер (отдельная задача)