Pin runtime to JDK 21 via run.sh; document full feature set

- 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
This commit is contained in:
2026-09-11 22:08:50 +03:00
parent 8336c5a9b2
commit f5b9fc27ce
13 changed files with 332 additions and 20 deletions

View File

@@ -16,36 +16,53 @@
## Требования
- JDK 21+ (сборка использует toolchain 21)
- Docker (для PostgreSQL 18)
- JDK 21 (runtime) + Docker (для PostgreSQL 18). Gradle сам скачает toolchain 21 для сборки.
- **Не запускать сервисы на JAVA_HOME=Java 25**: на 25 ломается logback внутри
fat-jar (NoClassDefFoundError `ThrowableProxy`), что роняет потоки Tomcat.
Скрипт `run.sh` использует JDK 21 автоматически.
## Запуск
```bash
cp .env.example .env
docker compose up -d postgres
./gradlew :services:identity-service:bootRun
./gradlew :services:academic-service:bootRun
./gradlew :services:progress-service:bootRun
./gradlew :services:gateway:bootRun
./gradlew :web:bootRun
./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`. Проверка: `GET :8080/actuator/health`.
progress `:8083`, web `:8090`. Интерфейс: `http://localhost:8090`.
## Текущий функционал
Открыть `http://localhost:8090`. При первом запуске будет предложено создать
аккаунт администратора (`/setup`); далее — вход по логину и паролю.
- вход администратора и студентов, обязательная смена пароля при первом входе;
- группы: создание, импорт студентов из `.xls/.xlsx/.csv`, выгрузка логинов и
паролей в XLSX/CSV, сброс пароля студента;
- JWT (RSA, ключи генерируются при первом старте identity и не хранятся в репозитории),
проверка токена на gateway, роли ADMIN/STUDENT.
Открыть `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/*.md` c
front-matter) и старого JSON; создание через UI с произвольным числом уровней;
просмотр/редактирование условия (markdown), вариантов, дат; статусы
draft/published (клик по бейджу меняет); даты выводятся в московском времени.
- **Распределение вариантов**: по уровню студента на лабу (по умолчанию — самый
простой), round-robin с уникальностью в группе; ручное назначение варианта.
- **Материалы** (`/learn`, публичная читалка): главы → разделы → статьи в
markdown (код, спойлеры, картинки; санитизация OWASP); импорт ZIP
(`chapters/N-глава/N-раздел/N-статья.md` + `assets/`); создание/переименование/
удаление глав, разделов, статей; перенос статей между разделами.
- **Студент**: видит опубликованные лабы, свой вариант с條件ем (markdown),
сроки сдачи/защиты и оценки.
- UI: светлая/тёмная тема (сохраняется в localStorage), модальные окна вместо
отдельных страниц, фавиконка, адаптивная вёрстка без inline-стилей.
## Сборка и тесты