
M12 Lifecycle
Choose RAII, pooling, lazy init, and guard patterns before implementing Rust resource ownership and cleanup.
Overview
m12-lifecycle is an agent skill for the Build phase that guides Rust resource lifecycle design—RAII, pooling, lazy init, and scoped cleanup—before you implement Drop and ownership.
Install
npx skills add https://github.com/actionbook/rust-skills --skill m12-lifecycleWhat is this skill?
- Maps five lifecycle patterns (RAII, lazy init, pool, guard, scope) to concrete Rust implementations
- Three-prompt checklist: resource cost, scope (function, request, app-wide), and error-time cleanup
- Covers Drop, OnceLock/LazyLock, r2d2/deadpool pools, MutexGuard guards, and transaction-boundary structs
- Layer-2 design framing: answer when to create, use, and clean up before writing implementation
- Bilingual keyword coverage for RAII, connection pools, and lazy initialization discovery
- Five lifecycle patterns mapped in the design table (RAII, lazy init, pool, guard, scope)
- Three thinking prompts for cost, scope, and error cleanup
Adoption & trust: 924 installs on skills.sh; 1.2k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are adding connections, locks, or globals in Rust but have not decided scope, ownership, or what must still run when operations fail.
Who is it for?
Solo builders implementing Rust HTTP services, workers, or CLIs where pools, sessions, or lazy globals need explicit cleanup rules.
Skip if: Teams that only need syntax help for Drop without design tradeoffs, or non-Rust stacks where RAII patterns do not apply.
When should I use this skill?
Designing resource lifecycles in Rust—RAII, Drop, pools, lazy init, guards, or cleanup on error.
What do I get? / Deliverables
You pick a documented lifecycle pattern and implementation path (Drop, pool, lazy cell, or guard) aligned to cost, scope, and error cleanup requirements.
- Chosen lifecycle pattern and implementation approach documented for the agent
- Scoped ownership and cleanup rules aligned to errors and resource cost
Recommended Skills
Journey fit
Resource lifecycle design sits in Build because it shapes how backends hold connections, locks, and scoped work before code ships. Backend subphase matches connection pools, transactions, Drop-based cleanup, and service-scoped resources in Rust services.
How it compares
Design-time lifecycle checklist for Rust backends, not a generic debugging or code-review skill.
Common Questions / FAQ
Who is m12-lifecycle for?
Indie and solo developers building Rust backends who want agent guidance on RAII, pools, and cleanup before writing structs and Drop implementations.
When should I use m12-lifecycle?
Use during Build/backend work when designing connection pools, lazy singletons, request-scoped guards, or transaction boundaries—and when errors must still trigger cleanup.
Is m12-lifecycle safe to install?
It is procedural design documentation without shell or network hooks; review the Security Audits panel on this Prism page before installing any skill from the repo.
SKILL.md
READMESKILL.md - M12 Lifecycle
# Resource Lifecycle > **Layer 2: Design Choices** ## Core Question **When should this resource be created, used, and cleaned up?** Before implementing lifecycle: - What's the resource's scope? - Who owns the cleanup responsibility? - What happens on error? --- ## Lifecycle Pattern → Implementation | Pattern | When | Implementation | |---------|------|----------------| | RAII | Auto cleanup | `Drop` trait | | Lazy init | Deferred creation | `OnceLock`, `LazyLock` | | Pool | Reuse expensive resources | `r2d2`, `deadpool` | | Guard | Scoped access | `MutexGuard` pattern | | Scope | Transaction boundary | Custom struct + Drop | --- ## Thinking Prompt Before designing lifecycle: 1. **What's the resource cost?** - Cheap → create per use - Expensive → pool or cache - Global → lazy singleton 2. **What's the scope?** - Function-local → stack allocation - Request-scoped → passed or extracted - Application-wide → static or Arc 3. **What about errors?** - Cleanup must happen → Drop - Cleanup is optional → explicit close - Cleanup can fail → Result from close --- ## Trace Up ↑ To domain constraints (Layer 3): ``` "How should I manage database connections?" ↑ Ask: What's the connection cost? ↑ Check: domain-* (latency requirements) ↑ Check: Infrastructure (connection limits) ``` | Question | Trace To | Ask | |----------|----------|-----| | Connection pooling | domain-* | What's acceptable latency? | | Resource limits | domain-* | What are infra constraints? | | Transaction scope | domain-* | What must be atomic? | --- ## Trace Down ↓ To implementation (Layer 1): ``` "Need automatic cleanup" ↓ m02-resource: Implement Drop ↓ m01-ownership: Clear owner for cleanup "Need lazy initialization" ↓ m03-mutability: OnceLock for thread-safe ↓ m07-concurrency: LazyLock for sync "Need connection pool" ↓ m07-concurrency: Thread-safe pool ↓ m02-resource: Arc for sharing ``` --- ## Quick Reference | Pattern | Type | Use Case | |---------|------|----------| | RAII | `Drop` trait | Auto cleanup on scope exit | | Lazy Init | `OnceLock`, `LazyLock` | Deferred initialization | | Pool | `r2d2`, `deadpool` | Connection reuse | | Guard | `MutexGuard` | Scoped lock release | | Scope | Custom struct | Transaction boundaries | ## Lifecycle Events | Event | Rust Mechanism | |-------|----------------| | Creation | `new()`, `Default` | | Lazy Init | `OnceLock::get_or_init` | | Usage | `&self`, `&mut self` | | Cleanup | `Drop::drop()` | ## Pattern Templates ### RAII Guard ```rust struct FileGuard { path: PathBuf, _handle: File, } impl Drop for FileGuard { fn drop(&mut self) { // Cleanup: remove temp file let _ = std::fs::remove_file(&self.path); } } ``` ### Lazy Singleton ```rust use std::sync::OnceLock; static CONFIG: OnceLock<Config> = OnceLock::new(); fn get_config() -> &'static Config { CONFIG.get_or_init(|| { Config::load().expect("config required") }) } ``` --- ## Common Errors | Error | Cause | Fix | |-------|-------|-----| | Resource leak | Forgot Drop | Implement Drop or RAII wrapper | | Double free | Manual memory | Let Rust handle | | Use after drop | Dangling reference | Check lifetimes | | E0509 move out of Drop | Moving owned field | `Option::take()` | | Pool exhaustion | Not returned | Ensure Drop returns | --- ## Anti-Patterns | Anti-Pattern | Why Bad | Better | |--------------|---------|--------| | Manual cleanup | Easy to forget | RAII/Drop | | `lazy_static!` | External dep | `std::syn