Архивирование с быстрым подключением и серверный рендеринг для веб-клиента #15
Notifications
Due Date
No due date set.
Blocks
#10 Расширение, оптимизация и миграции Mnesia
EventHub/EventHubBack
Reference: EventHub/EventHubBack#15
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Этап 3. Архивирование с быстрым подключением и серверный рендеринг для веб-клиента (пункт 4 задачи + решение для веба)
Цель: вынести исторические данные (старше 30 дней) в отдельные архивные узлы с возможностью быстрого доступа по требованию; реализовать серверный рендеринг календаря для минимизации нагрузки на браузеры.
Шаги:
3.1. Модуль архивного контроллера (
archive_controller)D(форматYYYYMMDD):eventhub_archive_D@Hostчерезslave:start/3или системный вызовerl -sname ....mnesia:create_schema([node()])).event,booking,reviewи т.д.) какdisc_only_copiesс теми же индексами, что и в основной базе (вызов обобщённой функцииcreate_indices/0на архивном узле).Dв архивный узел, затем удалить их из основной.init:stop/0), сохранив его файлы на диске в каталогеarchive_dir/D/.mnesia:backup/1основной базы перед удалением.3.2. Менеджер архивных узлов (
archive_manager– gen_server на основном узле)slave:start/3илиerl -sname, дождаться инициализации Mnesia.mnesia:change_config(extra_db_nodes, [ArchiveNode])(только для чтения).{ok, ArchiveNode}.extra_db_nodes, остановить узел.tar.gzи удалять с диска; при запросе — распаковать и запустить.3.3. API и серверный рендеринг
GET /calendar/view?month=2026-04&view=month– возвращает готовый HTML.archive_manager.mnesia:select(event, [{...}], ArchiveNode)илиmnesia:read.calendar_html_renderer:render_month(Year, Month, Events) -> iolist()генерирует HTML-сетку месяца с событиями.GET /calendar/day?date=..., возвращающим готовый HTML.archive_html_cacheна основном узле (ключ –{Year, Month}).Cache-Control: public, max-age=86400,ETagна основе хеша содержимого.Результат: основная база остаётся компактной, веб-клиент мгновенно отображает архивные месяцы без нагрузки на браузер.
План выполнения Задачи #15 – Архивирование и серверный рендеринг
1. Анализ и цели
После завершения задач #12, #13 и #14 основная база EventHub надёжна и реплицирована, но с ростом исторических данных производительность может снижаться.
Цели:
2. Архитектура решения
Вводятся три новых модуля и один HTTP‑эндпоинт:
archive_controllerarchive_managergen_server, управляющий пулом запущенных архивных узлов (старт, стоп, таймаут неактивности).calendar_html_rendererGET /calendar/view?...3. Детальный план реализации
Шаг 3.1. Модуль
archive_controllerОтветственность: Перенос данных за указанный день в новый архивный узел.
archive_day(Day)(гдеDay– строка"YYYYMMDD"):slave:start/3.mnesia:create_schema([Node]).event,recurrence_exception,booking,review,report) какdisc_only_copiesс теми же индексами, что в основной БД.D(фильтр поstart_timeдля событий,created_atдля остальных).archive_dir/<Day>/.mnesia:backup/1.Шаг 3.2. Модуль
archive_managerОтветственность: Управление жизненным циклом архивных узлов.
gen_server.map()с ключомNode :: atom()→#{pid => pid(), last_access => integer()}.get_archive_node(Day) -> {ok, Node} | {error, term()}:last_accessи вернуть его.slave:startилиerl -sname).mnesia:change_config(extra_db_nodes, [ArchiveNode]).tar.gzи удаление исходных файлов; при запросе – распаковка и запуск.Шаг 3.3. Серверный рендеринг (
calendar_html_renderer)Ответственность: Генерация готового HTML для отображения календаря в браузере.
render_month(Year, Month, Events):GET /calendar/day?date=....archive_html_cache, ключ{Year, Month}.Cache-Control: public, max-age=86400,ETag.Шаг 3.4. HTTP‑эндпоинт
GET /calendar/view?month=2026-05(илиfrom/to) – вход для веб‑клиента.archive_manager:get_archive_node(Day).mnesia:select/mnesia:readс нужного узла.calendar_html_renderer.4. Тестирование
archive_controller:archive_day(...). Проверить, что данные удалены из основной БД и доступны на архивном узле.archive_manager. Узел должен запуститься и вернуть данные./calendar/view?month=2026-05. Ответ должен быть валидным HTML с архивными событиями. Проверить работу кеша и автоматическую остановку архивного узла после таймаута.5. Документация
Добавить в
README.mdраздел «Архивирование данных»:archive_dir, пороговый срок хранения в днях).Этот план полностью согласован с выполненными задачами #12, #13, #14 и готов к реализации.
Финальная проверка задачи #15 – Архивирование и серверный рендеринг
Шаг 1. Подготовка окружения и загрузка записей
Очистите старые данные Mnesia и запустите приложение. Дождитесь приглашения
(eventhub@DESKTOP-SIR8B3R)1>и сообщенияBooted eventhub.Код для терминала (bash):
Код для Erlang-консоли после запуска:
Ожидаемый результат – список загруженных записей.
Шаг 2. Создание тестового пользователя
Сгенерируйте хеш пароля и создайте запись пользователя, который будет владельцем календаря.
Шаг 3. Создание календаря
Создайте календарь, принадлежащий этому пользователю. Запомните полученный
CalendarId– он понадобится для HTTP-запросов.Шаг 4. Создание события за вчерашний день
Предположим, что сегодня 4 мая 2026, вчера – 3 мая. Создайте событие в прошлом.
Проверьте, что запись видна:
Шаг 5. Получение JWT-токена владельца
В новом терминале (bash) выполните логин:
Из ответа извлеките
access_tokenи сохраните в переменную:Шаг 6. Проверка отображения горячего события
Запросите календарь за май 2026 (горячий месяц):
Должен вернуться HTTP 200. Проверьте содержимое:
Если событие найдено – горячий режим работает.
Шаг 7. Архивирование за вчерашний день
В Erlang-консоли выполните:
Дождитесь сообщения
Archived day 20260503 successfully.Проверьте, что событие удалено из основной базы:
Шаг 8. Проверка отображения архивного события
Снова запросите календарь за май:
Убедитесь, что событие по-прежнему видно (теперь оно берётся из архива):
Шаг 9. Проверка защиты от не-владельца
Создайте второго пользователя и получите его токен. Попробуйте запросить календарь с этим токеном – должен вернуться HTTP 403.
Шаг 10. Сброс кеша и повторный запрос
В Erlang-консоли удалите кеш:
Повторите запрос календаря – он должен выполниться без ошибок и вернуть тот же HTML.
Заключение
Если все шаги выполнены успешно, задача #15 полностью готова.