Project

General

Profile

Actions

Task #6116

open

EPIC: Speed up the stats updater daemon (scripts/workflow/update_stats.sh)

Added by Redmine Admin about 8 hours ago. Updated about 6 hours ago.

Status:
New
Priority:
High
Assignee:
-
Start date:
08/26/2026
Due date:
% Done:

79%

Estimated time:
(Total: 0:00 h)

Description

Source: sdlc/0-vibes/raw/2026-08-26/slow_ daemon.md — the infinite bash loop in scripts/workflow/update_stats.sh that chains 10 CLI commands, each a separate JVM launch, forever.

Where the time actually goes

The round is dominated by IIKO OLAP traffic, and the traffic volume is a product of four independent multipliers, each of which is fixable on its own:

Multiplier Where Factor
3 HTTP calls per logical request (auth → olap → logout) IikoOlapV2RequestsFetchingService.fetchOlapData:35,56 ×3
one OLAP request per day instead of one per range IikoStatsGatheringService.getMetricValuesFromIikoDateDesc:117 ×365
full 365-day window re-downloaded every round, nothing checks what is already stored same, plus all three metric commands ×∞ (repeats forever)
strictly serial across companies / partners / users InitialStatsGatheringCommand, PartnersMetricsGatheringCommand, UsersMetricsGatheringCommand ×N

Order of magnitude for iiko-stats-data-sync alone with N companies:
6 metrics × (1 network + N companies) × 365 days × 3 HTTP calls. At N=200 that is ~1.3M HTTP round-trips per round, all serialised, against an IIKO server that licenses a small number of concurrent API sessions.

On top of that, each of those requests writes its full request+response JSON to iiko_requests twice (INSERT then UPDATE) and printlns the whole payload to nohup.out.

Subtasks

Ordered by payoff. The first three are multiplicative — doing all three is what turns a multi-hour round into a short one.

The "IIKO is single-threaded" symptom is mostly self-inflicted: the code opens and closes an IIKO API session for every single request, so the session limit is hit constantly by our own login/logout churn rather than by concurrent work.


Subtasks 11 (4 open7 closed)

Task #6117: Reuse one IIKO session per command run instead of login/logout per requestResolved08/26/2026

Actions
Task #6118: Fetch only the missing date tail instead of re-downloading 365 days every roundResolved08/26/2026

Actions
Task #6119: Spike: ask IIKO OLAP for a date-grouped range in one request instead of one request per dayNew08/26/2026

Actions
Task #6120: Fix releaseToken: response body read twice, so IIKO sessions leakResolved08/26/2026

Actions
Task #6121: Make raw IIKO request/response logging to iiko_requests opt-inResolved08/26/2026

Actions
Task #6122: Stop printing full IIKO response payloads to stdoutResolved08/26/2026

Actions
Task #6123: Gather metrics for companies/partners/users with a bounded worker poolFeedback08/26/2026

Actions
Task #6124: Replace per-row DB writes and unpaged full-table loads in the sync commandsResolved08/26/2026

Actions
Task #6125: Run one round in a single JVM instead of 10 separate launchesFeedback08/26/2026

Actions
Task #6128: 66 тестов падают всегда — набор не может «падать быстро»New08/26/2026

Actions
Task #6129: Индексы под горячий путь демона: stat_slices вообще без индексовResolved08/26/2026

Actions
Actions #1

Updated by Redmine Admin about 8 hours ago

  • Subtask #6117 added
Actions #2

Updated by Redmine Admin about 8 hours ago

  • Subtask #6118 added
Actions #3

Updated by Redmine Admin about 8 hours ago

  • Subtask #6119 added
Actions #4

Updated by Redmine Admin about 8 hours ago

  • Subtask #6120 added
Actions #5

Updated by Redmine Admin about 8 hours ago

  • Subtask #6121 added
Actions #6

Updated by Redmine Admin about 8 hours ago

  • Subtask #6122 added
Actions #7

Updated by Redmine Admin about 8 hours ago

  • Subtask #6123 added
Actions #8

Updated by Redmine Admin about 8 hours ago

  • Subtask #6124 added
Actions #9

Updated by Redmine Admin about 8 hours ago

  • Subtask #6125 added
Actions #10

Updated by Redmine Admin about 7 hours ago

  • Subtask #6128 added
Actions #11

Updated by Redmine Admin about 7 hours ago

Ветка speedup/stats-daemon, два коммита: 50a6ebef (реализация) и ce3a1a2b (тесты).

Статус подзадач

Задача Статус
#6117 переиспользование сессии iiko Resolved
#6118 не перекачивать то, что уже в базе Resolved
#6120 releaseToken читал тело дважды Resolved
#6121 сырые запросы в iiko_requests по флагу Resolved
#6122 payload'ы и токен в stdout Resolved
#6124 N+1 и unpaged-выборки Resolved, частично — детали в задаче
#6127 диспатч companies-garbage-collect Resolved
#6123 пул потоков Feedback — механика есть, по умолчанию 1, нужен замер на сервере
#6125 весь оборот в одном процессе Feedback — команда есть, переключение демона за человеком
#6119 спайк по группировке OLAP по датам Открыт — нужен живой iiko

Заведена #6128: 66 тестов падают всегда из-за отсутствующих локальных файлов с учётными данными, из-за чего полный прогон не работает как сигнал.

Тесты

31 юнит-тест, без базы и без iiko. Оба ключевых набора проверены на то, что они ловят регрессию — временный откат исправления их роняет: IikoAuthTokensReleaseTest 3 из 4 на старом releaseToken, IikoStatsGatheringSkipTest 3 из 6 без пропуска сохранённых интервалов.

Полный прогон: 559 тестов, 66 падений — ровно те же 66, что падали до изменений.

Чего проверка не покрывает

Ни одного обращения к живому iiko отсюда сделать нельзя. Не проверено на реальном сервере: что iiko действительно принимает один ключ на серию запросов в течение трёх минут, что текст ответа про протухший ключ совпадает с тем, что ищет looksLikeExpiredToken, и что run-stats-round проходит все десять шагов. Первое выкатывание стоит делать под присмотром.

Что это должно дать

Три множителя из таблицы в описании снимаются: ×3 на логин/логаут (#6117), ×365 на посуточный обход в установившемся режиме (#6118), плюс убраны запись каждого тела в iiko_requests и печать payload'ов в nohup.out. Четвёртый, ×N по компаниям, снимается только после замера на сервере (#6123). Оставшийся крупный резерв — #6119: если iiko умеет отдавать год одним запросом с группировкой по дате, посуточный цикл исчезает и на полной перекачке тоже.

Actions #12

Updated by Redmine Admin about 6 hours ago

  • Subtask #6129 added
Actions

Also available in: Atom PDF