Task #6117
closedTask #6116: EPIC: Speed up the stats updater daemon (scripts/workflow/update_stats.sh)
Reuse one IIKO session per command run instead of login/logout per request
100%
Description
Problem¶
Every IIKO fetcher opens a brand-new API session and closes it again around a single request:
-
IikoOlapV2RequestsFetchingService.fetchOlapData—fetchToken(...)at line 35,releaseToken(token)at line 56 -
DepartmentsFetchingService.fetchDepartments— same shape -
IikoServerEmployeesFetchingService.fetchEmployees— same shape
So one logical OLAP data point costs three HTTP round-trips (/api/auth → /api/v2/reports/olap → /api/logout) plus two DB writes for the token row.
This is the real source of the "IIKO is single-threaded" symptom. IIKO licenses a limited number of concurrent API sessions; we spend that budget on our own login/logout churn, and the auth endpoint serialises.
A token cache already exists and is simply not used on this path: IikoAuthService.restoreToken() → IikoAuthTokensService.findActiveAndExpireOthers(), with a 3-minute expiry stamped in IikoAuthTokensFetchingService.fetchToken. The OLAP fetcher bypasses IikoAuthService and calls IikoAuthTokensFetchingService directly.
Proposed change¶
Introduce a single session holder (e.g. IikoSessionService) that all fetchers go through:
- hands out the current token, fetching a new one only when there is none or the stored
expirationhas passed (refresh a little early, e.g. 30s of slack); - refreshes and retries once when IIKO answers with an expired/invalid-token error;
- releases the session once, at the end of the command run (JVM shutdown hook), not per request.
Then change IikoOlapV2RequestsFetchingService, DepartmentsFetchingService and IikoServerEmployeesFetchingService to use it, and drop their per-call fetchToken/releaseToken pairs.
Keep the login/hashedPassword override parameters working — they should get their own cached session keyed by login.
Acceptance¶
- A run of
iiko-stats-data-syncproduces one/api/authcall per token lifetime, not one per OLAP request. -
/api/logoutis called once at the end of the run. - No behavioural change to the returned data.
Updated by Redmine Admin about 9 hours ago
- Blocks Task #6123: Gather metrics for companies/partners/users with a bounded worker pool added
Updated by Redmine Admin about 9 hours ago
- Related to Task #6120: Fix releaseToken: response body read twice, so IIKO sessions leak added
Updated by Redmine Admin about 9 hours ago
- Status changed from New to Resolved
- % Done changed from 0 to 100
Реализовано в ветке speedup/stats-daemon, коммит 50a6ebef.
Новый IikoSessionService (adapters/iiko/server/authorization/common/services/):
-
currentToken(login, hashedPassword)— кэш по логину, новый токен только когда сессии нет или доexpirationосталось меньше 30 с; -
withToken(...) { token -> ... }— выполняет запрос и ровно один раз повторяет его с новым токеном, если iiko ответил «Token is expired or invalid» (ответ приходит текстом с кодом 200, поэтому распознаётся по телу —IikoSessionService.looksLikeExpiredToken); -
releaseAll()под@PreDestroy— логаут один раз на выключении контекста Micronaut, а не после каждого запроса.
Переведены на него IikoOlapV2RequestsFetchingService, DepartmentsFetchingService, IikoServerEmployeesFetchingService — из них убраны парные fetchToken/releaseToken. Переопределение login/hashedPassword работает как раньше, кэш ключуется по логину.
Осталось за рамками этого коммита: ещё восемь фетчеров iiko живут по старой схеме — OlapDataFetchingService, EventsFetchingService, GroupsFetchingService, ProductsFetchingService, StoresFetchingService, TerminalsFetchingService, OutgoingInvoicesFetchingService, OlapPresetsFetchingService. Ни один из них не участвует в обороте демона, поэтому трогать их сейчас не стал, но лимит сессий у iiko они делят с остальными. Стоит отдельной задачи.
Проверка на живом iiko не проводилась — здесь нет доступа к серверу. Сборка проходит, тесты: 528/66 упавших и до, и после изменений (падения из-за отсутствующей фикстуры tmp/mock/iiko_logo_pass/iiko_auth.json, к этой задаче отношения не имеют).