mirror of
https://github.com/dartdavros/chatballs.git
synced 2026-10-05 09:14:58 +03:00
Ход AI выполнялся прямо в приёме сообщения: цикл опроса мессенджеров и HTTP-запрос виджета ждали провайдера, держа открытой транзакцию организации. Один ход — это два обращения к модели (эмбеддинг и чат) по тридцать секунд с двумя повторами, то есть до трёх минут, и всё это время ни одно входящее по всей установке не забиралось. Владелец видел это как «бот залипает»: сайт и MAX на одном агенте отвечали с задержками или молчали. Приём теперь доводит дело до записи сообщения и ставит событие `conversation.ai_turn_requested`. Ход считает роль событий воркера (`run_worker --role=events`) короткими транзакциями, между которыми остаются походы к провайдеру и в мессенджер. Туда же уехала расшифровка голосовых — последнее обращение наружу из цикла опроса. Воркер разделён на роли: `poller` опрашивает подключения и ведёт периодические работы (один экземпляр — курсоры и паузы после сбоя живут в его памяти), `events` разбирает outbox и масштабируется репликами (`CHATBALLS_EVENT_WORKERS`, по умолчанию две). Роль `all` осталась для разработки. Очередь событий научилась двум вещам: события одного диалога не выдаются параллельно (иначе два ответа приезжают клиенту вперемешку) и событие, взятое упавшим процессом, возвращается в очередь по истечении аренды. Попутно убраны мины, которые тот же залип и продлевали: - ход клиенту ограничен своим таймаутом (CHATBALLS_AI_TURN_TIMEOUT, 20 с) и сроком годности (CHATBALLS_AI_TURN_DEADLINE_SECONDS, 120 с) — просроченный ход не зовёт модель, а передаёт диалог оператору; - отказ провайдера по существу запроса (4xx, кроме 429) больше не повторяется трижды по таймауту; - предохранитель провайдера считает сбои по ключу «организация + интеграция», а не один на процесс: отозванный ключ одной организации гасил AI у всех; - потолок паузы после сбоя опроса — минута вместо четверти часа: он был компромиссом ради журнала однопоточного воркера. Виджет узнаёт, что ответ считается, по признаку `thinking` в ленте. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
196 lines
7.5 KiB
YAML
196 lines
7.5 KiB
YAML
# Override для локальной разработки (ADR-CHATBALLS-0028 §compose.dev).
|
||
# Применяется поверх canonical compose.yaml:
|
||
# docker compose -f compose.yaml -f compose.dev.yaml up
|
||
# Переопределяет image на build, dev-команды, bind mounts и host-порты.
|
||
# Не определяет отдельную production-топологию.
|
||
|
||
services:
|
||
# Секреты в dev генерирует тот же сервис на локально собранном backend-образе.
|
||
secrets:
|
||
build:
|
||
context: .
|
||
dockerfile: apps/backend/Dockerfile
|
||
|
||
postgres:
|
||
build:
|
||
context: .
|
||
dockerfile: deploy/docker/postgres.Dockerfile
|
||
ports:
|
||
- "${POSTGRES_HOST_PORT:-5432}:5432"
|
||
# Dev держит состояние в рабочем каталоге: базу видно, её легко снести
|
||
# и легко подсмотреть. В коробке это именованные тома (compose.yaml).
|
||
volumes:
|
||
- ./data/postgres:/var/lib/postgresql/data
|
||
|
||
redis:
|
||
ports:
|
||
- "${REDIS_HOST_PORT:-6379}:6379"
|
||
volumes:
|
||
- ./data/redis:/data
|
||
|
||
# Dev: migrate через init, без collectstatic (испечён только в prod-образе).
|
||
init:
|
||
build:
|
||
context: .
|
||
dockerfile: apps/backend/Dockerfile
|
||
environment:
|
||
# Dev-контур работает по http на localhost: без DEBUG включается
|
||
# SSL-redirect и SPA не может ходить в API. В коробке DEBUG выключен.
|
||
CHATBALLS_DEBUG: "true"
|
||
CHATBALLS_DELIVERY_MODE: ${CHATBALLS_DELIVERY_MODE:-CLOUD}
|
||
CHATBALLS_HELP_BASE_DOMAIN: localhost
|
||
CHATBALLS_HELP_PUBLIC_SCHEME: http
|
||
CHATBALLS_HELP_PUBLIC_PORT: ""
|
||
|
||
backend-app:
|
||
build:
|
||
context: .
|
||
dockerfile: apps/backend/Dockerfile
|
||
# Миграции выполняет one-shot init (CHATBALLS_DB_ROLE=migration); runtime-роль app
|
||
# не имеет прав на django_migrations, поэтому migrate здесь запускать нельзя.
|
||
command: uvicorn chatballs_backend.asgi_app:application --host 0.0.0.0 --port 8000 --reload
|
||
ports:
|
||
- "${BACKEND_APP_PORT:-8010}:8000"
|
||
environment:
|
||
# Dev-контур работает по http на localhost: без DEBUG включается
|
||
# SSL-redirect и SPA не может ходить в API. В коробке DEBUG выключен.
|
||
CHATBALLS_DEBUG: "true"
|
||
CHATBALLS_DELIVERY_MODE: ${CHATBALLS_DELIVERY_MODE:-CLOUD}
|
||
CHATBALLS_ALLOWED_HOSTS: "localhost,127.0.0.1,.localhost"
|
||
CHATBALLS_HELP_BASE_DOMAIN: localhost
|
||
CHATBALLS_HELP_PUBLIC_SCHEME: http
|
||
CHATBALLS_HELP_PUBLIC_PORT: ""
|
||
volumes:
|
||
- ./apps/backend:/app/apps/backend
|
||
- ./data/media:/app/apps/backend/media
|
||
depends_on:
|
||
init:
|
||
condition: service_completed_successfully
|
||
postgres:
|
||
condition: service_healthy
|
||
redis:
|
||
condition: service_healthy
|
||
|
||
backend-platform:
|
||
build:
|
||
context: .
|
||
dockerfile: apps/backend/Dockerfile
|
||
command: uvicorn chatballs_backend.asgi_platform:application --host 0.0.0.0 --port 8000 --reload
|
||
ports:
|
||
- "${BACKEND_PLATFORM_PORT:-8011}:8000"
|
||
environment:
|
||
# Dev-контур работает по http на localhost: без DEBUG включается
|
||
# SSL-redirect и SPA не может ходить в API. В коробке DEBUG выключен.
|
||
CHATBALLS_DEBUG: "true"
|
||
CHATBALLS_DELIVERY_MODE: ${CHATBALLS_DELIVERY_MODE:-CLOUD}
|
||
CHATBALLS_ALLOWED_HOSTS: "localhost,127.0.0.1,.localhost"
|
||
CHATBALLS_HELP_BASE_DOMAIN: localhost
|
||
CHATBALLS_HELP_PUBLIC_SCHEME: http
|
||
CHATBALLS_HELP_PUBLIC_PORT: ""
|
||
volumes:
|
||
- ./apps/backend:/app/apps/backend
|
||
|
||
backend-admin:
|
||
build:
|
||
context: .
|
||
dockerfile: apps/backend/Dockerfile
|
||
command: uvicorn chatballs_backend.asgi_admin:application --host 0.0.0.0 --port 8000 --reload
|
||
environment:
|
||
# Dev-контур работает по http на localhost: без DEBUG включается
|
||
# SSL-redirect и SPA не может ходить в API. В коробке DEBUG выключен.
|
||
CHATBALLS_DEBUG: "true"
|
||
CHATBALLS_DELIVERY_MODE: ${CHATBALLS_DELIVERY_MODE:-CLOUD}
|
||
volumes:
|
||
- ./apps/backend:/app/apps/backend
|
||
|
||
worker:
|
||
build:
|
||
context: .
|
||
dockerfile: apps/backend/Dockerfile
|
||
environment:
|
||
# Dev-контур работает по http на localhost: без DEBUG включается
|
||
# SSL-redirect и SPA не может ходить в API. В коробке DEBUG выключен.
|
||
CHATBALLS_DEBUG: "true"
|
||
CHATBALLS_DELIVERY_MODE: ${CHATBALLS_DELIVERY_MODE:-CLOUD}
|
||
volumes:
|
||
- ./apps/backend:/app/apps/backend
|
||
- ./data/media:/app/apps/backend/media
|
||
|
||
worker-events:
|
||
build:
|
||
context: .
|
||
dockerfile: apps/backend/Dockerfile
|
||
environment:
|
||
CHATBALLS_DEBUG: "true"
|
||
CHATBALLS_DELIVERY_MODE: ${CHATBALLS_DELIVERY_MODE:-CLOUD}
|
||
volumes:
|
||
- ./apps/backend:/app/apps/backend
|
||
- ./data/media:/app/apps/backend/media
|
||
|
||
# Dev: образ сервиса обновления собирается локально; сам сервис в dev
|
||
# бесполезен (стек поднят из исходников), но должен собираться и стартовать.
|
||
updater:
|
||
build:
|
||
context: .
|
||
dockerfile: deploy/docker/updater.Dockerfile
|
||
|
||
# Dev: frontend-сервис превращается в Vite dev-сервер internal-ui (HMR).
|
||
frontend:
|
||
build:
|
||
context: .
|
||
dockerfile: apps/internal-ui/Dockerfile
|
||
command: npm run dev -- --host 0.0.0.0 --port 5173
|
||
# В коробке frontend — nginx на 80, и его healthcheck нужен `up --wait`.
|
||
# Здесь это Vite на 5173: тот же тест был бы всегда красным.
|
||
healthcheck:
|
||
disable: true
|
||
environment:
|
||
# Direct Vite remains same-origin for cookies/CSRF and proxies only to the
|
||
# real local Django service. This variable exists only in dev compose.
|
||
VITE_DEV_API_TARGET: http://backend-app:8000
|
||
# Bind-mounts from the Windows host do not deliver inotify events into the
|
||
# container, so the watcher polls instead — otherwise HMR never fires.
|
||
VITE_DEV_POLL: "1"
|
||
ports:
|
||
- "${INTERNAL_UI_PORT:-5173}:5173"
|
||
volumes:
|
||
- ./apps/internal-ui:/app/apps/internal-ui
|
||
- ./packages:/app/packages
|
||
- /app/node_modules
|
||
- /app/apps/internal-ui/node_modules
|
||
|
||
# Dev-only: web-chat как отдельный Vite-сервер (в prod встроен в frontend-образ).
|
||
web-chat:
|
||
build:
|
||
context: .
|
||
dockerfile: apps/web-chat/Dockerfile
|
||
command: npm run dev -- --host 0.0.0.0 --port 5175
|
||
environment:
|
||
VITE_DEV_POLL: "1"
|
||
ports:
|
||
- "${WEB_CHAT_PORT:-5175}:5175"
|
||
volumes:
|
||
- ./apps/web-chat:/app/apps/web-chat
|
||
- ./packages:/app/packages
|
||
- /app/node_modules
|
||
- /app/apps/web-chat/node_modules
|
||
|
||
# Dev: gateway — nginx с local.conf вместо Caddy (та же маршрутизация, HMR-friendly).
|
||
gateway:
|
||
image: nginx:1.27-alpine
|
||
command: ["nginx", "-g", "daemon off;"]
|
||
ports:
|
||
- "80:80"
|
||
volumes:
|
||
- ./deploy/nginx/local.conf:/etc/nginx/conf.d/default.conf:ro
|
||
depends_on:
|
||
backend-app:
|
||
condition: service_healthy
|
||
backend-platform:
|
||
condition: service_healthy
|
||
frontend:
|
||
condition: service_started
|
||
web-chat:
|
||
condition: service_started
|
||
|