using MBN_STOCK_WEBVIEW.Infrastructure; using MMoneyCoderSharp.Data; namespace MBN_STOCK_WEBVIEW; public sealed partial class MainWindow { private LegacyForeignIndexCandleRestoreService? _namedForeignIndexCandleRestoreService; private async Task PostNamedForeignIndexCandleRestoreAsync( string requestId, IReadOnlyList items, CancellationToken cancellationToken) { var candidates = items .Select(static item => new LegacyForeignIndexCandleRestoreRow( item.ItemIndex, item.IsEnabled, item.Selection.GroupCode, item.Selection.Subject, item.Selection.GraphicType, item.Selection.Subtype, item.Page?.ToString() ?? string.Empty, item.Selection.DataCode)) .Where(LegacyForeignIndexCandleRestoreService.IsCandidate) .ToArray(); if (candidates.Length == 0) { return; } try { var runtime = _databaseRuntime; if (runtime is null) { PostNamedForeignIndexCandleRestoreError( requestId, "DATABASE_UNAVAILABLE", "현재 해외지수 master DB를 사용할 수 없어 캔들 행을 재검증하지 못했습니다."); return; } var service = _namedForeignIndexCandleRestoreService ??= new LegacyForeignIndexCandleRestoreService(runtime.Executor); var result = await service.ResolveAsync(candidates, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); PostMessage("named-foreign-index-candle-restore-results", new { requestId, result.RetrievedAt, totalRowCount = result.Rows.Count, rows = result.Rows.Select(ToNamedForeignIndexCandleRestoreWireRow) }); } catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { if (Volatile.Read(ref _playoutCommandInFlight) != 0 && !_lifetimeCancellation.IsCancellationRequested) { PostNamedForeignIndexCandleRestoreError( requestId, "PLAYOUT_PRIORITY", "송출 명령 우선 처리로 해외지수 캔들 재검증을 취소했습니다. 자동 재시도하지 않습니다."); } throw; } catch (DatabaseOperationException) { PostNamedForeignIndexCandleRestoreError( requestId, "DATABASE_UNAVAILABLE", "현재 해외지수 master DB에서 캔들 행을 재검증하지 못했습니다."); _ = PostDatabaseStatusAsync(_lifetimeCancellation.Token); } catch { PostNamedForeignIndexCandleRestoreError( requestId, "RESTORE_FAILED", "저장된 해외지수 캔들 행을 안전한 s8010 선택으로 복원하지 못했습니다."); } } private static object ToNamedForeignIndexCandleRestoreWireRow( LegacyForeignIndexCandleRestoreOutcome outcome) { if (outcome.IsResolved) { var identity = outcome.Identity!; return new { outcome.ItemIndex, status = "resolved", identity.TargetKey, identity.InputName, identity.Symbol, identity.NationCode, identity.ForeignDomesticCode, identity.SceneCode, identity.ValueType, identity.PeriodDays, identity.CutCode }; } return new { outcome.ItemIndex, status = "failed", failure = outcome.Failure switch { LegacyForeignIndexCandleRestoreFailure.InvalidRow => "INVALID_ROW", LegacyForeignIndexCandleRestoreFailure.IdentityNotFound => "IDENTITY_NOT_FOUND", LegacyForeignIndexCandleRestoreFailure.IdentityAmbiguous => "IDENTITY_AMBIGUOUS", LegacyForeignIndexCandleRestoreFailure.DatabaseDataInvalid => "DATABASE_DATA_INVALID", _ => "RESTORE_FAILED" } }; } private void PostNamedForeignIndexCandleRestoreError( string requestId, string code, string message) { PostMessage("named-foreign-index-candle-restore-error", new { requestId, code, message, retryable = false }); } }