Skip to content

adamflott/wora

Repository files navigation

wora

Write Once Run Anywhere (WORA): A Rust framework for building applications (daemons, etc.) that run in different environments (Linux, Kubernetes, etc.). Just like Java's claim, it really doesn't run everywhere. no_std or embedded environments are not supported.

Status

This crate is an early-stage async framework. The main public API is usable, with Unix-like platforms as the primary target and environment-specific executors for systemd, launchd, and container-style deployments.

  • restart policies, shutdown supervision, and signal mapping can be applied with RunnerOptions through exec_async_runner_with_options
  • initial typed config and secret loading is built into the runner
  • event-driven apps can use Wora::run_event_loop to auto-apply typed reloads
  • RunnerOptions::with_signal_mapper(...) lets apps map Unix-like signals to control or app-defined events
  • observability can be routed through sinks via O11yProcessor

Feature Tour

  • abstracts over common boilerplate with an API
  • execute the same code in different executors (with or without recompiling)
  • translates platform-specific control inputs into runtime control or app-defined events
  • watches existing metadata and secrets directories and emits typed reload events
  • supervises readiness, health, and graceful shutdown
  • exposes host, process, runtime, and tracing observability events
  • ships observability sinks and a processor for fan-out

Supported Environments

  • async-based apps
  • Unix-like environments
    • Linux-specific host details through procfs
    • macOS host details through sysinfo
  • service-manager and orchestration integrations
    • SystemdExecutor
    • LaunchdExecutor
    • ContainerExecutor

Architecture

WORA has five main pieces:

  • App: the workload lifecycle trait. Applications implement setup, main, reload_config, reload_secrets, and end.
  • AsyncExecutor: the environment adapter. Executors provide directories, setup, readiness, and teardown behavior.
  • Wora: the runtime context passed to apps. It carries directories, host data, event channels, runtime status, and observability options. Health and readiness are reported through Wora::report_health(...), Wora::report_readiness(...), or the cloned RuntimeStatusHandle.
  • WFS: the virtual filesystem abstraction. PhysicalVFS is the host filesystem implementation.
  • LockBackend: the single-instance coordination abstraction. ProcLockBackend uses host lock files and InMemoryLockBackend is useful for tests and fully virtual runner flows.
  • O11yProcessor: the observability pipeline for fan-out into sinks.

exec_async_runner wires those pieces together by creating a lock file, initializing observability, building the Wora context, running executor and app setup, loading initial config and secrets, watching the metadata and secrets directories, invoking App::main, supervising shutdown/readiness/health, and then running teardown.

The runner always installs recursive watchers on both metadata_root_dir and secrets_root_dir after executor and app setup. Executors should create both watch roots even when an app uses NoConfig or NoSecrets; initial loading skips missing config/secrets directories, but watcher installation expects those directories to exist.

Typed config and secret reloads are driven by filesystem watcher events (Event::ConfigChanged and Event::SecretChanged). ControlEvent::ReloadConfiguration, ControlEvent::Suspend, and ControlEvent::LogRotation are app-level control notifications: the runner delivers them to the app but does not automatically reload files, suspend work, or rotate sinks for the app. Use RunnerOptions::with_signal_mapper(...) when the default Unix-like signal mapping should produce app-defined events instead.

When a lock backend reports contention, the runner returns MainEarlyReturn::AlreadyRunning(...) instead of collapsing that case into a generic exit code.

Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.

Prerequisites

  • Rust 1.95 or newer. The crate declares rust-version = "1.95" and the checked-in rust-toolchain.toml pins 1.95.0 for repository builds.

Usage

Run the basic example:

cargo run --example basic

Run the daemon-style event loop example:

cargo run --example async_daemon -- --run-mode user

Run the Linux systemd daemon example:

cargo run --example systemd_daemon

Sample unit file:

examples/systemd_daemon.service

Run the onboarding example:

cargo run --example onboarding

Run checks:

cargo fmt --check
cargo test

AI Disclosure

OpenAI Codex is used to write documentation/tests and find issues. Everything is reviewed by me and I vouch for these AI-generated changes.

Versioning

We use SemVer for versioning when x.y.z when x is > 0, otherwise versioning is arbitrary. For the versions available, see the tags on this repository.

Authors

See also the list of contributors who participated in this project.

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details

Acknowledgments

About

A Rust framework for building applications (daemons, etc) that run in different environments (Linux, Kubernetes, etc)

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages