nexora-runtime
ExecutionEngine — ties the planner and scheduler together into a single execution unit. You do not use this directly; NexoraEngine (in nexora-api) is the public entry point.
Responsibilities
- Accept an
Intentand pass it to theCompositePlannerto produce aPlan. - Create an
ExecutionContextwith a newtraceIdandexecutionId. - Persist an
ExecutionRecordvia theExecutionStore(if configured). - Hand the
Planand context to theDagStepScheduler. - On completion (success or failure), update the persisted record and fire a
PlanCompleted/Failedevent.
Execution flow
Intent
└─ CompositePlanner.plan()
└─ Plan
└─ DagStepScheduler.execute()
├─ Step A (no deps) ──► CapabilityInvoker ──► InterceptorPipeline
├─ Step B (no deps) ──► CapabilityInvoker ──► InterceptorPipeline
└─ Step C (deps: A,B) ──► (waits) ──► CapabilityInvoker
└─ ExecutionResult
Thread model
By default, the engine uses Executors.newVirtualThreadPerTaskExecutor() (Java 21 virtual threads). Each step runs on its own virtual thread, allowing thousands of concurrent steps with minimal OS thread overhead.
Override the executor to use a platform thread pool or a custom thread factory:
NexoraEngine engine = NexoraEngine.builder()
.withExecutor(Executors.newFixedThreadPool(20))
.build();
Async execution
NexoraEngine.execute() returns a CompletableFuture<ExecutionResult>. The future completes when the entire plan finishes (or fails).
engine.execute(intent)
.thenAccept(result -> log.info("status={}", result.status()))
.exceptionally(ex -> { log.error("Execution failed", ex); return null; });
Use .join() for synchronous callers, but be aware this will block the calling thread.