Expand description
§Microde application runtime
microde-application is the Rust implementation of Microde’s composition and
lifecycle runtime. It installs passive and active modules, coordinates their
asynchronous lifecycle hooks, supports orderly stop requests, and reports a
deterministic execution result.
Lifecycle methods return owned, Send, 'static futures. This lets the runtime
poll modules concurrently without borrowing the service or holding a lock across
an await point.
use microde_application::{
MicrodeApplication, MicrodeError, MicrodeModule, ModuleFuture, ModuleKind,
};
struct Worker;
impl MicrodeModule for Worker {
const KIND: ModuleKind = ModuleKind::Passive;
fn run(&mut self) -> ModuleFuture {
Box::pin(async { Ok(()) })
}
fn stop(&mut self) -> ModuleFuture {
Box::pin(async { Ok(()) })
}
}
#[tokio::main]
async fn main() -> Result<(), MicrodeError> {
let mut service = MicrodeApplication::new();
service.install(|_| Worker)?;
let result = service.serve().await?;
assert_eq!(result.exit_code, 0);
assert!(result.error.is_none());
Ok(())
}Use run for a finite application task. Microde starts the modules first and
begins orderly shutdown when the task returns:
let result = service.run(|context| async move {
import_records().await?;
Ok(())
}).await?;Every module declares MicrodeModule::KIND. The default run and stop
operations are no-ops. A passive module’s run future is expected to complete
normally; an active module’s overridden run future should return only after
the module stops. An application’s owned serve or run future can be polled
while another task calls MicrodeApplication::stop; the first stop request wins and
all callers receive the same completed result.
§Explicit dependencies and references
install_named returns an opaque, identity-bearing ModuleHandle. Modules expose
owned values through typed Port and Provider declarations and return their
relationship descriptors from relationships(). Composition binds exact instances:
let database = service.install_named("database", |_| DatabaseModule::new())?;
let orders = service.install_named("orders", |_| OrdersModule::new(database_port.clone()))?;
service.bind(&orders, &orders_database, &database)?;Override setup_with_context to use dependencies. Override run_with_context to
use dependencies or references. Provider values are owned and cloned, preserving
Send + 'static lifecycle futures. Dependency cycles fail before initialization;
reference cycles are allowed and do not affect lifecycle order.
Calling serve or run seals the composition. All bindings and provider factories are
validated and staged before initialization, so a wiring or provider error starts
no lifecycle callback. Named instances are ordered by the dependency graph with
stable IDs as the tie-breaker; teardown, shutdown, and cleanup use the exact
reverse order.
Structs§
- Dependency
- Microde
Application - Composes modules and coordinates their lifecycle.
- Microde
Error - An owned error that can cross the runtime’s concurrency boundaries.
- Microde
Execution Result - The outcome returned after a application finishes its lifecycle.
- Microde
Stop Request - A non-blocking request for orderly lifecycle termination.
- Module
Handle - Opaque binding target for one installed module instance.
- Module
Instance Id - Stable identity of one installed module instance.
- Port
- Nominal runtime identity for a provider contract.
- Provider
- Reference
- Relationship
Descriptor - RunContext
- Setup
Context
Enums§
- Microde
Application State - The observable lifecycle state of a application.
- Module
Kind - Describes whether a module completes independently or requires a stop.
- Relationship
Kind
Traits§
- Microde
Context - Operations exposed by a application to its installed modules.
- Microde
Module - The lifecycle shared by every installed Microde module.
- Relationship
Slot - RunRelationship
Type Aliases§
- Microde
Context Handle - An independently owned module-facing context.
- Module
Future - The object-safe future returned by module lifecycle operations.