# Complete System Example - Macro-Based Version
This example demonstrates a realistic web application backend error system using **waddling-errors-macros** for concise, maintainable error definitions.
## 🎯 Key Pattern: Runtime vs Doc-Gen Separation
This example demonstrates the **correct pattern** for separating runtime code from documentation generation:
```
┌─────────────────────────────────────────────────────────────────┐
│ SAME SOURCE CODE → TWO DIFFERENT BINARIES │
├─────────────────────────────────────────────────────────────────┤
│ │
│ cargo run --features metadata,auto-register │
│ ↓ │
│ ┌──────────────────────────────────────┐ │
│ │ RUNTIME BINARY │ │
│ │ • Error codes available │ │
│ │ • NO doc-gen code compiled │ │
│ │ • Smaller binary size │ │
│ │ • Zero doc-gen overhead │ │
│ └──────────────────────────────────────┘ │
│ │
│ cargo run --features metadata,auto-register,doc-gen │
│ ↓ -- --generate-docs │
│ ┌──────────────────────────────────────┐ │
│ │ DOC-GEN BINARY │ │
│ │ • Error codes available │ │
│ │ • Doc-gen code INCLUDED │ │
│ │ • HtmlRenderer, JsonRenderer linked │ │
│ │ • Generates HTML/JSON documentation │ │
│ └──────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### Why This Pattern?
| Production binary size | Doc-gen code not compiled without feature |
| Runtime performance | Zero overhead - unused code isn't there |
| CI/CD flexibility | Generate docs only when needed |
| Developer experience | Same codebase, different outputs |
## Running the Example
### Normal Runtime (no documentation)
```bash
cargo run --example complete_macro_system --features metadata,auto-register
```
This shows:
- Error codes being used at runtime
- Actual hash values and messages
- System statistics
### Documentation Generation
```bash
cargo run --example complete_macro_system \
--features metadata,auto-register,doc-gen -- --generate-docs
```
This generates:
- `target/doc/WebApp_Backend_(Macros)-pub.html` - Public documentation
- `target/doc/WebApp_Backend_(Macros)-dev.html` - Developer documentation
- `target/doc/WebApp_Backend_(Macros)-int.html` - Internal documentation
- JSON versions for programmatic access
## How It Works
### 1. Feature-Gated Compilation
```rust
// In main.rs
fn main() {
if args.contains("--generate-docs") {
#[cfg(feature = "doc-gen")]
{
generate_documentation(); // Only compiled with doc-gen feature
return;
}
#[cfg(not(feature = "doc-gen"))]
{
eprintln!("Error: doc-gen feature not enabled");
}
}
// Normal runtime - always compiled
run_application();
}
#[cfg(feature = "doc-gen")] // Only exists in doc-gen binary
fn generate_documentation() {
use waddling_errors::doc_generator::{DocRegistry, HtmlRenderer};
// ... generate docs
}
```
### 2. Auto-Registration via `<formats>`
```rust
diag! {
<json, html>, // ← This enables auto-registration!
E.Auth.Token.MISSING: {
message: "JWT token missing",
// ...
},
}
```
The `<json, html>` syntax causes the macro to generate `#[ctor]` code that runs before `main()`, automatically registering all diagnostics.
### 3. Using Error Codes at Runtime
```rust
// Import the generated constants
use components::auth::E_AUTH_TOKEN_MISSING;
// Use them in your code
fn check_auth(request: &Request) -> Result<(), Error> {
let token = request.header("Authorization")
.ok_or_else(|| Error::new(
E_AUTH_TOKEN_MISSING.code, // "E.Auth.Token.MISSING"
E_AUTH_TOKEN_MISSING.hash, // "V6a0B"
E_AUTH_TOKEN_MISSING.message, // "JWT token missing..."
))?;
// ...
}
```
## CI/CD Integration
### GitHub Actions
```yaml
jobs:
build:
steps:
- name: Build (production)
run: cargo build --release --features metadata,auto-register
- name: Generate Docs
run: cargo run --features metadata,auto-register,doc-gen -- --generate-docs
- name: Deploy Docs
uses: peaceiris/actions-gh-pages@v3
with:
publish_dir: ./target/doc
```
### GitLab CI
```yaml
build:
script:
- cargo build --release --features metadata,auto-register
generate-docs:
script:
- cargo run --features metadata,auto-register,doc-gen -- --generate-docs
artifacts:
paths:
- target/doc/
```
## Project Structure
```
complete_macro_system/
├── main.rs # Entry point with runtime/doc-gen separation
├── sequences.rs # Sequence conventions (001=MISSING, etc.)
├── primaries/
│ └── mod.rs # primary! macro definitions
└── components/
├── mod.rs # Module organization
├── auth.rs # component! + diag! for AUTH
├── database.rs # component! + diag! for DB
├── api.rs # component! + diag! for API
├── cache.rs # component! + diag! for CACHE
├── queue.rs # component! + diag! for QUEUE
├── storage.rs # component! + diag! for STORAGE
└── navigation.rs # component! + diag! for NAVIGATION
```
## Components Overview
| **Auth** | JWT, OAuth2, RBAC | `E.Auth.Token.MISSING`, `E.Auth.Permission.DENIED` |
| **Db** | PostgreSQL operations | `C.Db.Connection.EXHAUSTED`, `C.Db.Data.CORRUPTED` |
| **Api** | External integrations | `B.Api.RateLimit.EXCEEDED`, `E.Api.Timeout.EXCEEDED` |
| **Cache** | Redis caching | `S.Cache.Data.WARMED`, `W.Cache.Data.STALE` |
| **Queue** | Background jobs | `K.Queue.Data.COMPLETED`, `E.Queue.Timeout.CANCELLED` |
| **Storage** | S3-compatible storage | `K.Storage.Data.UPLOADED`, `C.Storage.Data.CORRUPTED` |
| **Navigation** | Routing & pages | `E.Navigation.Page.NOT_FOUND` (the famous 404!) |
## Macro Syntax Quick Reference
### component! macro
```rust
component! {
ComponentName {
docs: "Description", // Documentation
examples: ["E.COMP..."], // Example error codes
tags: ["tag1", "tag2"], // Searchable tags
},
}
```
### primary! macro
```rust
primary! {
PrimaryName {
docs: "Description",
examples: ["example1"],
related: ["Other"],
},
}
```
### diag! macro
```rust
diag! {
<json, html>, // Auto-register for these formats
E.Component.Primary.SEMANTIC: {
message: "Error message template",
'CR 'Pub description: "Public description",
'CR 'Dev hints: ["Developer hints"],
'CR 'Int hints: ["Internal hints"],
'R role: "Public",
'R tags: ["tag1", "tag2"],
'R related_codes: ["E.Other.Code"],
'C deprecated: "2.0.0",
'C see_also: ["E.Replacement.Code"],
},
}
```
## Learn More
- See `waddling-errors/examples/complete_system` for the manual (non-macro) approach
- See `waddling-errors-macros/docs/` for full macro DSL specification
- See main documentation for error code conventions