feat(ui): add operation-timing NDJSON sink for hub invokes and bulk DB paths
Two chokepoints per P0-2: WorkerClient.InvokeTimedAsync(<T>) wraps all 63 _hub.InvokeAsync call sites (plus TryInvokeAsync), and Stopwatch blocks around the Island VMs' bulk DB load/write paths (list load, task list load, reorders, batch delete, reconcile tick, count refresh). Single-row reads stay untouched per the plan's rule of thumb. No display, no behavior change.
This commit is contained in:
@@ -610,6 +610,8 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
|
||||
private async System.Threading.Tasks.Task BindAsync(TaskRowViewModel row, CancellationToken ct)
|
||||
{
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
var ok = false;
|
||||
try
|
||||
{
|
||||
await using var ctx = await _dbFactory.CreateDbContextAsync(ct);
|
||||
@@ -701,12 +703,16 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
}
|
||||
}
|
||||
await Merge.RefreshMergePreviewAsync();
|
||||
ok = true;
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
finally { OperationTiming.Shared.Record("db", "DetailsIsland.BindAsync", sw.Elapsed, ok); }
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task LoadChildOutcomesAsync(string parentTaskId, CancellationToken ct)
|
||||
{
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
var ok = false;
|
||||
try
|
||||
{
|
||||
await using var ctx = await _dbFactory.CreateDbContextAsync(ct);
|
||||
@@ -717,6 +723,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
.OrderBy(t => t.SortOrder).ThenBy(t => t.CreatedAt)
|
||||
.ToListAsync(ct);
|
||||
ct.ThrowIfCancellationRequested();
|
||||
ok = true;
|
||||
if (children.Count == 0) return;
|
||||
|
||||
ChildOutcomes.Clear();
|
||||
@@ -749,10 +756,13 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch { /* best-effort */ }
|
||||
finally { OperationTiming.Shared.Record("db", "DetailsIsland.LoadChildOutcomesAsync", sw.Elapsed, ok); }
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task LoadPlanningChildrenAsync(string parentTaskId, CancellationToken ct)
|
||||
{
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
var ok = false;
|
||||
try
|
||||
{
|
||||
await using var ctx = await _dbFactory.CreateDbContextAsync(ct);
|
||||
@@ -762,6 +772,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
.Where(t => t.ParentTaskId == parentTaskId)
|
||||
.ToListAsync(ct);
|
||||
ct.ThrowIfCancellationRequested();
|
||||
ok = true;
|
||||
|
||||
foreach (var child in children)
|
||||
{
|
||||
@@ -791,6 +802,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch { /* best-effort */ }
|
||||
finally { OperationTiming.Shared.Record("db", "DetailsIsland.LoadPlanningChildrenAsync", sw.Elapsed, ok); }
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task RefreshPlanningChildAsync(string childTaskId)
|
||||
|
||||
Reference in New Issue
Block a user