Skip to content

CxODEV-2161: keep the engine polling after Conductor errors (3.10.1 backport) - #234

Draft
milansvitlica-codaxy wants to merge 4 commits into
v3from
CxODEV-2161-engine-keeps-polling-v3
Draft

milansvitlica-codaxy wants to merge 4 commits into
v3from
CxODEV-2161-engine-keeps-polling-v3

Conversation

@milansvitlica-codaxy

@milansvitlica-codaxy milansvitlica-codaxy commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Backport of #233 to v3 (3.10.1). Fixes CxODEV-2161 and CxODEV-2000 (YouTrack) for the CxO engines, which pin ConductorSharp 3.10.x.

The three code commits from #233 cherry-picked cleanly: WorkflowEngineBackgroundService.cs and TaskQueuePollingService.cs were identical on master and v3. With them:

  • A ConductorSharp engine no longer stops polling for good after a Conductor error.
  • An HTTP timeout is no longer taken for a shutdown.
  • /health is Healthy only while the engine actually reads its queues.

See #233 for the root cause, design and before/after table.

Behaviour change to note: the old FTL Workflow Engine Background Service encountered an (API) error(s) is gone. Each failed attempt now logs at Error: ConductorSharp engine stopped polling (attempt N); retrying in …. Alerts that matched the old FTL text need updating.

Versions: Client, Engine, Patterns and KafkaCancellationNotifier go to 3.10.1. Toolkit stays 3.0.1-beta3.

Tests: v3 PRs get no CI, so this is the local run (LF checkout, net6.0 via DOTNET_ROLL_FORWARD=Major): 88/88 passed, including the 13 new unit tests and the 5 end-to-end recovery tests.

🤖 Generated with Claude Code

milansvitlica-codaxy and others added 4 commits October 19, 2026 13:44
…t is not a shutdown (CxODEV-2000)

WorkflowEngineBackgroundService ran the deployment and the execution manager
once. Any error, or an HTTP timeout mistaken for a shutdown, ended polling for
good while the host stayed up (and, for a timeout, stayed Healthy).

RunAsync is now a supervisor loop: deploy, mark running, run the execution
manager; on any error that is not our own shutdown, mark not running, log an
error, back off (1 s doubling to 30 s, 500 ms jitter) and start again. The
backoff resets after a successful deploy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A real engine (DI wiring, hosted service, beta execution manager, HTTP
client) against a fake Conductor that answers 503, hangs (request timeout)
or loses the task-def registration race, then recovers. Each test checks
that the engine backs off, reports not running, and completes a task queued
after recovery; one also checks that a task in flight during the outage
still completes. All four fail on the old loop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…shutdown cancel a hung deploy

Review findings on the supervisor loop:

- Health and the backoff reset followed a successful deploy, not a successful
  poll. With Conductor's metadata up and its task queues down (e.g. the queue
  backend), the engine reported Healthy most of the time while polling nothing,
  and redeployed about once a second on a 4xx. TaskQueuePollingService now marks
  the engine running after a successful read; the background service no longer
  marks it after deploy and restarts the backoff only after a run that polled.
  Unhealthy is still set only by the background service.
- Deploy takes no token, so a hung deploy blocked StopAsync. It now runs under
  WaitAsync(stoppingToken).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to 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