feat: WAIT_FOR_WEBHOOK system task — full implementation (epic #888)#894
Draft
nthmost-orkes wants to merge 8 commits into
Draft
feat: WAIT_FOR_WEBHOOK system task — full implementation (epic #888)#894nthmost-orkes wants to merge 8 commits into
nthmost-orkes wants to merge 8 commits into
Conversation
… executing loop tasks Fixes conductor-oss#876. When a DO_WHILE task uses list iteration (via the `items` field or `_items` inputParameter) and the evaluated list is empty, the task previously scheduled and executed iteration 1 unconditionally. Now it short-circuits to COMPLETED before scheduling any loop tasks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…output key cleanup off-by-one
Two follow-up corrections to the empty-items DO_WHILE fix:
1. Add `addOutput("iteration", 0)` before completing with empty items list,
so downstream expressions like `${doWhileTask.output.iteration}` get 0
instead of null.
2. Fix `keepLastN` in-memory output key cleanup: `IntStream.range(0, N-k-1)`
was generating keys "0".."N-k-2" (mostly non-existent), leaving old
iteration output in memory. Corrected to `IntStream.rangeClosed(1, N-k)`
which matches the DB cleanup in `removeIterations()`.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… cleanup - testExecute_NonEmptyItemsList_SchedulesFirstIteration: ensures the empty-items early-exit doesn't accidentally block non-empty lists - testKeepLastN_OutputCleanup_RemovesMultipleKeys: exercises iteration=5, keepLastN=2 to confirm "1","2","3" are all removed and "4","5" are retained (the previous test only removed 1 key) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, PR 1) Introduces the module structure and core lifecycle classes for WAIT_FOR_WEBHOOK — a system task that pauses a workflow until a matching inbound webhook event arrives. This PR establishes the foundation: - TaskType.WAIT_FOR_WEBHOOK enum value + string constant - WaitForWebhookTaskMapper (core): resolves input, creates task IN_PROGRESS - webhook-task module: WaitForWebhookTask system task, WebhookTaskDAO interface, InMemoryWebhookTaskDAO default implementation - Build wiring: settings.gradle, server/build.gradle - 24 unit tests covering mapper, task lifecycle, and DAO operations - Example workflow: order_payment_workflow.json WebhookTaskDAO and WebhookVerifier are defined as Spring-pluggable interfaces so Orkes Enterprise can substitute durable backends (Postgres, Redis) without modifying OSS code. Subsequent PRs add: config CRUD (conductor-oss#889), hash computation (conductor-oss#890), inbound REST endpoint (conductor-oss#892), workflowsToStart (conductor-oss#891), docs (conductor-oss#893). Closes part of conductor-oss#888. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feac8b3 to
a66d94f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the complete `WAIT_FOR_WEBHOOK` system task for Conductor OSS (epic #888).
Originally planned as 6 separate PRs, consolidated into a single branch since the pieces are not independently functional. A precision pass and adversarial code review were done after the initial implementation, folded in here.
Orkes Enterprise convergence
Designed as a drop-in replacement for the Orkes Enterprise `WAIT_FOR_WEBHOOK` implementation. The `WebhookConfig`, `WebhookTaskDAO`, and `WebhookConfigDAO` interfaces live in `conductor-common` so Orkes can depend on them without pulling in the full `webhook-task` module.
Verified identical to Orkes Enterprise:
What the Orkes adapter layer needs to supply (see `orkes-io/orkes-conductor#3535`):
Correctness fixes (adversarial review)
Known issues — deferred (documented in #888)
Yellow: Hash normalization asymmetry
Registration hash appends expected value (e.g. `"PENDING"`); inbound hash appends extracted value (e.g. `"pending"`). Tasks with case-differing match values silently never complete. Fix requires coordinated OSS + Orkes deploy with a migration window for in-flight tasks.
Red: Hash delimiter collision
Routing key uses unescaped `;` as delimiter. Workflow names or task ref names containing `;` produce ambiguous hashes. Fix requires data migration of all `WEBHOOK_TASKS.` keys + coordinated Orkes deploy. Low probability in practice.
Intentional differences from Orkes Enterprise
Synchronous vs async processing
OSS completes matching tasks inline within the HTTP request. Orkes uses `_webhook_queue` + `WebhookWorker`. OSS approach is correct for single-node deployments; use `RedisWebhookTaskDAO` for multi-node.
`POST /webhook/{id}` — body is optional
OSS defaults to `"{}"` when body is absent. Orkes requires a body. More permissive intentionally — some providers (Stripe, GitHub) send POST pings with no body.
Test plan
🤖 Generated with Claude Code