Skip to content

feat(backend): модульный монолит в одной JVM - #136

Merged
malilex merged 4 commits into
devfrom
feature/backend-monolith
Nov 2, 2026
Merged

malilex merged 4 commits into
devfrom
feature/backend-monolith

Conversation

@malilex

@malilex malilex commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Зачем

Backend DS Builder требовал нескольких прикладных JVM-процессов и nginx.
Монолит упрощает сборку и запуск, сохраняя границы подсистем для будущего разделения.

Что сделано

Backend: одно приложение с модульной структурой

  • Добавлен backend-kt/app, объединяющий identity, projects, ds и documentation в одной JVM.
  • Подсистемы предоставляют библиотечные runtime; вызовы между ними используют адаптеры через DI.
  • Ресурсы имеют уникальные пространства имён и единые источники, БД остаются раздельными.
  • Добавлены готовность подсистем, управляемая остановка и ограниченный параллелизм workers.

Публичный вход: маршруты и авторизация внутри приложения

  • Сохранены публичные API, CORS, потоковые лимиты тела и проксирование Keycloak без nginx.
  • Size tokens переведены на публичный префикс и проверенный контекст.
  • Неизвестные префиксы закрыты; при запуске проверяется дерево зарегистрированных маршрутов.
  • DS требует явно выбранного адаптера входа; самостоятельные launcher'ы сохранены.
  • Общие IP-лимиты частоты и соединений оставлены внешней инфраструктуре.

Docker и CI: единый прикладной сервис

  • Compose запускает один backend с отдельными Keycloak, PostgreSQL и MinIO.
  • Production backend сохраняет сетевой alias gateway.
  • BACKEND_PUBLIC_URL необязателен: по умолчанию используется origin из KEYCLOAK_ISSUER.
  • App получил собственный бюджет сборки: Gradle 1 GiB, Kotlin daemon 2 GiB, максимум два workers.
  • OpenSpec синхронизирован и change архивирован.

Как проверено

  • Backend: ./gradlew verifyFast, ./gradlew verifyFull и Strictacode compare прошли.
  • App и зависимости повторно скомпилированы без build cache: 46 выполненных задач.
  • Проведено независимое ревью исправлений авторизации, границы маршрутов и конфигурации.
  • Изолированный Docker-контур стал healthy; прошли 48 HTTP-проверок, включая отказы
    для поддельных заголовков и внутренних путей, отсутствие общего IP-лимита и чтение
    size tokens с настоящим JWT.
  • Проверены production Compose alias и запуск конфигурации без отдельного публичного URL.
  • Изменённая спецификация backend-monolith-runtime проходит строгую валидацию.

Что важно знать

  • Общая валидация OpenSpec: семь унаследованных предупреждений в спецификациях из
    dev блокируют общий tools/verify gate; backend-проверки выполнены отдельно.
  • CI: прежние backend-app jobs падали из-за памяти компилятора. Исправление проверено
    локальной повторной компиляцией; результат нового GitHub Actions запуска ещё ожидается.
  • Локальные данные: первый монолитный запуск использует новый набор томов
    monolith_* без adopt; повторные запуски сохраняют эти данные.
  • Серверные данные: PostgreSQL и MinIO остаются внешними, с раздельными БД.
    Фактическая выкладка и переход серверного окружения требуют отдельного выполнения.
  • Публичный трафик: общие ограничения по IP настраиваются на внешнем reverse proxy.
  • Локальный setup: генерация web API meta пока требует зависимостей js/cli;
    клиент продолжает запускаться отдельным Compose.
  • nginx-конфиги: сохранены как исторический снимок; актуальный контракт находится
    в OpenSpec и тестах приложения.

Не входит

  • Legacy Publisher и его перенос в монолит.
  • Объединение локального Compose клиента с backend.
  • Публикация образов и переключение production.

OpenSpec

  • Архив: openspec/changes/archive/2026-10-27-add-backend-monolith-runtime.

@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d75c6811-b135-42cf-93ae-9235ab43481c
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@vkaltyrin vkaltyrin self-assigned this Oct 27, 2026
@neretin-trike

Copy link
Copy Markdown
Collaborator

Вот такие моментики агент нашёл:

  1. StatusPages в Ktor не умеет работать на уровне маршрута. Это плагин уровня приложения, а ContentNegotiation как раз route-scoped. Поэтому фраза «аналогично локализуются StatusPages» требует конкретного решения: один StatusPages с обработчиками по типам исключений каждой подсистемы или перехват на уровне маршрутов.

  2. База Exposed по умолчанию. Каждый Database.connect перезаписывает default в TransactionManager. В ds таких вызовов два: PostgresDatabasePool.kt:81 и ExposedPublicationTransactionRunner.kt:31. В монолите к ним добавятся ещё projects и documentation. В дизайне это упомянуто размыто («потенциальный неявный выбор подключения»). Нужна конкретная защита: тест или detekt-правило против transaction {} без db, либо «отравленная» база по умолчанию после старта.

  3. projects читает конфиг по общим ключам. projects-service/core/.../DatabaseProvider.kt берёт config.property("database.url"). Именно на этом ключе в общем ApplicationConfig всё и столкнётся. Стоит прямо записать это в задачу 2.1 как пример, который обязательно перевести на типизированный конфиг.

  4. Память одной JVM. Загрузки документации до 101 MB и распаковка архивов идут в одной куче с ds и SSE. В требованиях к Docker стоит задать -XX:MaxRAMPercentage или лимит памяти контейнера. Сейчас в рисках сказано только «OOM положит всё».

  5. RuntimeHandle. AutoCloseable и stop(gracePeriod) дублируют друг друга. А checks: Map<String, Boolean> теряет причину отказа, хотя спека требует диагностику по каждой подсистеме.

@vkaltyrin

Copy link
Copy Markdown
Contributor

ok

@malilex
malilex force-pushed the feature/backend-monolith branch from c1a2713 to fe0d643 Compare October 28, 2026 14:18
@vkaltyrin vkaltyrin removed their assignment Oct 28, 2026
Comment thread docker-compose.prod.yml Resolved
@malilex
malilex force-pushed the feature/backend-monolith branch from fe0d643 to 4dd9a85 Compare October 29, 2026 14:07
@malilex malilex changed the title docs(openspec): проект монолитной сборки backend feat(backend): модульный монолит в одной JVM Oct 29, 2026
@malilex
malilex force-pushed the feature/backend-monolith branch from 4dd9a85 to 67515b2 Compare October 29, 2026 14:37
@vkaltyrin
vkaltyrin self-requested a review October 30, 2026 07:12
@malilex
malilex requested a review from angirb October 30, 2026 07:14
@malilex

malilex commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator Author

@neretin-trike, по замечаниям выше:

Все пять пунктов учтены в реализации и OpenSpec.

  1. StatusPages устанавливается один раз на приложение, с обработчиками типизированных ошибок и общим безопасным ответом для технических сбоев. ContentNegotiation изолирован по маршрутам подсистем.

  2. Добавлен ExplicitDatabaseTest: проверяет production-код включённых подсистем и запрещает Exposed-транзакции без явно указанной БД, в том числе db = null. Вызовы используют именованный db, а публикация DS разделяет его существующий пул.

  3. Projects получает отдельный ApplicationConfig из собственного namespaced defaults.yaml, поэтому database.url не пересекается с настройками других подсистем. Изоляция покрыта тестом. Полную переработку в типизированную модель конфигурации не вводили.

  4. В обоих Compose по умолчанию BACKEND_MEMORY_LIMIT=2g, образ и Compose задают JAVA_TOOL_OPTIONS=-XX:MaxRAMPercentage=60.0. Оба значения переопределяются; в README описан запас для памяти вне heap и бюджет пулов БД.

  5. У RuntimeHandle уточнены обязанности: stop(gracePeriod) отменяет работу, ограниченно ожидает завершения и освобождает ресурсы через close(); close() — идемпотентное освобождение без ожидания, в том числе при неполном запуске. Map<String, Boolean> сохранили как минимальный безопасный формат, но БД и S3 документации проверяются и отображаются раздельно. Подробные исключения публично не раскрываются. Поведение остановки и readiness покрыто тестами.

Backend FAST/FULL, Strictacode и независимое ревью прошли. После последнего ребейса также прошли 50 HTTP-проверок на изолированном Docker-контуре.

* docs(openspec): plan editor and catalog loading optimizations

* fix: optimize editor and catalog data loading
@malilex
malilex merged commit c6c66b3 into dev Nov 2, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants