Initialize
Continous integration / Tests (push) Canceled after 0s
Testing clients / Build beanstalkd (push) Canceled after 0s
Continous integration / Docker build (push) Canceled after 0s
Testing clients / Test Pheanstalk PHP (push) Canceled after 0s
Testing clients / Test Greenstalk Python (3.9) (push) Canceled after 0s
Testing clients / Test Pystalk Python (3.10) (push) Canceled after 0s
Continous integration / Tests (push) Canceled after 0s
Testing clients / Build beanstalkd (push) Canceled after 0s
Continous integration / Docker build (push) Canceled after 0s
Testing clients / Test Pheanstalk PHP (push) Canceled after 0s
Testing clients / Test Greenstalk Python (3.9) (push) Canceled after 0s
Testing clients / Test Pystalk Python (3.10) (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# Критический Контекст
|
||||
|
||||
## Статус И Источники
|
||||
|
||||
- Здесь находится исходный Beanstalkd 1.13 на C99. Многопроцессная архитектура ниже принята как направление доработки, но ещё не реализована.
|
||||
- Постановка: [epics/00-overview.md](epics/00-overview.md). Открытые решения перечислены в [epics/01-contract.md](epics/01-contract.md); не считать их уже утверждёнными.
|
||||
- Исходные контракты: `README.md`, `doc/protocol.txt`, `doc/beanstalkd.ronn`, `doc/beanstalkd.1`. Каталог называется `doc`, не `docs`.
|
||||
- `doc/beanstalkd.1` и HTML генерируются из `doc/beanstalkd.ronn`. При изменении CLI обновлять исходник руководства и производные документы штатным способом.
|
||||
- Сохранять приоритеты проекта: стабильность, исправление ошибок, ясность, затем производительность; см. `CONTRIBUTING.md`.
|
||||
|
||||
## Принятое Решение
|
||||
|
||||
- Архитектура: процессы-владельцы групп tubes на одном хосте, frontend для TCP/протокола, IPC между frontend и владельцами, supervisor для управления процессами.
|
||||
- Каждая tube имеет одного владельца; один владелец обслуживает несколько tubes. Все изменения её заданий и планирование выполняются последовательно в event loop владельца.
|
||||
- У каждого owner slot отдельные состояние в памяти и WAL. Owner slot является стабильным логическим идентификатором, а не PID.
|
||||
- На первом этапе consumers не резервируют задания одновременно из нескольких наблюдаемых tubes. Допускается временный watch list из нескольких tubes при настройке, например `watch target`, `ignore default`. На момент `reserve` / `reserve-with-timeout` наблюдаемая tube должна быть одна.
|
||||
- Реакция на неподдерживаемый multi-watch reserve требует явного протокольного решения. Нельзя молча выбрать одну tube или выдать выдуманный стандартный ответ.
|
||||
- Одна наблюдаемая tube не означает один job, одну резервацию или одного владельца на всё время TCP-сессии. Переключение watch list и `reserve-job` могут оставить у сессии резервации разных владельцев. Не вводить дополнительные ограничения без согласования.
|
||||
- Одна горячая tube остаётся последовательной. Масштабируется совокупность независимых tubes, а не выполнение пользовательских задач внешними consumers.
|
||||
|
||||
## Владение Динамическими Tubes
|
||||
|
||||
- Постоянный дескриптор каждой tube не нужен. Объект появляется при `use`, `watch`, инициализации `default` или восстановлении заданий и удаляется после исчезновения удерживающих ссылок.
|
||||
- Задание в любом живом состоянии, включая reserved, удерживает tube. Ссылки от удалённых сессий должны учитываться у владельца; авария frontend должна их освобождать.
|
||||
- Владение определяется до создания объекта: `partition = stable_hash(tube_name) % PARTITION_COUNT`, затем `owner_slot = partition_map[partition]`.
|
||||
- Алгоритм hash, параметры, число разделов и карта одинаковы у всех процессов и стабильны между перезапусками с данными. Их точный формат задаётся в эпиках 01 и 02.
|
||||
- Конкурентный claim отдельной tube не нужен: все обращения с одним именем попадают одному владельцу; он локально выполняет find-or-create.
|
||||
- Маршрутизация сама по себе ничего не создаёт. Например, `stats-tube` и `pause-tube` неизвестного имени должны сохранить `NOT_FOUND`.
|
||||
- Жизненный цикл объекта tube не меняет принадлежность имени. Повторное создание использует того же владельца.
|
||||
- Одновременно активен не более одного процесса на owner slot. При падении перезапускается тот же slot; нельзя направлять его имена к другому живому владельцу как обычный failover.
|
||||
- Карта распределения фиксирована на первом этапе. `hash(name) % live_process_count`, автоматический rebalance и переназначение при сбое запрещены. Миграция требует отдельной процедуры.
|
||||
|
||||
## Инварианты Реализации
|
||||
|
||||
- Не передавать `Job*`, `Tube*`, `Conn*`, `File*` через IPC. Использовать сериализуемые ID, поколения процессов/сессий и явное владение данными.
|
||||
- Сохранять последовательность команд и ответов на TCP-соединении, текущие проверки владения резервацией, priority/FIFO внутри tube, delay, TTR, timeout, `DEADLINE_SOON` и освобождение резерваций при disconnect.
|
||||
- У задания не может быть двух действующих резерваций; один запрос reserve даёт не более одного результата. Повторное выполнение внешним consumer после TTR допустимо: exactly-once не обещается.
|
||||
- ID должны быть уникальны в логическом сервере, маршрутизируемы и безопасны при частичном перезапуске. `job_pri_less()` использует ID для FIFO; новый формат ID не должен нарушать порядок внутри tube.
|
||||
- IPC обязан иметь framing, лимиты памяти, backpressure, отмену ожиданий и защиту от устаревших сообщений. Не повторять автоматически `put` или другую мутацию с неизвестным результатом.
|
||||
- Смерть владельца, frontend и supervisor является частью контракта, а не только эксплуатационной деталью. Недоступность владельца не равна `NOT_FOUND`.
|
||||
- Не делить существующий WAL между независимыми writers и не снимать блокировку каталога ради многопроцессности. Изменение `Jobrec` требует следовать правилам `Walver` в `dat.h`.
|
||||
- Не обещать более сильную durability, чем реализует выбранный режим `-b`, `-f`, `-F`. Успешный IPC-ответ сам по себе не означает fsync.
|
||||
- Политика сохранения отдельного legacy-режима, включения новой архитектуры и переноса старого WAL согласуется в эпике 01 до изменения запуска и форматов. Не считать поддержку двух режимов уже утверждённым объёмом и не ломать существующее поведение/данные без явного решения.
|
||||
|
||||
## Карта Кода
|
||||
|
||||
| Область | Файлы и точки |
|
||||
| --- | --- |
|
||||
| Запуск и event loop | `main.c`, `serv.c:srvserve`, платформенные `linux.c`, `darwin.c`, `freebsd.c`, `sunos.c` |
|
||||
| Протокол, scheduler, timers | `prot.c:dispatch_cmd`, `process_queue`, `prottick`, `conn_timeout` |
|
||||
| Сессии и резервации | `conn.c:conn_reserve_job`, `connclose`, `dat.h:Conn` |
|
||||
| ID и jobs | `job.c:next_id`, `all_jobs`, `job_pri_less`; `dat.h:Job`, `Jobrec` |
|
||||
| Динамические tubes | `tube.c:tube_find_or_make`, `tube_iref`, `tube_dref` |
|
||||
| WAL и восстановление | `walg.c`, `file.c`, `serv.c:srv_acquire_wal`, `prot.c:prot_replay` |
|
||||
| Тесты | `testserv.c`, `testjobs.c`, `testheap.c`, `testms.c`, `testutil.c`, `ct/` |
|
||||
|
||||
## Проверки
|
||||
|
||||
- Сборка: `make`; регрессии: `make check`; существующие микробенчмарки: `make bench`.
|
||||
- Команды требуют поддерживаемого Unix-окружения и toolchain. Нативный Windows не заявлен как поддерживаемая платформа; наличие WSL/контейнеров проверять, а не предполагать.
|
||||
- `make bench` не заменяет end-to-end нагрузочный тест многопроцессного сервера.
|
||||
- Для каждой реализации проверять один и несколько owner slots, ошибки IPC, disconnect, TTR, аварии и восстановление WAL. Критерии: `epics/07-validation.md`.
|
||||
- Не выдавать статический анализ за измеренный выигрыш и не отмечать эпики завершёнными без проверок.
|
||||
Reference in New Issue
Block a user