- run.sh: start/stop/restart/status/logs for the whole stack, JAVA_BIN override, pinned to /usr/lib/jvm/java-21-openjdk (Java 25 breaks logback ThrowableProxy inside fat jars and kills Tomcat threads) - -Xmx320m per service, health-gated startup, logs/ dir (gitignored) - README: requirements, run.sh workflow, full current feature list - verified: 25-round load test across all pages under JDK 21 — 0 failures
5.2 KiB
5.2 KiB
LMS
Микросервисная система для проведения практических занятий (Kotlin + Spring Boot + PostgreSQL 18).
Модули
libs/common-http— общий формат ошибок и обработчик исключений.libs/security-jwt— выпуск/проверка JWT (RSA) иPasswordEncoder.libs/markdown— серверный рендер markdown со спойлерами и санитизацией.libs/test-support— общая тестовая инфраструктура (Testcontainers,postgres:18).services/identity-service— аккаунты, студенты, группы, зачисления (схемаidentity).services/academic-service— курсы, статьи, лабораторные, уровни, варианты (схемаacademic).services/progress-service— уровни студентов, распределение вариантов, работы, оценки (схемаprogress).services/gateway— Spring Cloud Gateway, маршрутизация и проверка JWT.web— серверный веб-интерфейс (Thymeleaf + htmx), BFF.
Требования
- JDK 21 (runtime) + Docker (для PostgreSQL 18). Gradle сам скачает toolchain 21 для сборки.
- Не запускать сервисы на JAVA_HOME=Java 25: на 25 ломается logback внутри
fat-jar (NoClassDefFoundError
ThrowableProxy), что роняет потоки Tomcat. Скриптrun.shиспользует JDK 21 автоматически.
Запуск
./gradlew bootJar -x test # собрать все сервисы
./run.sh start # поднять БД + все 5 сервисов на JDK 21
./run.sh status # проверить здоровье
./run.sh logs web # посмотреть лог сервиса
./run.sh stop | restart
Можно и без скрипта: docker compose up -d postgres, затем
/usr/lib/jvm/java-21-openjdk/bin/java -jar <jar> для каждого сервиса,
или ./gradlew :services:identity-service:bootRun и т.д. по одному.
Порты по умолчанию: gateway :8080, identity :8081, academic :8082,
progress :8083, web :8090. Интерфейс: http://localhost:8090.
Текущий функционал
Открыть http://localhost:8090. При первом запуске создаётся аккаунт
администратора (/setup); далее — вход по логину и паролю.
- Доступ: JWT (RSA, ключи identity генерирует при первом старте и хранит в БД), проверка токена на gateway, роли ADMIN/STUDENT, CSRF на всех POST-формах, session fixation-защита; вход студента с обязательной сменой пароля.
- Группы и студенты: создание groups, импорт
.xls/.xlsx/.csv, ручное добавление студента (генерация пароля), выгрузка логинов XLSX/CSV, сброс пароля; на странице группы — баллы по каждой лабе и средний балл. - Лабораторные: импорт ZIP (
lab.yaml+README.md+variants/*.mdc front-matter) и старого JSON; создание через UI с произвольным числом уровней; просмотр/редактирование условия (markdown), вариантов, дат; статусы draft/published (клик по бейджу меняет); даты выводятся в московском времени. - Распределение вариантов: по уровню студента на лабу (по умолчанию — самый простой), round-robin с уникальностью в группе; ручное назначение варианта.
- Материалы (
/learn, публичная читалка): главы → разделы → статьи в markdown (код, спойлеры, картинки; санитизация OWASP); импорт ZIP (chapters/N-глава/N-раздел/N-статья.md+assets/); создание/переименование/ удаление глав, разделов, статей; перенос статей между разделами. - Студент: видит опубликованные лабы, свой вариант с條件ем (markdown), сроки сдачи/защиты и оценки.
- UI: светлая/тёмная тема (сохраняется в localStorage), модальные окна вместо отдельных страниц, фавиконка, адаптивная вёрстка без inline-стилей.
Сборка и тесты
./gradlew build # сборка всех модулей
./gradlew check # тесты и проверки
Переменные окружения для БД: LMS_DB_URL, LMS_DB_USER, LMS_DB_PASSWORD.