using MBN_STOCK_WEBVIEW.Infrastructure; using MMoneyCoderSharp.Data; namespace MBN_STOCK_WEBVIEW; public sealed partial class MainWindow { private LegacyNamedKrxThemeRestoreService? _namedKrxThemeRestoreService; private async Task PostNamedKrxThemeRestoreAsync( string requestId, IReadOnlyList items, CancellationToken cancellationToken) { var candidates = items .Select(static item => new LegacyNamedKrxThemeRestoreRow( 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(LegacyNamedKrxThemeRestoreService.IsCandidate) .ToArray(); if (candidates.Length == 0) { return; } try { var runtime = _databaseRuntime; if (runtime is null) { PostNamedKrxThemeRestoreError( requestId, "DATABASE_UNAVAILABLE", "현재 Oracle DB를 사용할 수 없어 저장된 KRX 테마를 재검증하지 못했습니다."); return; } var service = _namedKrxThemeRestoreService ??= new LegacyNamedKrxThemeRestoreService(runtime.Executor); var result = await service.ResolveAsync(candidates, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); PostMessage("named-krx-theme-restore-results", new { requestId, result.RetrievedAt, totalRowCount = result.Rows.Count, rows = result.Rows.Select(ToNamedKrxThemeRestoreWireRow) }); } catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { if (Volatile.Read(ref _playoutCommandInFlight) != 0 && !_lifetimeCancellation.IsCancellationRequested) { PostNamedKrxThemeRestoreError( requestId, "PLAYOUT_PRIORITY", "송출 명령 우선 처리로 KRX 테마 재검증을 취소했습니다. 자동 재시도하지 않습니다."); } throw; } catch (DatabaseOperationException) { PostNamedKrxThemeRestoreError( requestId, "DATABASE_UNAVAILABLE", "현재 Oracle DB에서 KRX 테마를 재검증하지 못했습니다."); _ = PostDatabaseStatusAsync(_lifetimeCancellation.Token); } catch { PostNamedKrxThemeRestoreError( requestId, "RESTORE_FAILED", "저장된 KRX 테마 행을 안전한 현재 선택으로 복원하지 못했습니다."); } } private static object ToNamedKrxThemeRestoreWireRow( LegacyNamedKrxThemeRestoreOutcome outcome) { if (outcome.IsResolved) { var identity = outcome.Identity!; return new { outcome.ItemIndex, status = "resolved", identity.ActionId, identity.BuilderKey, identity.CutCode, identity.PageSize, identity.Sort, identity.ThemeTitle, identity.StoredThemeCode, identity.CurrentThemeCode, identity.PreviewItemCount, identity.PreviewIsTruncated, identity.CodeWasRemapped }; } return new { outcome.ItemIndex, status = "failed", failure = outcome.Failure switch { LegacyNamedKrxThemeRestoreFailure.InvalidRow => "INVALID_ROW", LegacyNamedKrxThemeRestoreFailure.UnsupportedAction => "UNSUPPORTED_ACTION", LegacyNamedKrxThemeRestoreFailure.IdentityNotFound => "IDENTITY_NOT_FOUND", LegacyNamedKrxThemeRestoreFailure.IdentityAmbiguous => "IDENTITY_AMBIGUOUS", LegacyNamedKrxThemeRestoreFailure.PreviewEmpty => "PREVIEW_EMPTY", LegacyNamedKrxThemeRestoreFailure.DatabaseDataInvalid => "DATABASE_DATA_INVALID", _ => "RESTORE_FAILED" } }; } private void PostNamedKrxThemeRestoreError( string requestId, string code, string message) { PostMessage("named-krx-theme-restore-error", new { requestId, code, message, retryable = false }); } }