fix(worker): kill cancelled runs' processes and make MCP approve actually merge

- CancelAsync now signals the running Claude process of the cancelled task and
  its cascaded children via the new RunCancellationRegistry (queue + override
  slots register their CTS there) instead of only flipping DB state.
- external MCP review_task 'approve' now mirrors the hub's ApproveReview:
  unit merge for parents, ApproveAndMergeAsync for childless tasks, optional
  targetBranch; ReviewTaskResult carries mergeStatus/conflicts.
This commit is contained in:
mika kuns
2026-07-23 20:24:36 +02:00
parent 451afc80f8
commit fee69998f8
15 changed files with 330 additions and 46 deletions
@@ -10,6 +10,7 @@ public sealed class OverrideSlotService
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;
private readonly TaskRunner _runner;
private readonly ILogger<OverrideSlotService> _logger;
private readonly RunCancellationRegistry _runCancels;
private readonly object _lock = new();
private volatile QueueSlotState? _slot;
@@ -17,11 +18,13 @@ public sealed class OverrideSlotService
public OverrideSlotService(
IDbContextFactory<ClaudeDoDbContext> dbFactory,
TaskRunner runner,
ILogger<OverrideSlotService> logger)
ILogger<OverrideSlotService> logger,
RunCancellationRegistry runCancels)
{
_dbFactory = dbFactory;
_runner = runner;
_logger = logger;
_runCancels = runCancels;
}
public QueueSlotState? CurrentSlot => _slot;
@@ -66,12 +69,14 @@ public sealed class OverrideSlotService
var cts = new CancellationTokenSource();
_slot = new QueueSlotState { TaskId = taskId, StartedAt = DateTime.UtcNow, Cts = cts };
_runCancels.Register(taskId, cts);
_ = work(cts.Token).ContinueWith(t =>
{
if (t.IsFaulted)
_logger.LogError(t.Exception, faultMessage, taskId);
lock (_lock) { _slot = null; }
_runCancels.Unregister(taskId, cts);
cts.Dispose();
}, TaskScheduler.Default);
}