118 lines
3.3 KiB
Markdown
118 lines
3.3 KiB
Markdown
|
|
# ADR-002: Axum como Backend Framework
|
||
|
|
|
||
|
|
**Status**: Accepted | Implemented
|
||
|
|
**Date**: 2024-11-01
|
||
|
|
**Deciders**: Backend Architecture Team
|
||
|
|
**Technical Story**: Selecting REST API framework with optimal async/middleware composition for Tokio ecosystem
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Decision
|
||
|
|
|
||
|
|
Usar **Axum 0.8.6** como framework REST API (no Actix-Web, no Rocket) para exponer 40+ endpoints de VAPORA.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Rationale
|
||
|
|
|
||
|
|
1. **Composable Middleware**: Tower ecosystem provides first-class composable middleware patterns
|
||
|
|
2. **Type-Safe Routing**: Router defined as strong types (not string-based paths)
|
||
|
|
3. **Tokio Ecosystem**: Built directly on Tokio (not abstraction layer), enabling precise async control
|
||
|
|
4. **Extractors**: Powerful extractor system (`Json`, `State`, `Path`, custom extractors) reduces boilerplate
|
||
|
|
5. **Performance**: Zero-copy response bodies, streaming support, minimal overhead
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Alternatives Considered
|
||
|
|
|
||
|
|
### ❌ Actix-Web
|
||
|
|
- Mature framework with larger ecosystem
|
||
|
|
- **Cons**: Actor model adds complexity, different async patterns than Tokio, harder to integrate with Tokio primitives
|
||
|
|
|
||
|
|
### ❌ Rocket
|
||
|
|
- Developer-friendly API
|
||
|
|
- **Cons**: Synchronous-first (async as afterthought), less composable, worse error handling
|
||
|
|
|
||
|
|
### ✅ Axum (CHOSEN)
|
||
|
|
- Minimal abstraction over Tokio/Tower
|
||
|
|
- **Pros**: Composable, type-safe, Tokio-native, growing ecosystem
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Trade-offs
|
||
|
|
|
||
|
|
**Pros**:
|
||
|
|
- ✅ Composable middleware (Tower trait-based)
|
||
|
|
- ✅ Type-safe routing with strong types
|
||
|
|
- ✅ Zero-cost abstractions, excellent performance
|
||
|
|
- ✅ Perfect integration with Tokio async ecosystem
|
||
|
|
- ✅ Streaming responses, WebSocket support built-in
|
||
|
|
|
||
|
|
**Cons**:
|
||
|
|
- ⚠️ Smaller ecosystem than Actix-Web
|
||
|
|
- ⚠️ Steeper learning curve (requires understanding Tower traits)
|
||
|
|
- ⚠️ Fewer third-party integrations available
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Implementation
|
||
|
|
|
||
|
|
**Router Definition**:
|
||
|
|
```rust
|
||
|
|
let app = Router::new()
|
||
|
|
.route("/api/v1/projects", post(create_project).get(list_projects))
|
||
|
|
.route("/api/v1/projects/:id", get(get_project).put(update_project))
|
||
|
|
.route("/metrics", get(metrics_handler))
|
||
|
|
.layer(TraceLayer::new_for_http())
|
||
|
|
.layer(CorsLayer::permissive())
|
||
|
|
.layer(Extension(Arc::new(app_state)));
|
||
|
|
|
||
|
|
let listener = TcpListener::bind("0.0.0.0:8001").await?;
|
||
|
|
axum::serve(listener, app).await?;
|
||
|
|
```
|
||
|
|
|
||
|
|
**Key Files**:
|
||
|
|
- `/crates/vapora-backend/src/main.rs:126-259` (router setup)
|
||
|
|
- `/crates/vapora-backend/src/api/` (handlers)
|
||
|
|
- `/crates/vapora-backend/Cargo.toml` (dependencies)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Verification
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Build backend
|
||
|
|
cargo build -p vapora-backend
|
||
|
|
|
||
|
|
# Test API endpoints
|
||
|
|
cargo test -p vapora-backend -- --nocapture
|
||
|
|
|
||
|
|
# Run server and check health
|
||
|
|
cargo run -p vapora-backend &
|
||
|
|
curl http://localhost:8001/health
|
||
|
|
curl http://localhost:8001/metrics
|
||
|
|
```
|
||
|
|
|
||
|
|
**Expected**: 40+ endpoints accessible, health check responds 200 OK, metrics endpoint returns Prometheus format
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Consequences
|
||
|
|
|
||
|
|
- All HTTP handling must use Axum extractors (learning curve for team)
|
||
|
|
- Request/response types must be serializable (integration with serde)
|
||
|
|
- Middleware stacking order matters (defensive against bugs)
|
||
|
|
- Easy to add WebSocket support later (Axum has built-in support)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## References
|
||
|
|
|
||
|
|
- [Axum Documentation](https://docs.rs/axum/)
|
||
|
|
- `/crates/vapora-backend/src/main.rs` (router definition)
|
||
|
|
- `/crates/vapora-backend/Cargo.toml` (Axum dependency)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Related ADRs**: ADR-001 (Workspace), ADR-008 (Tokio)
|