Open APIトークンのライフサイクル
cTraderのOpen APIはcTrader ID(cID)ごとに1つの有効なアクセス 토ークンのみを許可します。 新しいトークンが発行される瞬間 — スケジュールされた更新、またはユーザーが同じcIDで別のアカウントを 再認証的时候 — 以前的アクセストークンが無効化されます。 リモートノードで実行されているコピーエンジンはその今すぐ死亡したトークンを保持しているため、 新しいトークンはライブ接続をドロップせずにそれに到達する必要があります。
モデル
OpenApiAuthorizationはcIDの暗号化されたaccess + refreshトークンを保持する集約です。(UserId, CtidUserId)の一意インデックスがcIDごとにユーザーごとに正確に1つの許可を強制します。TokenVersion— トークンがローテーションするたびにインクリメントされる単調カウンター (Refresh()、別のアカウントが同じcIDでリンクされたときの再認証パスもカバー)。 これは単一有効トークンルールのバージョンマーカーであり、実行中のホストが2つのトークン文字列が衝突しても 変更を検出するために使用するものです。- トークンは保存時に
ISecretProtector(EncryptionPurposes.OpenApiAccessToken/OpenApiRefreshToken)で暗号化されます。プレーンテキストでログに記録または保存されることはありません。
伝播(インプレースでのグレースフルswap)
- トークンがローテート → 新しいトークン + 増分された
TokenVersionが永続化されます。 - ホストノード上の
CopyEngineSupervisorは各レконcileサイクルでプランを再読み取りし、 トークン署名(accessトークン + バージョン)を計算。変更はローテーション意味します。 - ホストを Tear downして再起動する代わりに(マ斯特の実行ストリームがドロップする) 、スーパーバイザーは新しいトークンを実行中のホストにプッシュします。
- ホストは既存のソケット上で(再度
ProtoOAAccountAuthReqで)影響を受けたアカウントを再認証し、 軽いreconcileを実行。古いトークンは死亡; コピーストリームは決して停止しません。
これがcross-cIDケースを安全にします:ユーザーが実行中に同じcIDから2番目のアカウントを追加すると 古いトークンが無効になり、実行中のコピープロファイルは新しいもので続行します。
更新
OpenApiTokenRefreshService(バックグラウンド)は有効期限前に認証情報をプロアクティブに更新;
OpenApiAuthorization.IsExpiring(threshold, now)がそれをゲート。
cTraderは更新ごとにrefreshトークンをローテートするため、新しいrefreshトークンは直ちに永続化されます;
永続化できない読み取り専用キャッシュは自己無効化します
(クラスター内テスト Job、秘密の書き込み可能なコピーをマウントする相關).
失敗エスカレーション
失敗した更新はサイレントではありません。
OpenApiAuthorization.MarkRefreshFailed(reason, now, criticalWindow)はRefreshFailedAtを記録し、
ConsecutiveRefreshFailuresをインクリメントし、常にAccessTokenRefreshFailed(警告)を発生させます。
トークンがApp:OpenApi:TokenRefreshCriticalWindow(デフォルト6h)以内に期限切れで、
更新がまだ失敗している場合、AccessTokenRefreshCriticalドメインイベント + Criticalログで一度だけエスカレート、
コピー/prop-firm操作がトークンを失う前に所有者が再認証できるように。
失敗カウンターとエスカレーションラッチは次の成功Refreshでリセットされます。
サービスはTokenRefreshIntervalごとにリトライを継続するため、プロバイダ/メンテナンス停止が
更新エンドポイントが返したときに自己修復します。
無効化アラートと自動回復(M1)
cIDでの部分的/再認証は、実行中のコピーホストがまだ保持しているトークンを無効にします。
取引呼び出しがOpenApiErrorKind.TokenInvalidで拒否された場合、
ホストはdistinctな**CopyTokenInvalidatedアラート(ログ1078)を発生させます —
而不是一般的な失敗 — 通知チャネルはトークンに注意が必要であることを認識。
回復は自動的:スーパーバイザーは各サイクルで許可を再読み取り、
更新されたトークンがトークン署名を変更した場合、実行中のホストにそれをプッシュしてインプレースswap** —
コピーは手動の再追加なしで再開。NotLinkableプロファイル
(トークン/認証が一時的に解決不能)は各スーパーバイザーサイクルで再度評価され、
プランが再度ビルドされるとすぐにホストされます。
ホスト生存watchdog(M2)
スーパーバイザーは各ホストされたプロファイルの実行タスクを監視します。
ホストがプロファイルがまだこのノードにアサインされている間に終了または障害が発生した場合、
watchdogはキャンセルし、次サイクルでそれを再開(ログCopyHostRestarted)、
因此 ETCホストは手動の再起動を必要とする代わりに自己修復 —
1つのプロファイルの失敗が他を停滞させることはありません(per-profile分離)。
テスト
- ユニット —
TokenVersionがRefreshで bump; ホストが再起動せずにインプレースswapを実行; cross-cID無効化swapソースと宛先トークン; 無効化された宛先トークンがCopyTokenInvalidatedを発生させ、 次のトークン pushで自動回復(M1); watchdogIsHostDead決定が実行/障害ホストを再起動し、 再アサインされたプロファイルをそのままにする(M2)。 - 統合 —
TokenVersionがEF経由で реальный Postgresに永続化 + インクリメント; 文字列が変更されていなくてもバージョンbumpでトークン署名が変更。