feat(worker): add generic OperationProgress channel, port MergeProgress onto it
Merge/verify phases now broadcast over a generic (opKey, phase, current, total) Hub event instead of a merge-specific one, so future producers (worktree cleanup, startup recovery, planning integration) can reuse it. IWorkerClient.MergeProgressEvent stays as a thin forwarder for existing consumers (elapsed seconds riding in the generic "current" slot).
This commit is contained in:
@@ -61,7 +61,7 @@ public sealed class TaskMergeService
|
||||
public const string StatusReverted = "reverted";
|
||||
public const string StatusConflictAborted = "conflict_aborted";
|
||||
|
||||
// Phase tokens for the MergeProgress broadcast — stable identifiers, localized by the UI.
|
||||
// Phase tokens for the OperationProgress broadcast — stable identifiers, localized by the UI.
|
||||
public const string PhaseMerging = "merging";
|
||||
public const string PhaseVerifying = "verifying";
|
||||
|
||||
@@ -168,7 +168,7 @@ public sealed class TaskMergeService
|
||||
/// Awaits <paramref name="work"/> while reporting MCP progress every
|
||||
/// <see cref="ProgressReportInterval"/> so a caller waiting on a long verify run doesn't hit
|
||||
/// the MCP client's own idle-silence abort. <paramref name="onTick"/> rides the same cadence
|
||||
/// for non-MCP callers (the Hub, which turns it into a MergeProgress broadcast). No-op
|
||||
/// for non-MCP callers (the Hub, which turns it into an OperationProgress broadcast). No-op
|
||||
/// passthrough when both are null.
|
||||
/// </summary>
|
||||
private static async Task<T> RunReportingProgressAsync<T>(
|
||||
@@ -392,7 +392,7 @@ public sealed class TaskMergeService
|
||||
|
||||
// Announced before the gate wait: another merge holding the repo is itself a reason the
|
||||
// caller sees nothing happen, and a UI waiting on this call needs a phase to show at once.
|
||||
await _broadcaster.MergeProgress(taskId, PhaseMerging, 0);
|
||||
await _broadcaster.OperationProgress(taskId, PhaseMerging, 0, 0);
|
||||
|
||||
var gate = GetMergeGate(list.WorkingDir);
|
||||
await gate.WaitAsync(ct);
|
||||
@@ -479,7 +479,7 @@ public sealed class TaskMergeService
|
||||
// silence here is what makes a working merge look like a dead button.
|
||||
if (!string.IsNullOrWhiteSpace(verifyCommand))
|
||||
{
|
||||
await _broadcaster.MergeProgress(taskId, PhaseVerifying, 0);
|
||||
await _broadcaster.OperationProgress(taskId, PhaseVerifying, 0, 0);
|
||||
await _broadcaster.WorkerLog(
|
||||
$"Verify command running after merging #{task.Number} \"{task.Title}\" into {targetBranch}",
|
||||
WorkerLogLevel.Info, DateTime.UtcNow);
|
||||
@@ -487,7 +487,7 @@ public sealed class TaskMergeService
|
||||
|
||||
var verifyFailure = await RunVerifyGateAsync(
|
||||
verifyCommand, list.WorkingDir, ct, progress,
|
||||
elapsed => _ = _broadcaster.MergeProgress(taskId, PhaseVerifying, (int)elapsed.TotalSeconds));
|
||||
elapsed => _ = _broadcaster.OperationProgress(taskId, PhaseVerifying, (int)elapsed.TotalSeconds, 0));
|
||||
if (verifyFailure is not null)
|
||||
{
|
||||
_logger.LogWarning("Verify command failed after merging task {TaskId}: {Reason}", taskId, verifyFailure.ErrorMessage);
|
||||
@@ -897,14 +897,14 @@ public sealed class TaskMergeService
|
||||
if (!string.IsNullOrWhiteSpace(verifyCommand) && !string.IsNullOrWhiteSpace(list.WorkingDir))
|
||||
{
|
||||
var verifyGate = GetMergeGate(list.WorkingDir!);
|
||||
await _broadcaster.MergeProgress(taskId, PhaseVerifying, 0);
|
||||
await _broadcaster.OperationProgress(taskId, PhaseVerifying, 0, 0);
|
||||
await verifyGate.WaitAsync(ct);
|
||||
try
|
||||
{
|
||||
// Same reason as the post-merge gate: this holds the approve call for minutes.
|
||||
var failed = await RunVerifyGateAsync(
|
||||
verifyCommand, list.WorkingDir!, ct, progress,
|
||||
elapsed => _ = _broadcaster.MergeProgress(taskId, PhaseVerifying, (int)elapsed.TotalSeconds));
|
||||
elapsed => _ = _broadcaster.OperationProgress(taskId, PhaseVerifying, (int)elapsed.TotalSeconds, 0));
|
||||
if (failed is not null) return failed;
|
||||
}
|
||||
finally { verifyGate.Release(); }
|
||||
|
||||
Reference in New Issue
Block a user