feat: consolidate legacy parity migration baseline

This commit is contained in:
2026-07-20 22:06:12 +09:00
parent 5eb4054120
commit 4a54977341
66 changed files with 5391 additions and 460 deletions

View File

@@ -22,6 +22,7 @@ public sealed partial class MainWindow : Window
private readonly CancellationTokenSource _lifetimeCancellation = new();
private readonly SemaphoreSlim _intentGate = new(1, 1);
private readonly SemaphoreSlim _orderedPlayoutIntentGate = new(1, 1);
private readonly PlayoutLaunchAuthorization _playoutLaunchAuthorization;
private readonly WindowSubclassProcedure _windowSubclassProcedure;
private readonly LegacyOperatorController _controller;
@@ -241,6 +242,7 @@ public sealed partial class MainWindow : Window
await InitializeWebViewAsync();
if (!_closing)
{
StartDatabaseHealthMonitor();
await ConnectPlayoutAsync(_lifetimeCancellation.Token);
}
}
@@ -380,15 +382,35 @@ public sealed partial class MainWindow : Window
private async Task ProcessIntentAsync(LegacyUiIntent intent)
{
var gateEntered = false;
var orderedPlayoutIntentEntered = false;
var databaseGateEntered = false;
var dispatchStarted = false;
try
{
// MainForm performed database search synchronously. The busy snapshot
// freezes the Web controls, while this zero-timeout gate prevents an
// already-posted duplicate from growing an unbounded DB request queue.
gateEntered = await _intentGate.WaitAsync(
0,
_lifetimeCancellation.Token);
// freezes the Web controls. Playout commands must retain their order behind
// a preceding local row-selection intent, but only one may wait or execute
// at a time so a double post can never become a queued vendor command.
if (IsOrderedPlayoutIntent(intent))
{
orderedPlayoutIntentEntered = await _orderedPlayoutIntentGate.WaitAsync(
0,
_lifetimeCancellation.Token);
if (orderedPlayoutIntentEntered)
{
await _intentGate.WaitAsync(_lifetimeCancellation.Token);
gateEntered = true;
}
}
else
{
// Keep the zero-timeout admission used by database and edit intents;
// those requests must not build an unbounded queue behind slow I/O.
gateEntered = await _intentGate.WaitAsync(
0,
_lifetimeCancellation.Token);
}
if (!gateEntered)
{
PostState(IsNamedPlaylistModalIntent(intent)
@@ -514,6 +536,13 @@ public sealed partial class MainWindow : Window
PostState(_controller.Current);
}
await AcquirePriorityDatabaseActivityAsync(_lifetimeCancellation.Token);
databaseGateEntered = true;
if (_closing)
{
return;
}
dispatchStarted = true;
var state = await HandleIntentAsync(intent, _lifetimeCancellation.Token);
ObserveOperatorMutationQuarantine(state);
@@ -546,13 +575,26 @@ public sealed partial class MainWindow : Window
_intentBusy = false;
}
if (databaseGateEntered)
{
_databaseActivityGate.Release();
}
if (gateEntered)
{
_intentGate.Release();
}
if (orderedPlayoutIntentEntered)
{
_orderedPlayoutIntentGate.Release();
}
}
}
private static bool IsOrderedPlayoutIntent(LegacyUiIntent intent) => intent is
LegacyExecutePlayoutIntent or LegacyGateAPrepareIntent;
private static bool IsNamedPlaylistModalIntent(LegacyUiIntent intent) =>
intent is LegacyRefreshNamedPlaylistsIntent or
LegacySelectNamedPlaylistIntent or
@@ -648,7 +690,8 @@ public sealed partial class MainWindow : Window
pointer.Shift,
pointer.X,
pointer.Y,
pointer.TimestampMilliseconds),
pointer.TimestampMilliseconds,
pointer.AllowAppend),
LegacyCutKeyDownIntent key => _controller.CutKeyDown(
key.Key,
key.Control,
@@ -1347,6 +1390,7 @@ public sealed partial class MainWindow : Window
DetachCloseConfirmation();
DetachInteractionMetricsRefresh();
_lifetimeCancellation.Cancel();
CancelActiveDatabaseHealthCheck();
ShutdownPlayoutRuntime();
ShutdownManualListsRuntime();
DataQueryExecutor.Reset();