FluxDI - Semi-automatic Dependency Injector
A lightweight, type-safe dependency injection container for Rust applications. FluxDI provides ergonomic service registration (including trait-object bindings), transient and singleton lifetimes, semi-automatic dependency resolution, and circular dependency detection.
โจ Features
- ๐ Type-Safe: Leverages Rust's type system for compile-time safety
- ๐ Transient Services: Create new instances on each request
- ๐ Singleton Services: Shared instances with reference counting via
Arc/Rc - ๐ Circular Detection: Prevents infinite loops in dependency graphs
- โ Error Handling: Comprehensive error types with detailed messages
- ๐ Optional Logging: Tracing integration with feature gates
- ๐ Zero-Cost Abstractions: Feature gates enable compile-time optimization
- ๐งต Thread-Safe by Default: Uses
Arc+RwLockfor concurrent access - ๐ฆ Module System: Organize services into reusable modules
- ๐๏ธ Enterprise Ready: Supports layered architecture, repository pattern, and use cases
๐ฆ Installation
Add this to your Cargo.toml:
[]
= { = "../fluxdi" } # For local development
Or from crates.io (when published):
[]
= "1.1.0"
๐ Quick Start
use ;
// Define your services
;
๐ Documentation (mdBook)
FluxDI now includes an mdBook under docs/.
Build docs:
Serve locally:
๏ฟฝ Examples
FluxDI includes ten comprehensive examples showcasing different use cases and patterns:
1. Basic Example
Location: examples/basic/
A simple introduction to FluxDI fundamentals:
- Service registration with
InjectorandProvider - Transient and singleton lifetimes
- Basic dependency resolution with
try_resolve() - Error handling with
Resulttypes
Run:
2. Complex Example (Advanced Patterns)
Location: examples/complex/
Demonstrates enterprise-grade architecture with:
- Domain Layer: Clear entity definitions and repository interfaces
- Application Layer: Use case pattern for business logic
- Infrastructure Layer: SQLite persistence with concrete implementations
- Dependency Injection: Multi-level service composition
- Module System: Modular DI configuration with imported modules
Architecture:
core/
โโโ domain/ (User, Todo entities & repository traits)
โโโ application/ (CreateUserUseCase, GetAllTodoUseCase, etc.)
infra/
โโโ di/ (Modules & dependency registration)
โโโ persistence/ (SQLite repositories)
Run:
Run Tests:
3. Actix-web Example
Location: examples/actix/
Minimal Actix-web integration with FluxDI extractors:
- App-level injector state via
injector_data(...) - Per-handler dependency resolution via
fluxdi::actix::Resolved<T> - Zero-boilerplate extraction for services from the container
Run:
Then request:
4. Axum REST API Example
Location: examples/axum/
Real-world REST API integration with Axum web framework:
- HTTP handler functions with DI-resolved dependencies
- Structured JSON responses with error handling
- CRUD endpoints for Users and Todos
- Service state management via
InjectorState - Automatic per-handler DI resolution via
Resolved<T>extractor - Dependency resolution per-request
- Lifecycle-driven startup via
Module::on_start+Application::bootstrap().await
Features:
POST /users- Create userGET /users- List all usersGET /users/{id}- Get user by IDDELETE /users/{id}- Delete userPOST /todos- Create todoGET /todos- List all todosPUT /todos/{id}/status- Update todo statusDELETE /todos/{id}- Delete todo
Run:
# Terminal 1: Start server
# Terminal 2: Run comprehensive test suite
The test suite includes:
- Server health checks
- Sequential dependency extraction between requests
- HTTP status code validation
- JSON response parsing and assertion
5. Axum Lifecycle Example
Location: examples/axum-lifecycle/
Demonstrates module lifecycle startup with async hooks:
- Register
Routeras DI service - Start
axum::servefromModule::on_start(...) - Bootstrap with
Application::bootstrap().await
Run:
6. Module Sync Bootstrap Example
Location: examples/module-sync/
Minimal module-centric synchronous startup:
- Uses
Module::configure(...)as the single registration hook - Starts with
Application::bootstrap_sync()
Run:
7. Module Async Bootstrap Example
Location: examples/module-async/
Async instance registration and lifecycle orchestration:
- Registers async instance via
Provider::root_async(...) - Uses
Application::bootstrap().await - Demonstrates lifecycle prewarm in
on_start(...)
Run:
8. SeaORM SQLite Module Example
Location: examples/seaorm-sqlite/
SeaORM + SQLite integration through FluxDI module lifecycle:
- Registers
DatabaseConnectionviaProvider::root_async(...) - Uses
Module::on_start(...)to run a startup connectivity check (SELECT 1) - Boots with
Application::bootstrap().await
Run:
9. Dual HTTP Random-Port Example
Location: examples/dual-http-random-port/
Runs two HTTP services in one module lifecycle:
- Randomly binds both services in
30000-65535 - Starts both servers concurrently in
on_start(...) - Gracefully aborts both tasks in
on_stop(...)
Run:
10. Mixed Sync + Async Module Example
Location: examples/module-mixed-sync-async/
Demonstrates sync and async providers in the same module:
- Registers sync providers with
Provider::root(...)andProvider::transient(...) - Registers async providers with
Provider::root_async(...) - Uses sync
resolve(...)and asynctry_resolve_async(...).awaitin the same startup flow
Run:
๏ฟฝ๐ Usage Guide
Service Registration
Transient Services
Create new instances on each request:
use ;
use Uuid;
let injector = root;
// Transient: new instance each time (default behavior)
injector.;
let logger1 = injector.;
let logger2 = injector.;
// logger1 and logger2 are different instances
Singleton Services
Create once and share across all dependents:
use ;
let injector = root;
// Singleton: same instance every time
injector.;
let config1 = injector.;
let config2 = injector.;
// config1 and config2 point to the same instance
Error Handling
FluxDI provides both panicking and non-panicking variants:
use ;
let injector = root;
injector.;
// Non-panicking (try_resolve returns Result)
match injector.
// Trying to resolve an unregistered type
match injector.
Dependency Injection
Services can depend on other services. Use module-based registration for clean organization:
use ;
// Define a module for persistence services
;
let injector = root;
let module = PersistenceModule;
module.providers;
let repo = injector.;
๐ Advanced Features
Circular Dependency Detection
FluxDI automatically detects and prevents circular dependencies by tracking resolution paths:
use ;
// Example: attempting to create circular dependencies will fail
let injector = root;
// These registrations will create a circular dependency
// Attempting to resolve either service will result in an error
// Error: "Circular dependency detected in resolution path"
Resource Limits
You can constrain concurrent factory execution per provider:
use ;
let injector = root;
injector.;
Available policies:
Policy::Deny: fail immediately withResourceLimitExceeded.Policy::Block: wait for a free slot (supported whenthread-safeis enabled).
Timeout support:
use Duration;
use ;
injector.;
Async non-blocking wait (optional):
[]
= { = "../fluxdi", = ["thread-safe", "async-factory", "resource-limit-async"] }
Tracing Integration
Enable the tracing feature for automatic logging:
[]
= { = "../fluxdi", = ["tracing"] }
use ;
use info;
;
async
OpenTelemetry Bridge
Enable OpenTelemetry bridge support with the opentelemetry feature:
[]
= { = "../fluxdi", = ["opentelemetry"] }
= { = "0.29", = ["trace"] }
use TracerProvider as _;
use SdkTracerProvider;
use opentelemetry_layer;
use ;
fluxdi only provides tracing-to-OTel wiring helpers (opentelemetry_layer and
try_init_opentelemetry) and does not auto-install exporters.
Service Metrics and Prometheus Export
Enable metrics collection:
[]
= { = "../fluxdi", = ["metrics"] }
Enable Prometheus text export (prometheus implies metrics):
[]
= { = "../fluxdi", = ["prometheus"] }
use ;
Async Factory Support
Enable async factories with the async-factory feature:
[]
= { = "../fluxdi", = ["async-factory"] }
use ;
async
Resolution strategy:
- If a type is registered with
Provider::*_async, resolve it withtry_resolve_async/resolve_async. - Sync providers (
Provider::root/singleton/transient) work with both sync and async resolve APIs. - Sync resolve against an async provider returns
AsyncFactoryRequiresAsyncResolve.
Runnable example:
Module Async Lifecycle Hooks
Module now supports async hooks for startup/shutdown orchestration:
configure(injector)as the primary, unified provider registration hookproviders_async(injector)as a legacy-compatible alias (new code should useconfigure)on_start(injector)to start runtime resources (for example, an Axum listener)on_stop(injector)to release resources in reverse module order
Use Application::bootstrap().await and Application::shutdown().await as the unified lifecycle APIs.
use ;
;
async
๐งช Testing
Unit Tests
Run the crate test suite:
# Run all tests for the workspace
# Run tests for the fluxdi crate only
# Run with tracing feature
# Run with async factory feature
# Run documentation tests
๐ Project Structure
fluxdi/
โโโ fluxdi/ # FluxDI library crate
โ โโโ src/ # core implementation (injector, provider, runtime)
โ โโโ README.md # This file
โโโ examples/
โ โโโ basic/ # Basic usage example with simple DI
โ โโโ complex/ # Advanced DI patterns with SQLite, repositories, use cases
โ โ โโโ src/
โ โ โ โโโ core/ # Domain (entities, use cases)
โ โ โ โโโ infra/ # Infrastructure (persistence, DI configuration)
โ โ โโโ test.sh # Test script for complex example
โ โโโ actix/ # Actix-web integration example
โ โ โโโ src/
โ โ โโโ main.rs # Minimal Actix extractor usage
โ โโโ axum-lifecycle/ # Axum startup in Module::on_start lifecycle hook
โ โ โโโ src/
โ โ โโโ main.rs # Lifecycle-driven server bootstrap
โ โโโ module-sync/ # Sync module bootstrap with configure()
โ โ โโโ src/
โ โ โโโ main.rs # bootstrap_sync usage
โ โโโ module-async/ # Async module bootstrap with async providers
โ โ โโโ src/
โ โ โโโ main.rs # bootstrap().await + root_async provider
โ โโโ module-mixed-sync-async/ # Sync and async providers in one module
โ โ โโโ src/
โ โ โโโ main.rs # mixed resolve + try_resolve_async usage
โ โโโ seaorm-sqlite/ # SeaORM + SQLite module lifecycle example
โ โ โโโ src/
โ โ โโโ main.rs # on_start connectivity check (SELECT 1)
โ โโโ dual-http-random-port/ # Two HTTP servers with random 30000-65535 ports
โ โ โโโ src/
โ โ โโโ main.rs # concurrent startup in on_start + abort in on_stop
โ โโโ axum/ # REST API with Axum web framework
โ โโโ src/
โ โ โโโ main.rs # HTTP handlers with DI integration
โ โโโ test.sh # Comprehensive API test suite
โโโ README.md
๐ง Configuration
Feature Flags
FluxDI exposes a small set of feature flags. See fluxdi/Cargo.toml for the authoritative list:
debug(enabled by default) โ enables extra debug formatting in selected types and errors.thread-safe(optional) โ switches internal shared pointer and synchronization primitives toArc+RwLockfor concurrent access.lock-free(optional) โ usesDashMapfor provider/instance stores inthread-safemode.tracing(optional) โ enables tracing logs and spans during registration and resolution.opentelemetry(optional) โ adds OpenTelemetry bridge helpers influxdi::observability.metrics(optional) โ enables internal injector counters andInjector::metrics_snapshot().prometheus(optional) โ enablesInjector::prometheus_metrics()text export (includesmetrics).actix(optional) โ enables Actix-web integration helpers and extractors (and enablesthread-safe).axum(optional) โ enables Axum integration helpers and extractors (and enablesthread-safe).async-factory(optional) โ enablesProvider::*_asyncandInjector::*_resolve_asyncAPIs.resource-limit-async(optional) โ uses Tokio semaphore for non-blocking async waits in resource limits.
The crate default is currently default = ["debug"]. If you need multithreaded use, enable thread-safe.
Environment Variables
When using the tracing feature, you can control logging levels:
# Set log level
RUST_LOG=debug
# Enable only FluxDI logs
RUST_LOG=fluxdi=info
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development Setup
- Clone the repository:
- Run tests:
- Check formatting:
- Run clippy:
๐ Roadmap & TODO
๐งต Thread Safety
- Arc-based Runtime: Thread-safe version of FluxDI using
Arcinstead ofRc(implemented behind thethread-safefeature) - Send + Sync Services: Support for
Send + Syncservices in thread-safe mode (enforced by API bounds) - Concurrent Access: Concurrent reads/writes supported via
RwLockin thread-safe mode - Lock-free Operations: Optional
lock-freefeature (DashMap) for high-concurrency resolve paths
๐ง Advanced Features
- Lazy Initialization: Singleton instances are created on first
resolve - Service Metrics: Internal counters + timing totals via
metrics_snapshot - Resource Limits: Per-provider concurrent creation limits with
Limits+Policy
๐ฆ Ecosystem Integration
- Async Factory Support: Async/await provider factories via
Provider::*_async+Injector::*_resolve_async - Actix-web Integration:
fluxdi::actix::{Resolved<T>, ServiceConfigExt, injector_data} - Axum Integration: Demonstrated with REST API example and state management
- Axum Auto-Resolve Plugin:
fluxdi::axum::Resolved<T>extractor for per-handler resolution - Rocket Integration: Layer and extractor support for Rocket web framework
๏ฟฝ๏ธ Architectural Patterns
- Repository Pattern: Demonstrated in complex example with SQLite repositories
- Layered Architecture: Clean separation of domain, application, and infrastructure layers
- Use Case Pattern: Business logic encapsulated in use cases with DI
- Web Framework Integration: Explored with Axum + Actix-web
๏ฟฝ๐ ๏ธ Developer Experience
- Derive Macros: Auto-generate factory functions from service structs (
#[injectable]) - Error Suggestions: Better error messages with fix suggestions
๐ Observability
- OpenTelemetry: Optional tracing bridge helpers via
opentelemetry_layer/try_init_opentelemetry - Prometheus Metrics:
prometheus_metrics()text export for scraping
๐ฏ Performance
- Memory Optimization: Reduced memory footprint for large containers
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments
- Inspired by dependency injection patterns from other languages and frameworks
- Built with โค๏ธ using Rust's powerful type system
- Thanks to the Rust community for excellent crates and documentation
FluxDI - A semi-automatic dependency injection container for Rust
Repository: DaiYuANg/fluxdi
Made with โค๏ธ by the Binary Sea Team