Rust Customization
The application composition root owns provider pools, trusted identity and tenant values, request policy, audit sinks, telemetry exporters, and lifecycle shutdown. Generated domain crates own model-derived APIs and registration.
Start with:
- Runtime Extension Points
- Database Providers
- Single-binary Deployment
- Observability and Tracing
- Concurrency and Deadlocks
Installing a Runtime Module remains passive. Schema reconciliation is explicit, and telemetry failure must not change business results or suppress audit delivery. Validate every provider or deployment profile against its own dated evidence boundary.
Runtime infrastructure
Rust provides InMemoryDataStore, a separate namespace-aware aggregation
cache, process-local keyed locks, RedisDataStore, and an owner-token Redis
Remote Lock with atomic compare-and-delete release. A required remote provider
must be installed and checked by readiness because an absent optional provider
uses compatibility no-op behavior.
The Rust cloud stack includes provider-neutral registry/discovery/config/health
traits, Nacos v2 gRPC, Consul registration/health, Axum Actuator-compatible
liveness/readiness/info/Prometheus endpoints, CloudApp, and graceful
shutdown. See
Cache, Lock, and Cloud Runtime Infrastructure
for the exact Consul and live-provider evidence boundary.
Worked Example: Trusted Runtime Composition
The generated service runtime constructs the provider. The application then adds policy, audit, tenant, cache, and optional telemetry resources.
use std::sync::Arc;
use teaql_runtime::{DataStore, InMemoryDataStore, UserContext};
pub async fn configured_context(
database_url: String,
app_audit_sink: AppAuditSink,
) -> Result<UserContext, ServiceRuntimeError> {
let mut context = service_runtime(ServiceRuntimeConfig { database_url }).await?;
context.set_request_policy(TrustedRequestPolicy);
context.set_custom_event_sink(app_audit_sink);
context.insert_named_resource("trusted_tenant", "system".to_owned());
context.insert_resource(
Box::new(InMemoryDataStore::default()) as Box<dyn DataStore>
);
context.set_runtime_telemetry(Arc::new(build_runtime_telemetry()));
Ok(context)
}
pub async fn readiness(context: &UserContext) -> Result<(), RuntimeError> {
context
.get_named_resource::<String>("trusted_tenant")
.filter(|tenant| !tenant.trim().is_empty())
.ok_or_else(|| RuntimeError::Behavior("missing trusted tenant".into()))?;
context.ensure_schema().await
}
build_runtime_telemetry() is application-owned and may return
NoopRuntimeTelemetry when OpenTelemetry is disabled. Installing telemetry or
a Runtime Module must not implicitly call ensure_schema().
Worked Example: Cache and Local Lock
let cache_key = format!("{tenant}:currency:{currency_code}");
let lock_key = format!("{tenant}:currency-refresh:{currency_code}");
if let Some(value) = context.get_in_store(&cache_key).await {
return Ok(value);
}
if !context.try_local_lock(&lock_key, 250, 5_000) {
return Err(RuntimeError::Behavior("currency refresh is busy".into()));
}
let result = async {
if let Some(value) = context.get_in_store(&cache_key).await {
return Ok(value);
}
let value = load_authorized_currency_value(context, currency_code).await?;
context.put_in_store(&cache_key, value.clone(), Some(300)).await;
Ok(value)
}.await;
context.unlock_local(&lock_key);
result
For cross-process exclusion, install
Arc<dyn RemoteLockProvider> from RedisRemoteLockProvider, acquire with
try_remote_lock(...).await, and always call unlock_remote(...).await. A
required Redis provider must be checked by readiness because the optional
boundary otherwise returns no-op success.
Worked Example: Cloud Service Startup
CloudApp::new()
.nacos("127.0.0.1:8848")
.namespace("production")
.group("APP")
.service_name("order-service")
.port(8080)
.routes(routes)
.start()
.await?;
This registers the service, merges business and Actuator routes, waits for a shutdown signal, and deregisters. Add database/Redis indicators so readiness represents the deployment rather than only the Nacos connection.