Skip to content

Commit 2380ab5

Browse files
committed
Add health endpoints, production defaults, perf
Introduce built-in health endpoints and a production baseline preset, plus a synthetic in-process performance snapshot and CI wiring. Changes include: add HealthEndpointConfig, HealthResponse and health helper handlers; RustApi methods to enable health_endpoints(), with_health_check(), and production_defaults()/production_defaults_with_config(); automatically register /health, /ready and /live when configured; tests for health endpoints; a new perf_snapshot example and CI step to run and upload its output; README, CHANGELOG and RELEASES updates to document production defaults and benchmark guidance; new .env for local examples; API exports extended (oauth2/session/job/session stores and helpers); new session module and multiple cookbook/docs/recipes additions; and Cargo.lock updates for new dependencies. Overall this adds production probe ergonomics and a reproducible perf snapshot to the project.
1 parent d7f8877 commit 2380ab5

49 files changed

Lines changed: 5553 additions & 115 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Placeholder environment variables for local documentation/examples
2+
# Replace with real values before running database-backed samples.
3+
DATABASE_URL=postgres://postgres:postgres@localhost:5432/rustapi_dev
4+
REDIS_URL=redis://127.0.0.1:6379
5+
OAUTH_CLIENT_ID=replace-me
6+
OAUTH_CLIENT_SECRET=replace-me
7+
OAUTH_REDIRECT_URI=http://127.0.0.1:3000/auth/callback
8+
OIDC_ISSUER_URL=https://accounts.google.com

.github/workflows/benchmark.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ jobs:
2828
- name: Run Benchmarks
2929
run: cargo bench --workspace | tee benchmark_results.txt
3030

31+
- name: Run Performance Snapshot
32+
run: cargo run -p rustapi-core --example perf_snapshot --release | tee perf_snapshot.txt
33+
3134
- name: Upload Benchmark Results
3235
uses: actions/upload-artifact@v4
3336
with:
3437
name: benchmark-results
35-
path: benchmark_results.txt
38+
path: |
39+
benchmark_results.txt
40+
perf_snapshot.txt

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ assets/b9c93c1cd427d8f50e68dbd11ed2b000.jpg
1212

1313
docs/cookbook/book/
1414
build_rs_cov.profraw
15+
answer.md
16+
docs/PRODUCTION_BASELINE.md
17+
docs/PRODUCTION_CHECKLIST.md
18+
/.github/instructions
19+
/.github/prompts
20+
/.github/skills

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
140140

141141
This release delivers a **12x performance improvement**, bringing RustAPI from ~8K req/s to **~92K req/s**.
142142

143+
> Note: the numbers below are preserved as a **historical release snapshot**. Current benchmark methodology and canonical public performance claims are maintained in `docs/PERFORMANCE_BENCHMARKS.md`.
144+
143145
#### Benchmark Results
144146

145147
| Framework | Requests/sec | Latency (avg) |

Cargo.lock

Lines changed: 35 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ RustAPI ships circuit breaker and retry middleware as first-class features, not
5757
- **Retry** with exponential backoff
5858
- **Rate Limiting** (IP-based, per-route)
5959
- **Body Limit** with configurable max size (default 1 MB)
60+
- **Health Probes** via `.health_endpoints()` for `/health`, `/ready`, and `/live`
6061

6162
### Environment-Aware Error Masking
6263

@@ -121,7 +122,7 @@ Run HTTP/1.1 (TCP) and HTTP/3 (QUIC/UDP) simultaneously on the same server. Enab
121122

122123
| Feature | RustAPI | Actix-web | Axum | FastAPI (Python) |
123124
|:--------|:-------:|:---------:|:----:|:----------------:|
124-
| Performance | ~92k req/s | ~105k | ~100k | ~12k |
125+
| Performance | See benchmark source | Workload-dependent | Workload-dependent | Workload-dependent |
125126
| Ergonomics | High | Low | Medium | High |
126127
| AI/LLM native format (TOON) | Yes | No | No | No |
127128
| Request replay / time-travel debug | Built-in | No | No | 3rd-party |
@@ -132,6 +133,8 @@ Run HTTP/1.1 (TCP) and HTTP/3 (QUIC/UDP) simultaneously on the same server. Enab
132133
| Background jobs | Built-in | 3rd-party | 3rd-party | 3rd-party |
133134
| API stability model | Facade + CI contract | Direct | Direct | Stable |
134135

136+
Current benchmark methodology and canonical published performance claims live in [`docs/PERFORMANCE_BENCHMARKS.md`](docs/PERFORMANCE_BENCHMARKS.md). Historical point-in-time numbers in older release notes should not be treated as the current baseline unless they are linked from that document.
137+
135138
## Quick Start
136139

137140
```rust
@@ -146,13 +149,52 @@ async fn hello(Path(name): Path<String>) -> Json<Message> {
146149
}
147150

148151
#[rustapi_rs::main]
149-
async fn main() {
150-
RustApi::auto().run("127.0.0.1:8080").await
152+
async fn main() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
153+
RustApi::auto().run("127.0.0.1:8080").await
151154
}
152155
```
153156

154157
`RustApi::auto()` collects all macro-annotated handlers, generates OpenAPI documentation (served at `/docs`), and starts a multi-threaded tokio runtime.
155158

159+
For production deployments, you can enable standard probe endpoints without writing handlers manually:
160+
161+
```rust
162+
use rustapi_rs::prelude::*;
163+
164+
#[rustapi_rs::main]
165+
async fn main() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
166+
let health = HealthCheckBuilder::new(true)
167+
.add_check("database", || async { HealthStatus::healthy() })
168+
.build();
169+
170+
RustApi::auto()
171+
.with_health_check(health)
172+
.run("127.0.0.1:8080")
173+
.await
174+
}
175+
```
176+
177+
This registers:
178+
- `/health` — aggregate dependency health
179+
- `/ready` — readiness probe (`503` when dependencies are unhealthy)
180+
- `/live` — lightweight liveness probe
181+
182+
Or use a single production baseline preset:
183+
184+
```rust
185+
use rustapi_rs::prelude::*;
186+
187+
#[rustapi_rs::main]
188+
async fn main() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
189+
RustApi::auto()
190+
.production_defaults("users-api")
191+
.run("127.0.0.1:8080")
192+
.await
193+
}
194+
```
195+
196+
`production_defaults()` enables request IDs, tracing spans, and standard probe endpoints in one call.
197+
156198
You can shorten the macro prefix by renaming the crate:
157199

158200
```toml
@@ -202,6 +244,8 @@ Detailed architecture, recipes, and guides are in the [Cookbook](docs/cookbook/s
202244
- [System Architecture](docs/cookbook/src/architecture/system_overview.md)
203245
- [Performance Benchmarks](docs/cookbook/src/concepts/performance.md)
204246
- [gRPC Integration Guide](docs/cookbook/src/crates/rustapi_grpc.md)
247+
- [Recommended Production Baseline](docs/PRODUCTION_BASELINE.md)
248+
- [Production Checklist](docs/PRODUCTION_CHECKLIST.md)
205249
- [Examples](crates/rustapi-rs/examples/)
206250

207251
---

RELEASES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
**Release Date**: February 26, 2026
44
**Full Changelog**: https://github.com/Tuntii/RustAPI/compare/v0.1.335...v0.1.397
55

6+
**Benchmark Source of Truth**: Current benchmark methodology and canonical performance claims live in `docs/PERFORMANCE_BENCHMARKS.md`. Historical release-specific benchmark notes should be treated as point-in-time snapshots unless they are linked from that document.
7+
68
---
79

810
## 🎯 Highlights

api/public/rustapi-rs.all-features.txt

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub use rustapi_rs::ConfigError
1717
pub use rustapi_rs::Cookies
1818
pub use rustapi_rs::CorsLayer
1919
pub use rustapi_rs::Created
20+
pub use rustapi_rs::CsrfState
2021
pub use rustapi_rs::Environment
2122
pub use rustapi_rs::Extension
2223
pub use rustapi_rs::ExtrasEnvironment
@@ -36,15 +37,27 @@ pub use rustapi_rs::JwtError
3637
pub use rustapi_rs::JwtLayer
3738
pub use rustapi_rs::JwtValidation
3839
pub use rustapi_rs::KeepAlive
40+
pub use rustapi_rs::MemorySessionStore
3941
pub use rustapi_rs::MethodRouter
4042
pub use rustapi_rs::Multipart
4143
pub use rustapi_rs::MultipartConfig
4244
pub use rustapi_rs::MultipartField
4345
pub use rustapi_rs::NoContent
46+
pub use rustapi_rs::OAuth2Client
47+
pub use rustapi_rs::OAuth2Config
48+
pub use rustapi_rs::Job
49+
pub use rustapi_rs::JobBackend
50+
pub use rustapi_rs::JobContext
51+
pub use rustapi_rs::JobError
52+
pub use rustapi_rs::JobQueue
53+
pub use rustapi_rs::JobRequest
54+
pub use rustapi_rs::PkceVerifier
4455
pub use rustapi_rs::Path
56+
pub use rustapi_rs::Provider
4557
pub use rustapi_rs::Query
4658
pub use rustapi_rs::RateLimitLayer
4759
pub use rustapi_rs::Redirect
60+
pub use rustapi_rs::RedisSessionStore
4861
pub use rustapi_rs::Request
4962
pub use rustapi_rs::RequestId
5063
pub use rustapi_rs::RequestIdLayer
@@ -57,6 +70,12 @@ pub use rustapi_rs::RouteMatch
5770
pub use rustapi_rs::Router
5871
pub use rustapi_rs::RustApi
5972
pub use rustapi_rs::RustApiConfig
73+
pub use rustapi_rs::Session
74+
pub use rustapi_rs::SessionConfig
75+
pub use rustapi_rs::SessionError
76+
pub use rustapi_rs::SessionLayer
77+
pub use rustapi_rs::SessionRecord
78+
pub use rustapi_rs::SessionStore
6079
pub use rustapi_rs::SqlxErrorExt
6180
pub use rustapi_rs::Sse
6281
pub use rustapi_rs::SseEvent
@@ -65,6 +84,10 @@ pub use rustapi_rs::StaticFile
6584
pub use rustapi_rs::StaticFileConfig
6685
pub use rustapi_rs::StatusCode
6786
pub use rustapi_rs::StreamBody
87+
pub use rustapi_rs::EnqueueOptions
88+
pub use rustapi_rs::InMemoryBackend
89+
pub use rustapi_rs::TokenError
90+
pub use rustapi_rs::TokenResponse
6891
pub use rustapi_rs::TracingLayer
6992
pub use rustapi_rs::Typed
7093
pub use rustapi_rs::TypedPath
@@ -73,6 +96,8 @@ pub use rustapi_rs::Validatable
7396
pub use rustapi_rs::ValidatedClaims
7497
pub use rustapi_rs::ValidatedJson
7598
pub use rustapi_rs::WithStatus
99+
pub use rustapi_rs::AuthorizationRequest
100+
pub use rustapi_rs::sse_from_iter
76101
pub use rustapi_rs::api_key
77102
pub use rustapi_rs::cache
78103
pub use rustapi_rs::circuit_breaker
@@ -95,6 +120,7 @@ pub use rustapi_rs::load_dotenv
95120
pub use rustapi_rs::load_dotenv_from
96121
pub use rustapi_rs::logging
97122
pub use rustapi_rs::otel
123+
pub use rustapi_rs::oauth2
98124
pub use rustapi_rs::patch
99125
pub use rustapi_rs::patch_route
100126
pub use rustapi_rs::post
@@ -109,6 +135,7 @@ pub use rustapi_rs::route
109135
pub use rustapi_rs::sanitization
110136
pub use rustapi_rs::security_headers
111137
pub use rustapi_rs::serve_dir
138+
pub use rustapi_rs::session
112139
pub use rustapi_rs::sse_response
113140
pub use rustapi_rs::structured_logging
114141
pub use rustapi_rs::timeout
@@ -228,6 +255,16 @@ pub mod rustapi_rs::extras::logging
228255
pub use rustapi_rs::extras::logging::logging
229256
pub mod rustapi_rs::extras::otel
230257
pub use rustapi_rs::extras::otel::otel
258+
pub mod rustapi_rs::extras::oauth2
259+
pub use rustapi_rs::extras::oauth2::AuthorizationRequest
260+
pub use rustapi_rs::extras::oauth2::CsrfState
261+
pub use rustapi_rs::extras::oauth2::OAuth2Client
262+
pub use rustapi_rs::extras::oauth2::OAuth2Config
263+
pub use rustapi_rs::extras::oauth2::PkceVerifier
264+
pub use rustapi_rs::extras::oauth2::Provider
265+
pub use rustapi_rs::extras::oauth2::TokenError
266+
pub use rustapi_rs::extras::oauth2::TokenResponse
267+
pub use rustapi_rs::extras::oauth2::oauth2
231268
pub mod rustapi_rs::extras::rate_limit
232269
pub use rustapi_rs::extras::rate_limit::RateLimitLayer
233270
pub use rustapi_rs::extras::rate_limit::rate_limit
@@ -239,6 +276,16 @@ pub mod rustapi_rs::extras::sanitization
239276
pub use rustapi_rs::extras::sanitization::sanitization
240277
pub mod rustapi_rs::extras::security_headers
241278
pub use rustapi_rs::extras::security_headers::security_headers
279+
pub mod rustapi_rs::extras::session
280+
pub use rustapi_rs::extras::session::MemorySessionStore
281+
pub use rustapi_rs::extras::session::RedisSessionStore
282+
pub use rustapi_rs::extras::session::Session
283+
pub use rustapi_rs::extras::session::SessionConfig
284+
pub use rustapi_rs::extras::session::SessionError
285+
pub use rustapi_rs::extras::session::SessionLayer
286+
pub use rustapi_rs::extras::session::SessionRecord
287+
pub use rustapi_rs::extras::session::SessionStore
288+
pub use rustapi_rs::extras::session::session
242289
pub mod rustapi_rs::extras::sqlx
243290
pub use rustapi_rs::extras::sqlx::SqlxErrorExt
244291
pub use rustapi_rs::extras::sqlx::convert_sqlx_error
@@ -269,6 +316,7 @@ pub use rustapi_rs::prelude::ContextBuilder
269316
pub use rustapi_rs::prelude::Cookies
270317
pub use rustapi_rs::prelude::CorsLayer
271318
pub use rustapi_rs::prelude::Created
319+
pub use rustapi_rs::prelude::CsrfState
272320
pub use rustapi_rs::prelude::Deserialize
273321
pub use rustapi_rs::prelude::Deserialize
274322
pub use rustapi_rs::prelude::Extension
@@ -283,17 +331,23 @@ pub use rustapi_rs::prelude::JwtLayer
283331
pub use rustapi_rs::prelude::JwtValidation
284332
pub use rustapi_rs::prelude::KeepAlive
285333
pub use rustapi_rs::prelude::LlmResponse
334+
pub use rustapi_rs::prelude::MemorySessionStore
286335
pub use rustapi_rs::prelude::Message
287336
pub use rustapi_rs::prelude::Multipart
288337
pub use rustapi_rs::prelude::MultipartConfig
289338
pub use rustapi_rs::prelude::MultipartField
290339
pub use rustapi_rs::prelude::Negotiate
291340
pub use rustapi_rs::prelude::NoContent
341+
pub use rustapi_rs::prelude::OAuth2Client
342+
pub use rustapi_rs::prelude::OAuth2Config
292343
pub use rustapi_rs::prelude::OutputFormat
293344
pub use rustapi_rs::prelude::Path
345+
pub use rustapi_rs::prelude::PkceVerifier
346+
pub use rustapi_rs::prelude::Provider
294347
pub use rustapi_rs::prelude::Query
295348
pub use rustapi_rs::prelude::RateLimitLayer
296349
pub use rustapi_rs::prelude::Redirect
350+
pub use rustapi_rs::prelude::RedisSessionStore
297351
pub use rustapi_rs::prelude::Request
298352
pub use rustapi_rs::prelude::RequestId
299353
pub use rustapi_rs::prelude::RequestIdLayer
@@ -304,6 +358,12 @@ pub use rustapi_rs::prelude::Router
304358
pub use rustapi_rs::prelude::RustApi
305359
pub use rustapi_rs::prelude::RustApiConfig
306360
pub use rustapi_rs::prelude::Schema
361+
pub use rustapi_rs::prelude::Session
362+
pub use rustapi_rs::prelude::SessionConfig
363+
pub use rustapi_rs::prelude::SessionError
364+
pub use rustapi_rs::prelude::SessionLayer
365+
pub use rustapi_rs::prelude::SessionRecord
366+
pub use rustapi_rs::prelude::SessionStore
307367
pub use rustapi_rs::prelude::Serialize
308368
pub use rustapi_rs::prelude::Serialize
309369
pub use rustapi_rs::prelude::SqlxErrorExt
@@ -332,6 +392,9 @@ pub use rustapi_rs::prelude::View
332392
pub use rustapi_rs::prelude::WebSocket
333393
pub use rustapi_rs::prelude::WebSocketStream
334394
pub use rustapi_rs::prelude::WithStatus
395+
pub use rustapi_rs::prelude::AuthorizationRequest
396+
pub use rustapi_rs::prelude::TokenError
397+
pub use rustapi_rs::prelude::TokenResponse
335398
pub use rustapi_rs::prelude::convert_sqlx_error
336399
pub use rustapi_rs::prelude::create_token
337400
pub use rustapi_rs::prelude::debug

api/public/rustapi-rs.default.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub use rustapi_rs::UploadedFile
5555
pub use rustapi_rs::Validatable
5656
pub use rustapi_rs::ValidatedJson
5757
pub use rustapi_rs::WithStatus
58+
pub use rustapi_rs::sse_from_iter
5859
pub use rustapi_rs::collect_auto_routes
5960
pub use rustapi_rs::delete
6061
pub use rustapi_rs::delete_route

0 commit comments

Comments
 (0)