Skip to content

Commit 44b8d64

Browse files
authored
Merge pull request #106 from Tuntii/update-docs-v0.1.300-9259717141717722755
Update Cookbook Documentation for v0.1.300
2 parents 6f71402 + 0bd0179 commit 44b8d64

File tree

3 files changed

+94
-15
lines changed

3 files changed

+94
-15
lines changed

docs/cookbook/src/crates/rustapi_extras.md

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ This crate is a collection of production-ready middleware. Everything is behind
1515
| `audit` | `AuditStore`, `AuditLogger` |
1616
| `insight` | `InsightLayer`, `InsightStore` |
1717
| `rate-limit` | `RateLimitLayer` |
18+
| `replay` | `ReplayLayer` (Time-Travel Debugging) |
19+
| `timeout` | `TimeoutLayer` |
20+
| `guard` | `PermissionGuard` |
21+
| `sanitization` | Input sanitization utilities |
1822

1923
## Middleware Usage
2024

@@ -135,7 +139,7 @@ let app = RustApi::new()
135139

136140
### Structured Logging
137141

138-
Emit logs as JSON for aggregators like Datadog or Splunk.
142+
Emit logs as JSON for aggregators like Datadog or Splunk. This is different from request logging; it formats your application logs.
139143

140144
```rust
141145
use rustapi_extras::structured_logging::{StructuredLoggingLayer, JsonFormatter};
@@ -184,6 +188,33 @@ let app = RustApi::new()
184188
.layer(ApiKeyLayer::new("my-secret-key"));
185189
```
186190

191+
### Permission Guards
192+
193+
The `guard` feature provides role-based access control (RBAC) helpers.
194+
195+
```rust
196+
use rustapi_extras::guard::PermissionGuard;
197+
198+
// Only allows users with "admin" role
199+
#[rustapi_rs::get("/admin")]
200+
async fn admin_panel(
201+
_guard: PermissionGuard
202+
) -> &'static str {
203+
"Welcome Admin"
204+
}
205+
```
206+
207+
### Input Sanitization
208+
209+
The `sanitization` feature helps prevent XSS by cleaning user input.
210+
211+
```rust
212+
use rustapi_extras::sanitization::sanitize_html;
213+
214+
let safe_html = sanitize_html("<script>alert(1)</script>Hello");
215+
// Result: "&lt;script&gt;alert(1)&lt;/script&gt;Hello"
216+
```
217+
187218
## Resilience
188219

189220
### Circuit Breaker
@@ -208,6 +239,18 @@ let app = RustApi::new()
208239
.layer(RetryLayer::default());
209240
```
210241

242+
### Timeout
243+
244+
Ensure requests don't hang indefinitely.
245+
246+
```rust
247+
use rustapi_extras::timeout::TimeoutLayer;
248+
use std::time::Duration;
249+
250+
let app = RustApi::new()
251+
.layer(TimeoutLayer::new(Duration::from_secs(30)));
252+
```
253+
211254
## Optimization
212255

213256
### Caching
@@ -231,3 +274,21 @@ use rustapi_extras::dedup::DedupLayer;
231274
let app = RustApi::new()
232275
.layer(DedupLayer::new());
233276
```
277+
278+
## Debugging
279+
280+
### Time-Travel Debugging (Replay)
281+
282+
The `replay` feature allows you to record production traffic and replay it locally for debugging.
283+
284+
See the [Time-Travel Debugging Recipe](../recipes/replay.md) for full details.
285+
286+
```rust
287+
use rustapi_extras::replay::{ReplayLayer, ReplayConfig, InMemoryReplayStore};
288+
289+
let replay_config = ReplayConfig::default();
290+
let store = InMemoryReplayStore::new(1_000);
291+
292+
let app = RustApi::new()
293+
.layer(ReplayLayer::new(replay_config).with_store(store));
294+
```

docs/cookbook/src/crates/rustapi_jobs.md

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,36 @@ Long-running tasks shouldn't block HTTP requests. `rustapi-jobs` provides a robu
1111

1212
Here is how to set up a simple background job queue using the in-memory backend.
1313

14-
### 1. Define the Job
14+
### 1. Define the Job and Data
1515

16-
Jobs are simple structs that implement `Serialize` and `Deserialize`.
16+
Jobs are separated into two parts:
17+
1. The **Data** struct (the payload), which must be serializable.
18+
2. The **Job** struct (the handler), which contains the logic.
1719

1820
```rust
1921
use serde::{Deserialize, Serialize};
2022
use rustapi_jobs::{Job, JobContext, Result};
21-
use std::sync::Arc;
23+
use async_trait::async_trait;
2224

25+
// 1. The payload data
2326
#[derive(Serialize, Deserialize, Debug, Clone)]
24-
struct EmailJob {
27+
struct EmailJobData {
2528
to: String,
2629
subject: String,
2730
body: String,
2831
}
2932

30-
// Implement the Job trait to define how to process it
31-
#[async_trait::async_trait]
33+
// 2. The handler struct (usually stateless)
34+
#[derive(Clone)]
35+
struct EmailJob;
36+
37+
#[async_trait]
3238
impl Job for EmailJob {
3339
const NAME: &'static str = "email_job";
40+
type Data = EmailJobData;
3441

35-
async fn run(&self, _ctx: JobContext) -> Result<()> {
36-
println!("Sending email to {} with subject: {}", self.to, self.subject);
42+
async fn execute(&self, _ctx: JobContext, data: Self::Data) -> Result<()> {
43+
println!("Sending email to {} with subject: {}", data.to, data.subject);
3744
// Simulate work
3845
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
3946
Ok(())
@@ -46,7 +53,7 @@ impl Job for EmailJob {
4653
In your `main` function, initialize the queue and start the worker.
4754

4855
```rust
49-
use rustapi_jobs::{JobQueue, InMemoryBackend, EnqueueOptions};
56+
use rustapi_jobs::{JobQueue, InMemoryBackend};
5057

5158
#[tokio::main]
5259
async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -56,17 +63,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5663
// 2. Create the queue
5764
let queue = JobQueue::new(backend);
5865

59-
// 3. Register the job type
60-
queue.register_job::<EmailJob>();
66+
// 3. Register the job handler
67+
queue.register_job(EmailJob).await;
6168

6269
// 4. Start the worker in the background
6370
let worker_queue = queue.clone();
6471
tokio::spawn(async move {
65-
worker_queue.start_workers().await;
72+
if let Err(e) = worker_queue.start_worker().await {
73+
eprintln!("Worker failed: {:?}", e);
74+
}
6675
});
6776

68-
// 5. Enqueue a job
69-
queue.enqueue(EmailJob {
77+
// 5. Enqueue a job (pass the DATA, not the handler)
78+
queue.enqueue::<EmailJob>(EmailJobData {
7079
to: "user@example.com".into(),
7180
subject: "Welcome!".into(),
7281
body: "Thanks for joining.".into(),

docs/cookbook/src/crates/rustapi_testing.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77
1. **In-process API testing**: Testing your endpoints without binding to a real TCP port.
88
2. **External service mocking**: Mocking downstream services (like payment gateways or auth providers) that your API calls.
99

10+
## Installation
11+
12+
Add the crate to your `dev-dependencies`:
13+
14+
```toml
15+
[dev-dependencies]
16+
rustapi-testing = { version = "0.1.300" }
17+
```
18+
1019
## The `TestClient`
1120

1221
Integration testing is often slow and painful because it involves spinning up a server, waiting for ports, and managing child processes. `TestClient` solves this by wrapping your `RustApi` application and executing requests directly against the service layer.

0 commit comments

Comments
 (0)