Ein Task kann jetzt auf beliebig viele Vorgaenger warten. Die Einzelspalte tasks.depends_on_task_id wird durch die Beziehungstabelle task_dependencies ersetzt (Composite-PK, beide FKs ON DELETE CASCADE -- das reproduziert das alte ON DELETE SET NULL: geloeschter Vorgaenger = Kante weg = Task wieder pickbar). BlockedByTaskId bleibt unberuehrt. - Migration AddTaskDependencies kopiert jede bestehende depends_on_task_id verlustfrei in die Tabelle, bevor die Spalte fallengelassen wird - QueuePicker gatet per doppelt negiertem NOT EXISTS: kein Task mit 0 Kanten wird blockiert, alle Kanten muessen done sein, eine Kante auf einen verschwundenen Task blockiert weiter - SetDependsOnAsync ersetzt die ganze Menge; Zykluspruefung ist jetzt eine BFS ueber den Graphen, faengt also auch A->B->C->A - blockedReason nennt alle offenen Vorgaenger (External/TaskBlocking, von ExternalMcpService und TaskWaitMcpTools gemeinsam genutzt) - add_task/update_task nehmen dependsOnTaskIds; die alte Skalarform bleibt als Ein-Element-Menge inkl. ""-Clear-Sentinel gueltig - UI: Fan-in-Zeile bleibt flach und listet alle Vorgaenger im After-Label, die lineare Kette rendert unveraendert
21 lines
763 B
C#
21 lines
763 B
C#
using ClaudeDo.Data;
|
|
using ClaudeDo.Data.Models;
|
|
|
|
namespace ClaudeDo.Worker.Tests.Infrastructure;
|
|
|
|
internal static class TestDependencies
|
|
{
|
|
/// <summary>
|
|
/// Seeds task_dependencies rows straight through the context. The production writer is
|
|
/// <c>TaskStateService.SetDependsOnAsync</c>, which most read-path fixtures don't build —
|
|
/// this is the "arrange" shortcut, not a second writer.
|
|
/// </summary>
|
|
public static async Task SeedDependsOnAsync(
|
|
this ClaudeDoDbContext ctx, string taskId, params string[] dependsOnTaskIds)
|
|
{
|
|
ctx.TaskDependencies.AddRange(dependsOnTaskIds.Select(id =>
|
|
new TaskDependencyEntity { TaskId = taskId, DependsOnTaskId = id }));
|
|
await ctx.SaveChangesAsync();
|
|
}
|
|
}
|