Expand description
High-level application facade.
Minimal builder API for constructing an AlloraRuntime from a configuration file.
Intended for embedding with only a couple of lines of code.
§Quick Start
use allora_runtime::Runtime;
let rt = Runtime::new().run()?; // attempts to load ./allora.yml§Overview
The builder exposes three operations:
new()– create a fresh builder (auto-discovery enabled)with_config_file(path)– provide an explicit configuration file pathrun()– build and return anAlloraRuntime
If no path is supplied, run() will try a sensible default (allora.yml).
Errors surface via the returned Result.
§Custom Path
let rt = Runtime::new().with_config_file("examples/basic/helloworld/allora.yml").run()?;§Service Wiring & The #[service] Macro
Services are described in configuration (YAML) under service-activator: blocks using a ref-name field.
Example YAML fragment:
version: 1
service-activators:
- ref-name: hello_world
from: inbound.orders
to: vetted.ordersAt runtime, wiring matches each ref-name value against inventory descriptors submitted via
the #[service] attribute macro. The macro registers a constructor closure that builds a
single shared instance (singleton) of your type via its zero-arg new() and invokes its async process method.
§Using #[service]
Apply the attribute to an inherent impl block that contains a zero-arg new() method.
If name is omitted the concrete type name (with spaces removed) is used.
Supported forms:
#[service]– implicit name = type name#[service(name = "custom")]– explicit reference name matching YAMLref-name
Example:
use allora::{service, Service, Exchange, error::Result};
#[derive(Debug)]
struct Uppercase;
impl Uppercase { pub fn new() -> Self { Self } }
#[service(name="uppercase")]
impl Uppercase {}
#[async_trait::async_trait]
impl Service for Uppercase {
async fn process(&self, exchange: &mut Exchange) -> Result<()> {
if let Some(body) = exchange.in_msg.body_text() { exchange.out_msg = Some(Message::from_text(body.to_uppercase())); }
Ok(())
}
}§Descriptor Wiring Criteria
A service is wired only if:
- Its
ref-namematches a registered descriptorname. - Both
fromandtochannel IDs exist in the runtime. - The inbound channel is currently a direct channel (other kinds may be supported later).
§Logging Fields
Structured fields emitted during build:
config.path/config.canonical– discovery detailsservice_activator.ref_name,inbound,outbound– wiring decisionswired.count– number of services wiredchannel.id,kind– registered channelsdescriptor.impl(legacy field name in traces) now maps to descriptorname.
§Testing Notes
- Use #tokio::test for async service wiring tests.
- Macro UI tests (see
tests/macro/) validate diagnostics & naming. - All services share a single instance; design internal mutability carefully.
Structs§
- Runtime
Allorabuilder holds configuration inputs prior to runtime construction.