Skip to content

Extract TaskRunner from TaskProcessor - #7036

Draft
bentsherman wants to merge 3 commits into
masterfrom
task-output-resolver-v1
Draft

Extract TaskRunner from TaskProcessor#7036
bentsherman wants to merge 3 commits into
masterfrom
task-output-resolver-v1

Conversation

@bentsherman

@bentsherman bentsherman commented Apr 15, 2026

Copy link
Copy Markdown
Member

At its core, a process is a function that accepts an input, executes a
task and returns an asynchronous result. TaskProcessor implements this functionality together with the dataflow interface, so that a task can only be executed by feeding values through the process input channels.

This PR extracts the core task execution logic in TaskProcessor to a separate TaskRunner class:

  • the resolution of the task inputs and outputs
  • the cache lookup
  • the executor delegation
  • the task error strategy and retries

TaskProcessor keeps the dataflow interface -- the operator, the process
state, the output channel emission and the publishing -- as well as the process scoped services shared by all task executions, such as the name, the config, the executor and the task environment.

The processor creates a runner with taskCompleted as the completion handler, so that the runner does not depend on the dataflow interface: a task can be executed by invoking TaskRunner.submit() directly, without the process being part of a dataflow network.

(NOTE: This PR also extracts the legacy process output resolution logic to a separate TaskOutputResolverV1 class, mirroring TaskOutputResolver for typed outputs).

Side benefit: reduces TaskProcessor from ~2200 lines to ~1200 lines, making it easier for agents to read and modify

@bentsherman
bentsherman requested a review from jorgee April 15, 2026 22:36
@bentsherman
bentsherman force-pushed the task-output-resolver-v1 branch from 0678fc3 to 52d90b1 Compare July 29, 2026 23:33
@netlify

netlify Bot commented Jul 29, 2026

Copy link
Copy Markdown

Deploy Preview for nextflow-docs ready!

Name Link
🔨 Latest commit 21eb11a
🔍 Latest deploy log https://app.netlify.com/projects/nextflow-docs/deploys/6a748b9988876800089b17b0
😎 Deploy Preview https://deploy-preview-7036--nextflow-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@bentsherman
bentsherman removed the request for review from jorgee July 29, 2026 23:34
@bentsherman
bentsherman force-pushed the task-output-resolver-v1 branch from 52d90b1 to fba6d59 Compare July 29, 2026 23:55
@bentsherman bentsherman changed the title Move legacy process output resolution to separate class Extract TaskRunner from TaskProcessor Jul 30, 2026
@bentsherman
bentsherman requested a review from pditommaso July 30, 2026 16:55
@nextflow-io nextflow-io deleted a comment from netlify Bot Jul 30, 2026
@bentsherman
bentsherman force-pushed the task-output-resolver-v1 branch from 5daa309 to 5e59d3f Compare August 3, 2026 16:19
Signed-off-by: Ben Sherman <bentshermann@gmail.com>
Rename `finalizeTask0` to `taskCompleted` and document it as the
boundary between the execution of a task and the dataflow interface
of the process, that is the only point at which task results are
emitted to the process output channels.

All execution paths converge here: the `when` guard, a store directory
hit, a cached result and the normal completion of a task. No behaviour
change, this only names the seam in preparation for extracting the task
execution logic to a separate class.

Assisted-by: Claude Opus 5 (1M context)
Signed-off-by: Ben Sherman <bentshermann@gmail.com>
At its core a process is a function that accepts an input, executes a
task and returns an asynchronous result. TaskProcessor implements this
functionality together with the dataflow interface of the process, so
that a task can only be executed by feeding values through the process
input channels.

Move the execution of a task to a separate `TaskRunner` class:

- the resolution of the task inputs and outputs
- the store directory and cache lookup
- the delegation to the executor, including task arrays
- the task error strategy and retries

TaskProcessor keeps the dataflow interface -- the operator, the process
state, the output binding and the publishing -- as well as the process
scoped services shared by all task executions, such as the name, the
config, the executor and the task environment.

The processor creates a runner with `taskCompleted` as the completion
handler, so that the runner does not depend on the dataflow interface:
a task can be executed by invoking `TaskRunner.submit()` directly,
without the process being part of a dataflow network (see the test
'should execute a task without a dataflow network').

Note that `resumeOrDie` is now synchronized on the runner rather than on
the processor, so it no longer excludes `bindOutputs` and
`sendPoisonPill`. These methods do not share mutable state, the coarse
lock was incidental.

Assisted-by: Claude Opus 5 (1M context)
Signed-off-by: Ben Sherman <bentshermann@gmail.com>
@bentsherman
bentsherman force-pushed the task-output-resolver-v1 branch from 5e59d3f to 21eb11a Compare August 6, 2026 13:26
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