Runner Orchestration
How Runner.run() coordinates the full lifecycle — validation, connector loop, signal handling, and reporting.
The Runner is the command-line entry point for launching a Lucille run. When invoked, it reads the configuration file, validates all component configurations, generates a unique runId, launches the configured components, waits for all work to complete, and prints a run summary.
A Lucille Run is a sequence of Connectors executed one after the other. Each Connector feeds a specific Pipeline. A run can include multiple Connectors feeding multiple Pipelines, all sharing the same Indexer.
Connectors run strictly in sequence: the next Connector does not start until all documents from the previous Connector have been fully processed and indexed. This ordering guarantee is enforced automatically by the Publisher’s accounting system.
For each Connector in the configured sequence, the Runner:
WorkerPool (N Worker threads based on worker.threads).PublisherImpl and launches the Connector in a ConnectorThread.publisher.waitForCompletion() until all work is done.Local mode (default):
java \
-Dconfig.file=/path/to/config.conf \
-cp 'lucille-core/target/lucille.jar:lucille-core/target/lib/*' \
com.kmwllc.lucille.core.Runner
Distributed mode:
java \
-Dconfig.file=/path/to/config.conf \
-cp 'lucille-core/target/lucille.jar:lucille-core/target/lib/*' \
com.kmwllc.lucille.core.Runner \
-distributed
External mode (single JVM, Kafka messaging):
java \
-Dconfig.file=/path/to/config.conf \
-cp 'lucille-core/target/lucille.jar:lucille-core/target/lib/*' \
com.kmwllc.lucille.core.Runner \
-external
Config validation only (no run):
Validates every Connector, Stage, and Indexer spec and prints all errors. Exits without executing anything.
java \
-Dconfig.file=/path/to/config.conf \
-cp 'lucille-core/target/lucille.jar:lucille-core/target/lib/*' \
com.kmwllc.lucille.core.Runner \
-validate
Render effective config (no run):
Prints the fully resolved configuration after HOCON substitutions (environment variables, include directives, etc.). Useful for debugging config variable expansion.
java \
-Dconfig.file=/path/to/config.conf \
-cp 'lucille-core/target/lucille.jar:lucille-core/target/lib/*' \
com.kmwllc.lucille.core.Runner \
-render
runner {
# Log detailed stage-by-stage metrics at end of run (default: INFO)
metricsLoggingLevel: "INFO"
# Connector timeout in milliseconds (default: 86400000 = 24 hours; set <= 0 to disable)
connectorTimeout: 86400000
}
The Runner generates a UUID runId for each run. The run ID is:
run_id field).At the end of every run, the Runner logs a structured summary:
RUN SUMMARY: Success. 1/1 connectors complete. All published docs succeeded.
connector1: complete. 200000 docs succeeded. 0 docs failed. 0 docs dropped. Time: 416.47 secs.
Run took 417.46 secs.
A connector that failed entirely is distinguished from one that completed with individual document failures. Connectors after a failed one are listed as skipped.
The Runner handles SIGINT (Ctrl+C) and SIGTERM. On signal receipt:
Lucille supports four run types, selected via command-line flags:
| RunType | Flag(s) | Description |
|---|---|---|
LOCAL | (none) | Single JVM, in-memory queues. Default. |
EXTERNAL | -external | Single JVM, Kafka messaging. |
DISTRIBUTED | -distributed | Separate JVMs per component, Kafka messaging. |
TEST | (API only) | Single JVM, in-memory, search backend bypassed, messages captured. |
For deployment instructions — starting runs in each mode, command-line flags, and operational considerations — see Deployment.
For runner and other top-level configuration parameters, see Writing a Config.
How Runner.run() coordinates the full lifecycle — validation, connector loop, signal handling, and reporting.