# 04. Queue Engine И Протокол Статус: не начат. Зависимости: 02, 03; ID/WAL интегрируются с 05. ## Цель Все операции над заданиями исполняются владельцем соответствующей tube; frontend сохраняет протокольный контракт без общей памяти и центрального глобального планировщика. ## Задачи 1. Отделить parsing/response I/O от мутаций queue engine в `prot.c`. Сохранить существующие heaps, списки и однотредовое исполнение владельца, не переписывая их на shared memory. 2. Удалить зависимость владения job от локального `Conn*` frontend. Использовать логическую сессию и локальное owner-side состояние. 3. Сделать глобальные реестры и счётчики локальными роли процесса. Один процесс-владелец может сохранить process-local globals, если они не смешиваются с frontend; не вводить контейнеры/абстракции без необходимости. 4. Перенести delayed jobs, pause и TTR в timer loop владельца. Согласовать reserve timeout и safety margin с управлением сессиями из 03. 5. Реализовать маршрутизацию всех команд по таблице; подтвердить завершение каждой команды только в согласованной точке состояния/WAL. 6. Сохранить проверки числовых диапазонов, framing body/CRLF, ошибки нехватки памяти и порядок ответов. 7. Реализовать явно выбранную реакцию на multi-watch reserve. Не запретить промежуточный `watch target` при подключении с `default`. ## Маршрутизация | Команды | Источник владельца/исполнитель | | --- | --- | | `use`, `watch`, `ignore` | Имена tubes и изменение ссылок сессии | | `put`, `peek-ready`, `peek-delayed`, `peek-buried`, `kick` | Текущая `use` tube | | `reserve`, `reserve-with-timeout` | Единственная наблюдаемая tube плюс состояние deadlines сессии | | `peek`, `delete`, `release`, `bury`, `touch`, `reserve-job`, `kick-job`, `stats-job` | Job ID; не текущая `use`/watch tube | | `pause-tube`, `stats-tube` | Явно указанное имя | | `list-tube-used`, `list-tubes-watched` | Подтверждённое состояние сессии frontend | | `list-tubes`, `stats` | Сбор данных владельцев/frontend по определённому контракту | | `quit` | Закрытие клиентской сессии и cleanup у всех затронутых owners | ## Совместимость - Priority/FIFO сохраняются внутри tube. Текущий `job_pri_less` использует `(priority, id)`; изменение ID требует доказательства эквивалентности или отдельного ordering field. - `reserve-job` не привязывается к watch list и сохраняет выбор ready/buried/delayed job по ID. - `delete` чужой reserved job недопустим, но ready/delayed/buried jobs доступны по прежним правилам. `release`, `bury`, `touch` проверяют сессию-владельца резервации. - Disconnect возвращает резервации в очереди; timeout во время передачи body не приводит к use-after-free. - `use` не меняет watch list, а `ignore` не освобождает уже зарезервированные jobs. - Недоступный owner не трактуется как пустая tube или отсутствующий job. Ответы `NOT_FOUND`/`TIMED_OUT` не подменяют отказ инфраструктуры. ## Статистика - Суммировать только действительно аддитивные job/command counters с определённым владельцем каждого счётчика. - Connection/producer/worker/waiting counters считают уникальные клиентские сессии, а не IPC endpoints и не число owner-side копий. - `list-tubes` объединяет реальные объекты, не все возможные имена, и не дублирует `default`. - Определить согласованность snapshot при конкурентных изменениях. Не обещать атомарный глобальный snapshot без реализации барьера. - Для `pid`, server `id`, `uptime`, `rusage-*` и binlog-полей применять контракт 01. Номера сегментов разных WAL нельзя бессмысленно суммировать. ## Приёмка - Каждая строка routing table имеет успешные, ошибочные и межвладельческие тесты, где применимо. - Полный lifecycle ready/reserved/delayed/buried и приоритеты проходят на двух и более owners. - `use` одной tube при watch другой корректен, в том числе если owners различны. - Один consumer может держать несколько jobs; смена watch/`reserve-job` не теряет старые резервации. - Нулевая/положительная задержка reserve, safety margin, `touch`, pause/unpause и disconnect соответствуют выбранному контракту. - Гонки reserve vs delete, timeout vs touch, pause vs reserve и disconnect vs reply не дают двух активных резерваций или двух ответов. - Исходный `make check` используется по матрице совместимости 01. Если выбран отдельный legacy-режим, он проходит весь прежний набор, включая multi-tube; ограничение нового режима не переносится на legacy. ## Точки Кода `prot.c`, `conn.c`, `job.c`, `tube.c`, `dat.h`, `testserv.c`, `testjobs.c`, `testheap.c`.