Skip to content

ADR: hints process directive for executor-specific scheduling hints#6960

Merged
bentsherman merged 2 commits into260414-hints-directivefrom
adr/hints-process-directive
Apr 23, 2026
Merged

ADR: hints process directive for executor-specific scheduling hints#6960
bentsherman merged 2 commits into260414-hints-directivefrom
adr/hints-process-directive

Conversation

@robsyme
Copy link
Copy Markdown
Collaborator

@robsyme robsyme commented Mar 23, 2026

Summary

Architecture Decision Record proposing a new hints process directive with namespaced keys as a generic extension point for executor-specific scheduling hints.

First use case: AWS Batch consumable resources for license-seat-aware scheduling.

Options Evaluated

  1. Dedicated consumableResources directive — too narrow, each executor feature would need its own directive
  2. Overload resourceLabels — conflates metadata tags with scheduling behavior; resourceLabels uses replacement semantics in config overrides, so a sysadmin's cost-tracking labels would be wiped out if a user sets consumable resources (and vice versa)
  3. New hints directive (recommended) — generic, extensible, namespaced keys, executors consume what they understand

Proposed Syntax

process runDragen {
    hints 'consumable-resource:my-dragen-license': 1
}

Ref: #5917, #6957

🤖 Generated with Claude Code

Propose a generic 'hints' process directive with namespaced keys as
the extension point for executor-specific scheduling hints. First use
case: AWS Batch consumable resources for license-seat management.

Evaluates three options: dedicated consumableResources directive,
overloading resourceLabels, and a new hints directive. Recommends
hints for extensibility and separation of concerns.

Ref: #5917
Signed-off-by: Rob Syme <rob.syme@gmail.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 23, 2026

Deploy Preview for nextflow-docs-staging ready!

Name Link
🔨 Latest commit 07feada
🔍 Latest deploy log https://app.netlify.com/projects/nextflow-docs-staging/deploys/69dec0cec279ef0008111b8d
😎 Deploy Preview https://deploy-preview-6960--nextflow-docs-staging.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.

@adamrtalbot
Copy link
Copy Markdown
Collaborator

See also Kubernetes Node Selectors and Node Affinity which perform a similar function: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/

Indeed, the exisitng nodeLabel method could be ported to this directive.

@adamrtalbot
Copy link
Copy Markdown
Collaborator

Other related tickets I know of:

  1. Ability to dedicate accelerator directive (GPU) over range #5570 (on-prem)
  2. Support reservation when provisioning VM/ accelerators on Google Batch #4262 (GCP)

This may provide useful context in terms of use cases.

@bentsherman
Copy link
Copy Markdown
Member

Related: WDL requirements and hints

@adamrtalbot
Copy link
Copy Markdown
Collaborator

#5850

@bentsherman
Copy link
Copy Markdown
Member

Another use case: scheduling priority for AWS Batch: #6998

@pditommaso
Copy link
Copy Markdown
Member

pditommaso commented Apr 9, 2026

Thanks @robsyme for the thorough ADR. The hints directive is the right direction — we're all aligned on that. Here's a refined proposal for the naming, syntax, and validation semantics.

Key format: camelCase with optional dot-scoped categories

Keys use camelCase and support an optional dot-separated scope to group related hints into logical categories:

process runDragen {
    hints consumableResource: 'my-dragen-license'
    hints 'scheduling.priority': 10
    hints 'scheduling.provisioningModel': 'spot'
}
// nextflow.config
process {
    withName: 'runDragen' {
        hints = [
            consumableResource: 'my-dragen-license',
            'scheduling.provisioningModel': 'spot'
        ]
    }
}

This keeps simple hints flat (consumableResource) while letting related hints cluster under a shared scope (scheduling.priority, scheduling.provisioningModel) — readable without imposing structure where it's not needed.

Optional executor prefix for targeting

When a hint is specific to a given executor or platform, it can be prefixed with an executor/vendor namespace using slash notation:

hints 'aws/consumableResource': 'my-dragen-license'
hints 'seqera/scheduling.provisioningModel': 'spot'
hints 'k8s/scheduling.nodeSelector': 'gpu=true'

Full key format: [executor/][scope.]hintName

Unprefixed hints are "universal" — any executor that understands them can consume them. Prefixed hints are only consumed by the matching executor. This gives pipeline authors a way to be explicit when portability matters and specific when it doesn't.

Value parsing

Hint values are always strings or integers at the Nextflow level. Interpretation and parsing of values is delegated to the implementing executor. A value could be a simple literal:

hints 'scheduling.provisioningModel': 'spot'

Or it could use = as a conventional key-value separator when the executor needs structured content:

hints 'k8s/scheduling.nodeSelector': 'gpu=true'

This keeps the core directive simple (a Map<String, Object>) while giving executors the flexibility to define richer value semantics without burdening the Nextflow config parser.

Validation

Instead of silently ignoring unknown hints (as the current ADR proposes), we should validate against known hints to catch typos and misconfiguration:

  • Unprefixed hints: Nextflow checks against a registry of known hint keys. An unknown key (e.g. scheduling.provisioningModle) produces a warning suggesting the closest match — similar to how we handle unknown directives today.
  • Prefixed hints (e.g. aws/consumableResource): The target executor performs a strict check — an unrecognized key is an error, since the user explicitly declared the executor scope and a typo or unsupported hint should not pass silently.

This two-tier approach balances portability (a pipeline using unprefixed hints can run on executors that don't support them, with a warning) against correctness (a pipeline using executor-prefixed hints gets fast failure if the hint is wrong).

Accumulation vs. replacement semantics

Config overrides use replacement by default, consistent with how other map-type directives (resourceLabels, ext) work:

// This replaces all hints from the process definition
process {
    withName: 'runDragen' {
        hints = ['scheduling.provisioningModel': 'spot']
    }
}

For hints that support accumulation (i.e. adding to rather than replacing), use the + prefix on the key name:

// This adds a consumable resource while preserving existing hints
process {
    withName: 'runDragen' {
        hints = ['+consumableResource': 'another-license']
    }
}

Not all hints support accumulation — it only makes sense for hints that are inherently multi-valued (like consumableResource, where a process might need multiple license types). Scalar hints like scheduling.provisioningModel are single-valued by nature — using + on them should produce an error.

Initial hint catalog

For the first implementation, I'd suggest supporting at least:

Hint key Value type Accumulation Executors Use case
consumableResource String or Map<String,Integer> Yes AWS Batch License-seat-aware scheduling (#5917)
scheduling.provisioningModel String ('spot', 'standard') No AWS Batch, Google Batch, Azure Batch Spot/preemptible instance selection (#4262, #5850)
scheduling.priority Integer No AWS Batch Job scheduling priority (#6998)

As @adamrtalbot noted, K8s node selectors/affinity (#5570) are a natural future candidate (e.g. scheduling.nodeSelector).

Summary of changes vs. current ADR

Aspect Current ADR This proposal
Key format Colon-separated (consumable-resource:name) camelCase with optional dot scope (scheduling.provisioningModel)
Executor scoping Implicit (executor picks what it knows) Explicit optional prefix (aws/hint)
Unknown hints Silently ignored Warning (unprefixed) or error (prefixed)
Config override Accumulation by default Replacement by default, + prefix for accumulation

Signed-off-by: Ben Sherman <bentshermann@gmail.com>
pditommaso added a commit that referenced this pull request Apr 14, 2026
Introduce a new map-type `hints` process directive that provides a
structured, extensible way for pipeline authors to pass executor-specific
scheduling hints. Keys use `[executor/][scope.]hintName` format.

Core features:
- Multiple `hints` calls within a process body accumulate (merge)
- Config overrides via withName:/withLabel: replace the entire map
- Values support String, Integer, and Closure types
- Two-tier validation: warnings for unknown unprefixed keys (global
  registry), errors for unknown executor-prefixed keys
- Initial global catalog contains only `consumableResource`

Seqera Platform integration:
- `seqera/machineRequirement.*` hints map to MachineRequirementOpts
  fields (arch, provisioning, maxSpotAttempts, machineTypes, diskType,
  diskThroughputMiBps, diskIops, diskEncrypted, diskAllocation,
  diskMountPath, diskSize, capacityMode)
- Hints override Seqera config scope values at the task level
- Unknown `seqera/` keys produce an error

Ref: #5917, #6960

Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
@bentsherman bentsherman changed the base branch from master to 260414-hints-directive April 23, 2026 20:01
@bentsherman bentsherman merged commit acf6d95 into 260414-hints-directive Apr 23, 2026
24 checks passed
@bentsherman bentsherman deleted the adr/hints-process-directive branch April 23, 2026 20:02
pditommaso added a commit that referenced this pull request Apr 25, 2026
…7034)

* Add ADR for hints process directive

Propose a generic 'hints' process directive with namespaced keys as
the extension point for executor-specific scheduling hints. First use
case: AWS Batch consumable resources for license-seat management.

Evaluates three options: dedicated consumableResources directive,
overloading resourceLabels, and a new hints directive. Recommends
hints for extensibility and separation of concerns.

Ref: #5917
Signed-off-by: Rob Syme <rob.syme@gmail.com>

* Fix module info formatting separator [ci fast]

Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>

* Update ADR

Signed-off-by: Ben Sherman <bentshermann@gmail.com>

* Add `hints` process directive for executor-specific scheduling hints

Introduce a new map-type `hints` process directive that provides a
structured, extensible way for pipeline authors to pass executor-specific
scheduling hints. Keys use `[executor/][scope.]hintName` format.

Core features:
- Multiple `hints` calls within a process body accumulate (merge)
- Config overrides via withName:/withLabel: replace the entire map
- Values support String, Integer, and Closure types
- Two-tier validation: warnings for unknown unprefixed keys (global
  registry), errors for unknown executor-prefixed keys
- Initial global catalog contains only `consumableResource`

Seqera Platform integration:
- `seqera/machineRequirement.*` hints map to MachineRequirementOpts
  fields (arch, provisioning, maxSpotAttempts, machineTypes, diskType,
  diskThroughputMiBps, diskIops, diskEncrypted, diskAllocation,
  diskMountPath, diskSize, capacityMode)
- Hints override Seqera config scope values at the task level
- Unknown `seqera/` keys produce an error

Ref: #5917, #6960

Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>

* update docs

Signed-off-by: Ben Sherman <bentshermann@gmail.com>

* Add awsbatch/consumableResources hint

Signed-off-by: Ben Sherman <bentshermann@gmail.com>

* Fix HintHelper signatures to match TaskConfig.getHints() [ci fast]

TaskConfig.getHints() returns Map<String, String>, but HintHelper
declared Map<String, Object>, causing @CompileStatic compile errors
in SeqeraTaskHandler.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>

* Use String hint values in HintHelperTest to match production path [ci fast]

TaskConfig.getHints() always delivers Map<String, String>; tests now
reflect that contract instead of relying on generics erasure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>

* Address code review for hints directive

- Enforce Map<String,String> shape; remove AWS-specific KNOWN_HINTS leak
  from core HintDefs. Core validates shape only; executors validate their
  own namespaces.
- AWS Batch: harden consumableResources parser with clear errors, prefer
  awsbatch/-prefixed key, warn on unknown awsbatch/* keys.
- Seqera: derive known hint keys from MachineRequirementOpts via @ConfigOption
  reflection; overlay preserves all declared fields. Accept unprefixed
  machineRequirement.* keys too — prefixed wins on collision. Drop dangling
  references to the removed `arch` field.
- Replace Mock(TaskConfig) integration test in AWS Batch with a real
  ProcessBuilder → TaskConfig path; add compact SeqeraTaskHandler submit
  tests covering hint overlay and foreign-namespace passthrough.
- Docs: spell out unprefixed-applies-to-any-executor semantics; list all
  Seqera-supported hints.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>

* minor edits

Signed-off-by: Ben Sherman <bentshermann@gmail.com>

* Fix ordering of seqera executor config options

Signed-off-by: Ben Sherman <bentshermann@gmail.com>

* Allow hint values to be any raw data type

Signed-off-by: Ben Sherman <bentshermann@gmail.com>

* Update docs/reference/config.md [ci skip]

Co-authored-by: Chris Hakkaart <chris.hakkaart@seqera.io>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>

* Update docs/reference/process.md [ci skip]

Co-authored-by: Chris Hakkaart <chris.hakkaart@seqera.io>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>

* Update docs/reference/process.md [ci skip]

Co-authored-by: Chris Hakkaart <chris.hakkaart@seqera.io>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>

* Update docs/reference/process.md [ci skip]

Co-authored-by: Chris Hakkaart <chris.hakkaart@seqera.io>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>

---------

Signed-off-by: Rob Syme <rob.syme@gmail.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Signed-off-by: Ben Sherman <bentshermann@gmail.com>
Co-authored-by: Rob Syme <rob.syme@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Ben Sherman <bentshermann@gmail.com>
Co-authored-by: Chris Hakkaart <chris.hakkaart@seqera.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants