Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/rustapi-extras/src/oauth2/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ mod property_tests {
// Remaining time should be close to expires_in (within a few seconds)
let remaining_secs = remaining.unwrap().as_secs();
prop_assert!(remaining_secs <= expires_in_secs);
prop_assert!(remaining_secs >= expires_in_secs - 2); // Allow 2 sec tolerance
prop_assert!(remaining_secs >= expires_in_secs.saturating_sub(2)); // Allow 2 sec tolerance
}

/// Property 16: Token response builder pattern works correctly
Expand Down
18 changes: 9 additions & 9 deletions docs/GETTING_STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ Add RustAPI to your `Cargo.toml`:

```toml
[dependencies]
rustapi-rs = "0.1.9"
rustapi-rs = "0.1.233"
```

Or with specific features:

```toml
[dependencies]
rustapi-rs = { version = "0.1.9", features = ["jwt", "cors", "toon", "ws", "view"] }
rustapi-rs = { version = "0.1.233", features = ["jwt", "cors", "toon", "ws", "view"] }
```

### Available Features
Expand Down Expand Up @@ -358,7 +358,7 @@ ApiError::internal("message") // 500
### CORS

```toml
rustapi-rs = { version = "0.1.4", features = ["cors"] }
rustapi-rs = { version = "0.1.233", features = ["cors"] }
```

```rust
Expand All @@ -379,7 +379,7 @@ RustApi::new()
### JWT Authentication

```toml
rustapi-rs = { version = "0.1.4", features = ["jwt"] }
rustapi-rs = { version = "0.1.233", features = ["jwt"] }
```

```rust
Expand Down Expand Up @@ -409,7 +409,7 @@ async fn protected(user: AuthUser<Claims>) -> Json<Response> {
### Rate Limiting

```toml
rustapi-rs = { version = "0.1.4", features = ["rate-limit"] }
rustapi-rs = { version = "0.1.233", features = ["rate-limit"] }
```

```rust
Expand All @@ -427,7 +427,7 @@ RustApi::new()
## TOON Format (LLM Optimization)

```toml
rustapi-rs = { version = "0.1.4", features = ["toon"] }
rustapi-rs = { version = "0.1.233", features = ["toon"] }
```

```rust
Expand Down Expand Up @@ -458,7 +458,7 @@ Response includes token counting headers:
Real-time bidirectional communication:

```toml
rustapi-rs = { version = "0.1.4", features = ["ws"] }
rustapi-rs = { version = "0.1.233", features = ["ws"] }
```

```rust
Expand Down Expand Up @@ -495,7 +495,7 @@ websocat ws://localhost:8080/ws
Server-side HTML rendering with Tera:

```toml
rustapi-rs = { version = "0.1.4", features = ["view"] }
rustapi-rs = { version = "0.1.233", features = ["view"] }
```

Create a template file `templates/index.html`:
Expand Down Expand Up @@ -697,7 +697,7 @@ struct AnyBody { ... }
Check that the `swagger-ui` feature is enabled (it's on by default):

```toml
rustapi-rs = { version = "0.1.9", features = ["swagger-ui"] }
rustapi-rs = { version = "0.1.233", features = ["swagger-ui"] }
```

### CLI Commands Not Working
Expand Down
36 changes: 36 additions & 0 deletions docs/cookbook/src/crates/rustapi_extras.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This crate is a collection of production-ready middleware. Everything is behind
| `cors` | `CorsLayer` |
| `csrf` | `CsrfLayer`, `CsrfToken` extractor |
| `audit` | `AuditStore`, `AuditLogger` |
| `insight` | `InsightLayer`, `InsightStore` |
| `rate-limit` | `RateLimitLayer` |

## Middleware Usage
Expand Down Expand Up @@ -82,3 +83,38 @@ async fn delete_user(
}
```

## Traffic Insight

The `insight` feature provides powerful real-time traffic analysis and debugging capabilities without external dependencies. It is designed to be low-overhead and privacy-conscious.

```toml
[dependencies]
rustapi-extras = { version = "0.1", features = ["insight"] }
```

### Setup

```rust
use rustapi_extras::insight::{InsightLayer, InMemoryInsightStore, InsightConfig};
use std::sync::Arc;

let store = Arc::new(InMemoryInsightStore::new());
let config = InsightConfig::default();

let app = RustApi::new()
.layer(InsightLayer::new(config, store.clone()));
```

### Accessing Data

You can inspect the collected data (e.g., via an admin dashboard):

```rust
#[rustapi_rs::get("/admin/insights")]
async fn get_insights(State(store): State<Arc<InMemoryInsightStore>>) -> Json<InsightStats> {
// Returns aggregated stats like req/sec, error rates, p99 latency
Json(store.get_stats().await)
}
```

The `InsightStore` trait allows you to implement custom backends (e.g., ClickHouse or Elasticsearch) if you need long-term retention.
88 changes: 75 additions & 13 deletions docs/cookbook/src/crates/rustapi_jobs.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,87 @@

## Background Processing

Long-running tasks shouldn't block HTTP requests. `rustapi-jobs` provides a robust queue system.
Long-running tasks shouldn't block HTTP requests. `rustapi-jobs` provides a robust queue system that can run in-memory or be backed by Redis/Postgres.

## Usage Example

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

### 1. Define the Job

Jobs are simple structs that implement `Serialize` and `Deserialize`.
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The text suggests a job is just a serializable struct, but in rustapi-jobs the Job trait is implemented by a handler type with an associated Data payload type (the payload is what needs Serialize/Deserialize). Update this description to match the actual API so readers don’t model jobs incorrectly.

Copilot uses AI. Check for mistakes.

```rust
use serde::{Deserialize, Serialize};
use rustapi_jobs::{Job, JobContext, Result};
use std::sync::Arc;

#[derive(Serialize, Deserialize, Debug, Clone)]
struct EmailJob {
to: String,
subject: String,
body: String,
}

// Implement the Job trait to define how to process it
#[async_trait::async_trait]
impl Job for EmailJob {
const NAME: &'static str = "email_job";

async fn run(&self, _ctx: JobContext) -> Result<()> {
println!("Sending email to {} with subject: {}", self.to, self.subject);
// Simulate work
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
Ok(())
}
}
```

### 2. Configure the Queue

In your `main` function, initialize the queue and start the worker.

```rust
// Define a job
#[derive(Serialize, Deserialize)]
struct EmailJob { to: String }
use rustapi_jobs::{JobQueue, InMemoryBackend, EnqueueOptions};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. Create the backend
let backend = InMemoryBackend::new();

// 2. Create the queue
let queue = JobQueue::new(backend);

// Enqueue it
queue.push(EmailJob { to: "alice@example.com" }).await;
// 3. Register the job type
queue.register_job::<EmailJob>();

// 4. Start the worker in the background
let worker_queue = queue.clone();
tokio::spawn(async move {
worker_queue.start_workers().await;
});

// 5. Enqueue a job
queue.enqueue(EmailJob {
to: "user@example.com".into(),
subject: "Welcome!".into(),
body: "Thanks for joining.".into(),
}).await?;
Comment on lines +68 to +73
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JobQueue::enqueue takes the job’s Data payload and is generic over the job type (e.g., enqueue::<EmailJob>(data)), returning a job id String. Enqueuing the handler struct (queue.enqueue(EmailJob { ... })) doesn’t match the actual API in crates/rustapi-jobs/src/queue.rs and won’t compile.

Copilot uses AI. Check for mistakes.

Ok(())
}
```

## Backends

- **Memory**: Great for development and testing.
- **Redis**: High throughput persistence.
- **Postgres**: Transactional reliability (acid).
- **Memory**: Great for development and testing. Zero infrastructure required.
- **Redis**: High throughput persistence. Recommended for production.
- **Postgres**: Transactional reliability (ACID). Best if you cannot lose jobs.

## Reliability Features

## Reliability
The worker system includes built-in reliability features:

The worker system features:
- **Exponential Backoff**: Automatic retries for failing jobs.
- **Dead Letter Queue**: Poison jobs are isolated for manual inspection.
- **Exponential Backoff**: Automatically retries failing jobs with increasing delays.
- **Dead Letter Queue (DLQ)**: "Poison" jobs that fail repeatedly are isolated for manual inspection.
- **Concurrency Control**: Limit the number of concurrent workers to prevent overloading your system.
Comment on lines +89 to +91
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs claim built-in DLQ and concurrency controls, but rustapi-jobs currently only implements retries with exponential backoff; DLQ is explicitly marked TODO in crates/rustapi-jobs/src/queue.rs, and there is no concurrency configuration in the crate. Please adjust this section to reflect the current behavior (or clearly mark DLQ/concurrency as planned/future work).

Copilot uses AI. Check for mistakes.
15 changes: 15 additions & 0 deletions docs/cookbook/src/getting_started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@ Verify your installation:
cargo-rustapi --version
```

## Adding to an Existing Project

If you prefer not to use the CLI, you can add RustAPI to your `Cargo.toml` manually:

```bash
cargo add rustapi-rs@0.1.233
```
Comment on lines +28 to +34
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new section pins rustapi-rs to 0.1.233, but the earlier CLI install command in this same doc installs whatever the latest cargo-rustapi is. To keep the installation guide consistent with the “match workspace version” goal, consider pinning cargo install cargo-rustapi --version 0.1.233 (or explicitly note the recommended compatible CLI version).

Copilot uses AI. Check for mistakes.

Or add this to your `Cargo.toml`:

```toml
[dependencies]
rustapi-rs = "0.1.233"
```

## Editor Setup

For the best experience, we recommend **VS Code** with the **rust-analyzer** extension. This provides:
Expand Down
10 changes: 10 additions & 0 deletions docs/cookbook/src/learning/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ We maintain a comprehensive examples repository with **18 real-world projects**

🔗 **[rustapi-rs-examples](https://github.com/Tuntii/rustapi-rs-examples)** - Complete examples from hello-world to production microservices

### Cookbook Internal Path

If you prefer reading through documentation first, follow this path through the cookbook:

1. **Foundations**: Start with [Handlers & Extractors](../concepts/handlers.md) and [System Overview](../architecture/system_overview.md).
2. **Core Crates**: Read about [rustapi-core](../crates/rustapi_core.md) and [rustapi-macros](../crates/rustapi_macros.md).
3. **Building Blocks**: Try the [Creating Resources](../recipes/crud_resource.md) recipe.
4. **Security**: Implement [JWT Authentication](../recipes/jwt_auth.md) and [CSRF Protection](../recipes/csrf_protection.md).
5. **Advanced**: Explore [Performance Tuning](../recipes/high_performance.md) and [HTTP/3](../recipes/http3_quic.md).

### Why Use the Examples Repository?

| Benefit | Description |
Expand Down
Loading