Enum Class JobDispatcher
- All Implemented Interfaces:
Serializable, Comparable<JobDispatcher>, Constable
harness/PACKAGE.md states
the contract; the section "The dispatch contract" carries the numbers.- Since:
- 0.1 (2025-09-18)
- Author:
- Andrey Santrosyan
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordScheduler configuration.Nested classes/interfaces inherited from class Enum
Enum.EnumDesc<E> -
Enum Constant Summary
Enum Constants -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final longThe graceful drain window ashutdown(long)caller uses when it has no deployment-specific number. -
Method Summary
Modifier and TypeMethodDescriptionbooleanCancels a job;JobHandle.cancel(String)calls this.intcancelWorkflow(String workflowId, String reason) Cancels all jobs belonging to a workflow.The sealed envelope.getHeart()The heartbeat engine, for operator surfaces (store inspection, cancellation).static JobDispatcherThe one instance, under the name callers read most naturally; the same object asINSTANCE.Gets the message bus for event subscription.Gets statistics for the unified execution system.booleanChecks if the dispatcher is running.<T extends JobEvent>
MessageBus.SubscriptionobserveWorkflow(AbstractWorkflowObserver<T> observer, Class<T> eventType) Subscribes an AbstractWorkflowObserver to its workflow's events.observeWorkflow(String workflowId, JobObserver<JobEvent> observer) Subscribes an observer to all events from a specific workflow.voidregisterForShutdown(Stoppable stoppable) Registers a component for graceful shutdown.voidregisterSpendGate(SpendGate gate) voidscheduleHeartbeat(ScheduleHeartbeat spec, String userId) The authority-bearing heartbeat entry for code OUTSIDE any job - boot wiring, an operator endpoint with an authenticated session.voidsealComplianceEnvelope(ComplianceEnvelope envelope) Seals the envelope - once, permanently.voidshutdown(long timeoutMs) Shuts down the dispatcher and all active schedulers.voidstart()Starts the dispatcher.<T> JobHandle<T> Submits a job for execution without dependencies.<T,D> JobHandle <T> Submits a job with a single typed dependency.<T,D> JobHandle <T> Submits a job with multiple dependencies.<T> JobHandle<T> Submits a job for execution with initial metadata seeded into the job's context.<T> JobHandle<T> Submits a job with initial metadata and dependencies - the full form the two simpler overloads delegate to.<T> CompletableFuture<JobHandle<T>> submitWithDelay(Job<T> job, Duration delay) Submits a job after a delay using a virtual thread.<T extends JobEvent>
MessageBus.Subscriptionsubscribe(JobObserver<T> observer, Class<T> eventType) Subscribes an observer to job events.<T extends JobEvent>
MessageBus.Subscriptionsubscribe(JobObserver<T> observer, Class<T> eventType, Class<? extends Job> jobType) Subscribes an observer to job events from specific job types.static JobDispatcherReturns the enum constant of this class with the specified name.static JobDispatcher[]values()Returns an array containing the constants of this enum class, in the order they are declared.
-
Enum Constant Details
-
INSTANCE
-
-
Field Details
-
DEFAULT_SHUTDOWN_TIMEOUT_MS
public static final long DEFAULT_SHUTDOWN_TIMEOUT_MSThe graceful drain window ashutdown(long)caller uses when it has no deployment-specific number.- See Also:
-
-
Method Details
-
values
Returns an array containing the constants of this enum class, in the order they are declared.- Returns:
- an array containing the constants of this enum class, in the order they are declared
-
valueOf
Returns the enum constant of this class with the specified name. The string must match exactly an identifier used to declare an enum constant in this class. (Extraneous whitespace characters are not permitted.)- Parameters:
name- the name of the enum constant to be returned.- Returns:
- the enum constant with the specified name
- Throws:
IllegalArgumentException- if this enum class has no constant with the specified nameNullPointerException- if the argument is null
-
getInstance
The one instance, under the name callers read most naturally; the same object asINSTANCE. -
sealComplianceEnvelope
Seals the envelope - once, permanently. A second seal throws. -
getComplianceEnvelope
The sealed envelope. A read before any seal returns the refusing default WITHOUT sealing, so an early reader gets deterministic default-deny and the servlet's later legitimate seal still lands. -
registerSpendGate
-
submit
-
submit
Submits a job for execution with initial metadata seeded into the job's context. The metadata is seeded before any lifecycle event (JobScheduled, JobStartedEvent, TerminalEvent) fires for the job, so all downstream observers see the seeded keys in the snapshot's metadata map.The dispatcher is semantically opaque about the contents: it forwards the map into the child's
JobContextviaJobContext.putMetadata(String, Object)and does not interpret any key. Callers choose the key namespace (e.g.AbstractOrchestrator.META_ITERATION,Tool.OBS_INPUT).- Type Parameters:
T- the job's return type- Parameters:
job- the job to submitinitialMetadata- metadata entries to seed into the job's context, or null for none- Returns:
- a handle to monitor and control the job
-
submit
Submits a job with a single typed dependency. Type-safe method where the dependency type D is captured at compile time.Usage Example:
JobHandle<Data> dataHandle = dispatcher.submit(extractJob); JobHandle<Report> reportHandle = dispatcher.submit(reportJob, dataHandle); // reportJob can access Data result via context.singleDependencyResult()- Type Parameters:
T- the job's return typeD- the dependency's return type- Parameters:
job- the job to submitdependency- the single job that must complete first- Returns:
- a handle to monitor and control the job
-
submit
Submits a job with multiple dependencies.For homogeneous dependencies (all same type D):
List<JobHandle<Data>> dataHandles = List.of(h1, h2, h3); JobHandle<Report> report = dispatcher.submit(synthJob, dataHandles); // Inside synthJob.execute(): List<Data> allData = context.allDependencyResults();For heterogeneous dependencies (mixed types):
List<JobHandle<?>> mixedHandles = List.of(dataHandle, configHandle, statusHandle); JobHandle<Report> report = dispatcher.submit(synthJob, mixedHandles); // Inside synthJob.execute(): Map<JobSnapshot, Object> results = context.getDependencyResults(); for (var entry : results.entrySet()) { if (entry.getKey().jobClass() == DataJob.class) { Data data = (Data) entry.getValue(); } }- Type Parameters:
T- the job's return typeD- the dependency type (for homogeneous), or ? for heterogeneous- Parameters:
job- the job to submitdependencies- list of jobs that must complete first- Returns:
- a handle to monitor and control the job
-
submit
public <T> JobHandle<T> submit(Job<T> job, Map<String, Object> initialMetadata, List<? extends JobHandle<?>> dependencies) Submits a job with initial metadata and dependencies - the full form the two simpler overloads delegate to. Orchestrators use it to stamp their bookkeeping metadata onto dependency-sequenced children.- Type Parameters:
T- the job's return type- Parameters:
job- the job to submitinitialMetadata- metadata visible on the context from the start, or nulldependencies- jobs that must complete first, or null- Returns:
- a handle to monitor and control the job
-
submitWithDelay
Submits a job after a delay using a virtual thread. The delay allows parent transactions to commit before the job starts, solving race conditions where a job needs to see committed data.For root-level jobs only: the delayed submission happens on a fresh virtual thread, which is not any live job's executing thread, so the submission door admits it only when the job's parent is not a live job - exactly the shape of a workflow root. An orchestrator that wants delayed work inside its subtree sequences it behind a dependency instead.
Usage Example:
// Submit job with 500ms delay to ensure transaction commits dispatcher.submitWithDelay( new ReindexJob(root, documentId), Duration.ofMillis(500) ).thenAccept(handle -> { log.info("Job started: {}", handle.getJobId()); });- Type Parameters:
T- the job's return type- Parameters:
job- the job to submitdelay- the delay before submission (null, zero, or negative means immediate)- Returns:
- CompletableFuture that completes with the JobHandle after the delay
-
start
public void start()Starts the dispatcher. Schedulers are started on demand when jobs are submitted. -
shutdown
public void shutdown(long timeoutMs) Shuts down the dispatcher and all active schedulers.- Parameters:
timeoutMs- maximum time to wait for shutdown
-
isRunning
public boolean isRunning()Checks if the dispatcher is running. -
registerForShutdown
Registers a component for graceful shutdown. -
getMessageBus
Gets the message bus for event subscription. Public to allow advanced usage, but prefer using the subscription methods. -
getHeart
The heartbeat engine, for operator surfaces (store inspection, cancellation). -
scheduleHeartbeat
The authority-bearing heartbeat entry for code OUTSIDE any job - boot wiring, an operator endpoint with an authenticated session. Demands a principal exactly likeJob.workflow; the platform threat model trusts code, so a trusted caller naming a principal here is the same posture as every root-workflow submission. Jobs never call this: an orchestrator schedules by publishing the spec throughJobContext.publish, which captures its identity and sealed guard; a non-orchestrator cannot schedule at all. -
subscribe
public <T extends JobEvent> MessageBus.Subscription subscribe(JobObserver<T> observer, Class<T> eventType) Subscribes an observer to job events. This is the main public API for event subscription.- Type Parameters:
T- the event type- Parameters:
observer- the observer to registereventType- the type of events to observe- Returns:
- a subscription handle that can be used to unsubscribe
-
subscribe
public <T extends JobEvent> MessageBus.Subscription subscribe(JobObserver<T> observer, Class<T> eventType, Class<? extends Job> jobType) Subscribes an observer to job events from specific job types.- Type Parameters:
T- the event type- Parameters:
observer- the observer to registereventType- the type of events to observejobType- the job type to filter by (null for all job types)- Returns:
- a subscription handle that can be used to unsubscribe
-
observeWorkflow
Subscribes an observer to all events from a specific workflow. This is a convenience method that creates a filtered observer for workflow events.- Parameters:
workflowId- the workflow ID to observeobserver- the observer to handle workflow events- Returns:
- a subscription handle that can be used to unsubscribe
-
observeWorkflow
public <T extends JobEvent> MessageBus.Subscription observeWorkflow(AbstractWorkflowObserver<T> observer, Class<T> eventType) Subscribes an AbstractWorkflowObserver to its workflow's events. This method automatically sets the subscription on the observer for self-cleanup.- Type Parameters:
T- the event type the observer handles- Parameters:
observer- the workflow observer to subscribeeventType- the class of events to observe- Returns:
- a subscription handle that can be used to unsubscribe
-
cancel
Cancels a job;JobHandle.cancel(String)calls this. A job still in a queue leaves it, is recorded CANCELLED, and its waiters are released with aJobCancelledException. A running job is signalled through its context, and its own unwinding settles the state, the event and the handle. A caller waiting on the handle gets an ExecutionException whose cause is JobCancelledException.- Parameters:
jobId- the ID of the job to cancelreason- the cancellation reason- Returns:
- true if the job was found and cancellation was initiated
-
cancelWorkflow
Cancels all jobs belonging to a workflow.This method cancels all running and queued jobs that share the specified workflowId. Useful for fail-fast scenarios where one job failure should abort the entire workflow.
- Parameters:
workflowId- the workflow ID to cancelreason- the cancellation reason- Returns:
- the number of jobs cancelled
-
getStatistics
-