You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In graph config allow user to specify delay, next state would be queued after specified delay.
Motivation
Workflow pacing – Many workflows need delays between steps (e.g., rate limiting, waiting for external systems, cooling-off periods).
Time-based orchestration – Enable workflows with built-in timing without requiring nodes to raise ReQueueAfterSignal.
Declarative delays – Configure delays at graph definition time rather than in node code, improving separation of concerns.
Batch processing – Add delays between batch operations to avoid overwhelming downstream systems.
Current State
What Exists
Component
Location
Purpose
next_nodes
GraphNodeModel / NodeTemplate
List of node identifiers to execute next
enqueue_after
State model
Timestamp (ms) when state should be enqueued
create_next_states
state-manager/app/tasks/create_next_states.py
Creates next states when current state completes
ReQueueAfterSignal
python-sdk/exospherehost/signals.py
Programmatic delay via exception (requires node code changes)
Current Limitations
No way to specify delays in graph configuration
Must use ReQueueAfterSignal in node code to add delays
Delays are not visible in graph definition
Cannot configure different delays for different next nodes from the same node
Proposed Solution
Delay Configuration per Next Node
Allow specifying a delay for each next node connection in the graph configuration. When a state completes, the next states will be created with enqueue_after set to current time + delay.
Key Features
Per-edge delays – Configure delay for each next_nodes entry
Flexible delay format – Support milliseconds (integer) or human-readable strings (e.g., "5m", "1h", "30s")
Backward compatibility – If no delay specified, next states are enqueued immediately (current behavior)
Multiple next nodes – Each next node can have its own delay
Recommended: Separate field for backward compatibility
Control Flow
flowchart TD
A["State completes successfully"] --> B["create_next_states() called"]
B --> C["Get next_node_identifiers from template"]
C --> D["For each next_node"]
D --> E{"Delay configured?"}
E -->|yes| F["Calculate enqueue_after = now + delay"]
E -->|no| G["enqueue_after = now (immediate)"]
F --> H["Create State with enqueue_after"]
G --> H
H --> I["State will be enqueued at enqueue_after time"]
Loading
Acceptance Criteria
GraphNodeModel supports next_node_delays field (optional dict)
NodeTemplate supports next_node_delays field (optional dict)
Validation: delay values must be non-negative integers
Validation: delay keys must match valid next_node identifiers
create_next_states applies delays when creating next states
States with delays have correct enqueue_after timestamp
Backward compatibility: graphs without delays work as before
Unit tests for delay application logic
Integration tests for end-to-end delay flow
Documentation updated in docs/exosphere/graph-components.md
Engineering Tasks
Python SDK:
Add next_node_delays field to GraphNodeModel in exospherehost/models.py
Add validation for delay values (non-negative integers)
Add validation that delay keys match next_nodes identifiers
State Manager:
Add next_node_delays field to NodeTemplate in app/models/node_template_model.py
Update create_next_states to apply delays when creating states
Validate delay keys exist in next_nodes during graph validation
Testing:
Unit tests for delay validation
Integration tests for delayed state creation
Test backward compatibility (no delays specified)
Test multiple next nodes with different delays
Documentation:
Update docs/exosphere/graph-components.md with delay configuration
Add examples showing delay usage
Document delay behavior and timing
Risks & Mitigations
Risk
Mitigation
Breaking change for existing graphs
Make next_node_delays optional, default to immediate enqueue (backward compatible)
Invalid delay keys (typos, removed nodes)
Validate during graph validation, reject invalid graphs
Negative delays causing immediate execution
Validate delays are non-negative during graph creation
Very large delays causing states to be enqueued far in future
Consider max delay limit (e.g., 1 year) or document behavior
Delay precision confusion
Document that delays are in milliseconds, show examples
Open Questions
Delay format: Should we support human-readable strings (e.g., "5m", "1h") in addition to milliseconds?
Maximum delay: Should there be a maximum delay cap to prevent accidental long-term scheduling?
Delay validation: Should delays be validated at graph creation time or state creation time?
Dashboard UI: How should delays be displayed in the graph visualization?
Absolute vs relative: Should we support absolute timestamps (like RequeueAtSignal) in addition to relative delays?
Additional Notes
This feature complements ReQueueAfterSignal - use graph-level delays for declarative timing, signal-based delays for dynamic timing
Delays are applied at state creation time, not at node execution time
Consider future enhancement: delay expressions based on node outputs (e.g., delay based on data size)
Aligns with feature-plan feat: RequeueAtSignal #587 (RequeueAtSignal) - both provide timing control but at different levels
In graph config allow user to specify delay, next state would be queued after specified delay.
Motivation
ReQueueAfterSignal.Current State
What Exists
next_nodesGraphNodeModel/NodeTemplateenqueue_afterStatemodelcreate_next_statesstate-manager/app/tasks/create_next_states.pyReQueueAfterSignalpython-sdk/exospherehost/signals.pyCurrent Limitations
ReQueueAfterSignalin node code to add delaysProposed Solution
Delay Configuration per Next Node
Allow specifying a delay for each next node connection in the graph configuration. When a state completes, the next states will be created with
enqueue_afterset to current time + delay.Key Features
next_nodesentryProposed Design
Data Model
Graph Node Configuration:
Current structure:
{ "node_name": "DataLoader", "identifier": "loader", "next_nodes": ["processor", "validator"] }Proposed structure:
{ "node_name": "DataLoader", "identifier": "loader", "next_nodes": ["processor", "validator"], "next_node_delays": { "processor": 5000, "validator": 10000 } }Alternative: Delay as part of next_nodes mapping
{ "node_name": "DataLoader", "identifier": "loader", "next_nodes": { "processor": {"delay": 5000}, "validator": {"delay": 10000} } }Recommended: Separate field for backward compatibility
Control Flow
flowchart TD A["State completes successfully"] --> B["create_next_states() called"] B --> C["Get next_node_identifiers from template"] C --> D["For each next_node"] D --> E{"Delay configured?"} E -->|yes| F["Calculate enqueue_after = now + delay"] E -->|no| G["enqueue_after = now (immediate)"] F --> H["Create State with enqueue_after"] G --> H H --> I["State will be enqueued at enqueue_after time"]Acceptance Criteria
GraphNodeModelsupportsnext_node_delaysfield (optional dict)NodeTemplatesupportsnext_node_delaysfield (optional dict)create_next_statesapplies delays when creating next statesenqueue_aftertimestampdocs/exosphere/graph-components.mdEngineering Tasks
Python SDK:
next_node_delaysfield toGraphNodeModelinexospherehost/models.pynext_nodesidentifiersState Manager:
next_node_delaysfield toNodeTemplateinapp/models/node_template_model.pycreate_next_statesto apply delays when creating statesnext_nodesduring graph validationTesting:
Documentation:
docs/exosphere/graph-components.mdwith delay configurationRisks & Mitigations
next_node_delaysoptional, default to immediate enqueue (backward compatible)Open Questions
RequeueAtSignal) in addition to relative delays?Additional Notes
ReQueueAfterSignal- use graph-level delays for declarative timing, signal-based delays for dynamic timing