Skip to content

v0.2.0

Choose a tag to compare

@onixus onixus released this 13 Aug 15:44
· 371 commits to main since this release
b40b73e

Производительность списков и выгрузки. Аудит выявил три подтверждённые проблемы — все три исправлены в #43.

База данных

В схеме не было ни одного индекса, а SQLite, в отличие от PostgreSQL, не индексирует внешние ключи автоматически. Каждая выборка стадий и рисков расчёта, полей шаблона и поиск активного шаблона шли полным сканом таблицы.

Индексы добавлены строго под запросы, которые есть в коде — лишние только замедляют запись:

Модель Индекс
Stage, Risk [calculationId, order]
FormField, StageTemplate, RiskTemplate [templateId, order]
Calculation [createdAt], [templateId], [status, createdAt]
FormTemplate [isActive]

EXPLAIN QUERY PLAN подтверждает SEARCH USING INDEX вместо SCAN.

Списки

Экраны «Все расчёты», «Архитектор» и «Админ» читали таблицу целиком и вдобавок тянули каждую стадию со всеми полями, включая длинный requirements, ради двух чисел в колонке «Трудозатраты». Теперь читается одна страница (50 строк) и только отображаемые поля.

На экране архитектора разделение на «ожидают согласования» и «остальные» делалось фильтрацией полного массива в памяти — заменено двумя запросами. Очередь согласования по-прежнему показывается целиком, постранично идёт только архив под ней.

API

/api/calculations, /api/templates и /api/users принимают ?page и ?limit (потолок 200). Тело ответа осталось массивом, поэтому существующие вызовы не ломаются, но добавлены заголовки X-Total-Count / X-Page / X-Page-Size / X-Total-Pages — ограничение выдачи видно клиенту, а не происходит молча.

Изменение поведения: по умолчанию эти эндпоинты теперь отдают 50 записей вместо всей таблицы. Отсюда минорная версия, а не патч.

Выгрузка

Экспорт docx/xlsx/pdf/zip оборачивал результат в new Uint8Array(buffer), что для Node Buffer копирует все байты — вторая полная копия многомегабайтного документа в памяти. Заменено представлением поверх той же памяти.

Сборка

Исправлена сборка Docker-образа (#46): npm ci запускал скрипт prepare, а тот прогонял format и typecheck в слое, где ещё нет исходников, и обрывал установку. В GitHub Actions это было не видно, потому что раннер сам выставляет CI=true. Также синхронизирован package-lock.json (#45).

Образ

Собран локально как ghcr.io/onixus/evacal:v0.2.0 / :latest, digest sha256:b4ab990cc881450564c83327d3d7e91659e175f30c3e988b720b290ab0978ac9.

В GHCR не опубликован: GitHub Actions в репозитории сейчас не запускается — «recent account payments have failed or your spending limit needs to be increased». По той же причине у этого релиза нет прогонов CI; все шаги CI (lint, typecheck, тесты, build) прогонялись локально — 274 теста зелёные.

Образ проверен вживую: migrate создаёт схему на чистом томе, приложение отвечает 200 на /, /login, /?page=2 и /api/calculations, индексы в БД контейнера на месте.

Опубликовать образ после починки биллинга:

docker login ghcr.io -u onixus
docker push ghcr.io/onixus/evacal:v0.2.0
docker push ghcr.io/onixus/evacal:latest