Skip to content

Add FORK_JOIN task support - #227

Open
rennolaj wants to merge 1 commit into
codaxy:masterfrom
rennolaj:feat/master/fork-join-task
Open

Add FORK_JOIN task support#227
rennolaj wants to merge 1 commit into
codaxy:masterfrom
rennolaj:feat/master/fork-join-task

Conversation

@rennolaj

Copy link
Copy Markdown

Objective

Add support for Conductor's static FORK_JOIN task type. The engine already supported FORK_JOIN_DYNAMIC (runtime-determined branches), but had no builder/model for the build-time, fixed-branch FORK_JOIN — even though the client SDK already carries the enum values and ForkTasks/JoinOn fields needed for it (Client/Generated/Models.cs).

Approach

  • Builders/ForkJoinTaskBuilder.csAddTask(reference, input, params branches), where each branch is an Action<ITaskSequenceBuilder<TWorkflow>>. Builds one FORK_JOIN task (ForkTasks = each branch's built tasks, in order) plus an auto-generated companion JOIN task (JoinOn = the last task reference of each branch) — mirroring how DynamicForkJoinTaskBuilder emits a fork+join pair, and reusing SwitchTaskBuilder's pattern for collecting multiple sub-branches into one builder.
  • Model/ForkJoinTaskModel.csForkJoinInput/ForkJoinTaskModel, following the same TaskModel<TInput, NoOutput> shape as every other operator.
  • Validates zero branches, and validates each branch has at least one task, both raising a clear InvalidOperationException rather than letting an empty branch reach a bare LINQ Sequence contains no elements exception (an actual gap found and fixed during review).
  • Test fixtures follow the exact 6-file shape used by every prior "add an operator" PR (do-while Added the builder to support the do-while task type #205, events Add support for event tasks #188, human task Add human task support #111, wait task Add wait task support #110): sample workflow .cs + expected .json (captured from the real serializer output, not hand-written) + csprojEmbeddedResource entry + [Fact]s in Integration/WorkflowBuilderTests.cs.
  • The happy-path fixture (ForkJoinTask.cs) deliberately gives one branch two tasks using synthetic, non-business-flavored PassThroughTaskExtensions.AddTasks calls, specifically so the test can distinguish "picks the branch's last task" from "picks its first task" for joinOn — a single-task-per-branch fixture can't tell those apart, since first and last are the same task.
  • No README.md/SKILL.md changes — confirmed no prior operator-addition PR ever touches docs (they're handled in separate bulk-doc PRs), so this follows that same precedent.

Modified files (8 files, +287)

  • src/ConductorSharp.Engine/Builders/ForkJoinTaskBuilder.cs (new)
  • src/ConductorSharp.Engine/Model/ForkJoinTaskModel.cs (new)
  • test/ConductorSharp.Engine.Tests/Samples/Workflows/ForkJoinTask.cs + .json (new)
  • test/ConductorSharp.Engine.Tests/Samples/Workflows/EmptyForkJoinTask.cs (new — zero-branches case)
  • test/ConductorSharp.Engine.Tests/Samples/Workflows/EmptyBranchForkJoinTask.cs (new — empty-branch case)
  • test/ConductorSharp.Engine.Tests/ConductorSharp.Engine.Tests.csproj (+1 EmbeddedResource)
  • test/ConductorSharp.Engine.Tests/Integration/WorkflowBuilderTests.cs (+3 [Fact]s)

Checks

  • dotnet test test/ConductorSharp.Engine.Tests/ConductorSharp.Engine.Tests.csprojpassed, 73/73 (3 new: happy path, zero-branches exception, empty-branch exception).
  • dotnet build ConductorSharp.slnpassed.
  • dotnet csharpier --check on all changed files — passed (repo's enforced pre-commit formatter).
  • No live-Conductor / runtime-execution test exists for this — confirmed none exists for any operator in this repo (no such test infrastructure here at all, for any task type), so this isn't a gap specific to this change.

Risks

  • The branch-declaration API (params Action<ITaskSequenceBuilder<TWorkflow>>[] branches) is a new design choice — no direct precedent existed for "one property reference → N parallel branches" prior to this PR (FORK_JOIN_DYNAMIC doesn't need one, since its branches are runtime data, not C# code).
  • JoinOn is computed as each branch's last built task's reference name. This is standard Conductor convention, but only exercised end-to-end via generated JSON assertions here, not against a live Conductor server.
  • This environment's local .NET SDK only has the 10.0 runtime installed, not net6.0 (the projects' target framework) — all checks above were run with DOTNET_ROLL_FORWARD=LatestMajor and HUSKY=0 (to skip the husky install pre-build hook, which also needs net8.0). Worth confirming your CI/dev environment has net6.0 so neither workaround is needed there.

Review focus

  • The ForkJoinTaskBuilder<TWorkflow> branch-collection API in ForkJoinTaskBuilder.cs — is params Action<ITaskSequenceBuilder<TWorkflow>>[] branches the shape you'd want, or would you prefer something else?
  • Name/TaskReferenceName are both set to the same prefixed string (FORK_JOIN_<ref>, JOIN_<ref>) on the two emitted tasks, matching DynamicForkJoinTaskBuilder's existing convention for two-task-emission builders (single-task builders like WaitTaskBuilder instead leave TaskReferenceName unprefixed) — confirm this reasoning holds.

Out of scope

  • FORK_JOIN_DYNAMIC, DO_WHILE, SWITCH, and every other existing operator — untouched.
  • The generated client (Client/Generated/Models.cs) — already had what was needed.
  • README.md/SKILL.md documentation — deliberately excluded per the operator-addition precedent (see Approach).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@rennolaj