Životní cyklus Open API tokenu
Open API cTrader umožňuje jeden platný přístupový token na cTrader ID (cID) najednou. V okamžiku, kdy je vydán nový token — plánovaná obnova nebo znovuautorizace, když uživatel propojí další účet na stejném cID — je předchozí přístupový token zneplatněn. Copy engine běžící na vzdáleném uzlu drží ten nyní mrtvý token, takže nový token k němu musí dorazit bez přerušení živého spojení.
Model
OpenApiAuthorizationje agregát, který drží šifrované access + refresh tokeny cID. Unikátní index na(UserId, CtidUserId)vynucuje přesně jednu autorizaci na cID na uživatele.TokenVersion— monotónní čítač zvýšený při každé rotaci tokenu (Refresh(), což také pokrývá cestu znovu-autentifikace, když je na stejném cID propojen další účet). Je to verzační marker pro pravidlo jednoho platného tokenu a to, co běžící hostitel používá k detekci změny, i kdyby dva řetězce tokenů náhodou kolidovaly.- Tokeny jsou šifrovány v klidu přes
ISecretProtector(EncryptionPurposes.OpenApiAccessToken/OpenApiRefreshToken). Nikdy nejsou logovány ani ukládány v plaintextu.
Šíření (graceful in-place swap)
- Token se otočí → nový token + zvýšená
TokenVersionjsou persistovány. CopyEngineSupervisorna hostitelském uzlu znovu čte plán každý reconciliační cyklus a počítá token signature (přístupové tokeny + verze). Změna znamená rotaci.- Místo rozebrání hostitele a restartu (což by zahodilo execution stream mastera), supervisor pushuje nový token do běžícího hostitele.
- Hostitel znovu autentifikuje dotčený účet na existujícím socketu (
ProtoOAAccountAuthReqznovu) přesSwapAccessTokenAsync, pak provede lehkou rekonciliaci. Starý token zemře; copy stream se nikdy nezastaví.
To je to, co dělá cross-cID případ bezpečným: uživatel přidávající druhý účet ze stejného cID uprostřed běhu invaliduje starý token a běžící copy profil pokračuje na novém.
Obnova
OpenApiTokenRefreshService (background) proaktivně obnovuje autorizace před vypršením; OpenApiAuthorization.IsExpiring(threshold, now) to řídí. cTrader rotuje refresh token při každé obnově, takže nový refresh token je okamžitě persistován; cache pouze pro čtení, která nemůže persistovat, by se invalidovala (relevantní pro in-cluster test Job, který mountuje zapisovatelnou kopii secret).
Eskalace selhání
Selhaná obnova není tichá. OpenApiAuthorization.MarkRefreshFailed(reason, now, criticalWindow) zaznamenává RefreshFailedAt, zvyšuje ConsecutiveRefreshFailures a vždy vyvolává AccessTokenRefreshFailed (warning). Když je token nyní do App:OpenApi:TokenRefreshCriticalWindow (default 6h) od vypršení a obnova stále selhává, eskaluje jednou s doménovou událostí AccessTokenRefreshCritical + Critical log, aby owner mohl znovu autorizovat předtím, než copy/prop-firm operace token ztratí. Čítač selhání a eskalační západka se resetují při dalším úspěšném Refresh. Služba pokračuje v opakování každých TokenRefreshInterval, takže výpadek poskytovatele/maintenance se self-healuje, když se refresh endpoint vrátí.
Alert na invalidaci & auto-recovery (M1)
Částečná/znovu-autorizace na cID invaliduje token, který běžící copy hostitel stále drží. Když obchodní volání odmítne s OpenApiErrorKind.TokenInvalid, hostitel vyvolá distinct CopyTokenInvalidated alert (log 1078) — ne generické selhání — takže kanál notifikací ví, že token potřebuje pozornost. Recovery je automatická: supervisor znovu čte autorizaci každý cyklus a, když obnovený token změní token signature, pushuje ho do běžícího hostitele pro in-place swap — kopírování pokračuje bez manuálního znovupřidání. NotLinkable profil (token/auth dočasně nerozpsaný) je stejně znovu vyhodnocován každý supervisor cyklus a hostován v momentě, kdy se jeho plán znovu sestaví.
Watchdog živosti hostitele (M2)
Supervisor sleduje run task každého hostovaného profilu. Pokud hostitel skončí nebo selže, zatímco jeho profil je stále přiřazen k tomuto uzlu, watchdog zruší a restartuje ho příští cyklus (log CopyHostRestarted), takže zaseknutý hostitel se self-healuje místo potřeby manuálního restartu — a selhání jednoho profilu nikdy nezastaví ostatní (izolace per-profil).
Testy
- Unit —
TokenVersionse zvýší naRefresh; hostitel provede in-place swap bez restartu; cross-cID invalidace vymění source a destination tokeny; invalidovaný destination token vyvoláCopyTokenInvalidateda auto-recoveruje na další token push (M1); watchdog rozhodnutíIsHostDeadrestartuje dokončený/selhavší hostitel a nechá reassignovaný profil být (M2). - Integration —
TokenVersionpersistuje + inkrementuje přes EF na skutečném Postgres; token signature se změní při version bump, i když string zůstane nezměněn.