README
booblik — брокер сообщений на Kotlin/JVM с хранением в append-only логе. Документация разложена
по слоям: от «почему архитектура именно такая» к «как это устроено на проводе» и «что внутри
модуля».
[ Research — почему так; что проверено, что гипотеза ]
│
[ Feature — что делает система и зачем + BDD = критерии приёмки ]
│
[ Protocol — контракт на проводе ]
│
[ Service — зона ответственности модуля, грабли ]| Слой | Папка | Отвечает на вопрос |
|---|---|---|
| Research | research/ | почему архитектура именно такая; что проверено, что гипотеза |
| Feature | features/ | что делает система и зачем, BDD-сценарии = критерии приёмки |
| API | api/ | протокол на проводе |
| Service | services/ | зона ответственности модуля, конфиг, грабли |
Слоя screens/ нет: клиента с интерфейсом у брокера не бывает.
Оговорка про статус
Инвариант: main описывает то, что есть.
Закрыты все вехи, M0–M11: хранилище, сеть, протокол и клиент, эксплуатация, проверки
корректности, подписки и долгий FETCH, поставка (образ в GHCR, клиент в reposilite), образец
из четырёх сервисов. Сегмент, разреженный индекс, две реализации записи, партиция с роллингом
и retention, восстановление после рестарта, актор записи с батчами и групповым коммитом;
собственный acceptor на селекторе, бинарный протокол, FETCH мимо кучи; несколько топиков,
конвейерное соединение, Producer с накоплением, Consumer со своей позицией и подписка как
Flow; конфигурация с проверкой при старте, метрики, дистрибутив и образ со своей проверкой
здоровья. 104 теста — оба пути записи и оба транспорта прогоняются через один набор утверждений.
Потолок по проводу — 1,4 млн записей в секунду, брокер отдельным процессом, генератор на другой машине (замер 16). Раннее число 267 тысяч снималось со стендом внутри JVM брокера и им же и было ограничено.
Брокер запускается, обслуживает и переживает рестарт — это проверяет ci/smoke.sh в гейте.
Чего не будет: создания топиков (набор партиций задаётся при старте), TLS и сжатия — они несовместимы с zero-copy (§1.2), — и отставания потребителя в метриках: брокер не хранит позиции читателей.
Утверждения, которые по ходу работы перестали быть верными, — их стоит знать до чтения: барьер через маппинг оказался не барьером (§1.9), индексный файл не нужен (§1.10), короткий замер завышал маппинг в десять раз (§1.11), а zero-copy ничего не даёт ниже гигабайта в секунду (замер 7). Правьте по источнику, а не по памяти.
Ресёрч отделяет прогоны (скомпилировано и запущено) от чтения исходников и от гипотез. Правите утверждение — перепроверяйте источник, а не соседний документ.
Документы
Research
- research-architecture — проверенные факты, решения, риски.
Точка входа для любого, кто берётся за задачу. Две центральные посылки исходного драфта
здесь опровергнуты по исходникам: Kafka пишет лог не через mmap (§1.1), а Ktor не отдаёт
SocketChannel(§1.3). - research-usecases — за чем к брокеру приходят и что из этого строится в booblik, а что рядом с ним. Отвечает на вопрос про очередь задач: она не становится фичей брокера (Р11), а компактификация закрыта конструкцией — ключа нет на проводе (Р12).
- source-draft — исходный драфт задания, зафиксирован как есть. Не руководство к действию: расхождения разобраны в разделе 2 ресёрча.
Образец
- dev/ — четыре сервиса в
docker compose, показывающие booblik в работе: раздача партиций и позиция у потребителя, очередь задач как протокол поверх лога, проекция (read model) и ретранслятор в Kafka и обратно. Собирается от опубликованного клиента и образа, поэтому ловит дефекты поставки, которых не видит сборка «всё вместе»: так нашлись0.1.1(корутины вruntime) и0.1.2(аккумулятор терял запись).
Совместимость клиентов
- conformance/ — чем проверяется клиент на любом языке. Golden-вектора для двух алгоритмов, которых нет на проводе, но которые обязаны совпадать: партиционер (ключ до брокера не доходит) и CRC32C (на zero-copy-пути его проверяет только клиент). Плюс гарнесс из 13 проверок против живого брокера — со своей реализацией протокола, потому что проверять продюсера им же самим нечем. Контракт клиента и роли — там же; спецификация алгоритмов — §7 протокола.
Клиенты
- clients/ — паблишеры на Go, Python, Node.js и .NET (переписаны начисто,
ноль зависимостей) плюс Kotlin/Native — таргет, а не пятая реализация: он делит кодек с
JVM-клиентом через
:booblik-protocol. У каждого языка своя грабля в одной строке хеша, и это главный аргумент за golden-вектора.
Производительность
- benchmarking — методика, профиль рантайма, правила и все снятые числа. Веха не закрывается без строки в этом документе.
Features
- feature-subscribe-and-publish — подписка на топик
и публикация:
follow/replay, долгий FETCH, хендл топика с маршрутизацией по ключу. Веха M7 закрыта, документ описывает существующее поведение. - feature-append-and-fetch — записать в лог и прочитать по оффсету. Это весь брокер; всё остальное существует ради скорости этих двух операций.
API
- protocol-wire — бинарный протокол: кадр, PRODUCE, FETCH, коды ошибок.
Services
- booblik-core — хранение: сегмент, индекс, две записи,
transferTo. - booblik-client — клиент и общий кодек.
- booblik-net — провод: селектор, кодек, сессии, два транспорта.
- booblik-app — запуск: конфигурация, метрики, retention, дистрибутив.
- booblik-benchmark — числа: JMH и пробы.
Бэклог — ../BACKLOG.md, задачи M-NN по вехам M0…M11, все закрыты. Каждая
веха заканчивается строчкой итога: что вышло сверх плана и какая гипотеза не подтвердилась.
Соглашения
idво frontmatter = имя файла.- Главный потребитель — Claude Code. Каждый документ даёт якоря кода: путь к файлу, а не пересказ содержимого. Путь остаётся верным, копия протухает.
- Один документ = одна сущность.
- Числа в документах — только снятые прогоном, с указанием хоста и режима сброса. Без режима сброса число бессмысленно, а не неточно.
- Гипотезы называются гипотезами; отклонения от драфта называются отклонениями.
- Код по-английски, документация по-русски. Идентификаторы, имена задач Gradle и сообщения об ошибках — вербатим как в коде.