This commit is contained in:
dal 2025-02-13 15:05:10 -07:00
parent 2d47c2c539
commit 977b5eb6de
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
2 changed files with 270 additions and 0 deletions

View File

@ -2,3 +2,142 @@
description: These are global rules and recommendations for the rust server.
globs:
---
# Global Rules and Project Structure
## Project Overview
This is a Rust web server project built with Axum, focusing on high performance, safety, and maintainability.
## Project Structure
- `src/`
- `routes/`
- `rest/` - REST API endpoints using Axum
- `routes/` - Individual route modules
- `ws/` - WebSocket handlers and related functionality
- `database/` - Database models, schema, and connection management
- `main.rs` - Application entry point and server setup
## Database Connectivity
- The primary database connection is managed through `get_pg_pool()`, which returns a lazy static `PgPool`
- Always use this pool for database connections to ensure proper connection management
- Example usage:
```rust
let mut conn = get_pg_pool().get().await?;
```
## Code Style and Best Practices
### References and Memory Management
- Prefer references over owned values when possible
- Avoid unnecessary `.clone()` calls
- Use `&str` instead of `String` for function parameters when the string doesn't need to be owned
### Database Operations
- Use Diesel for database migrations and query building
- Migrations are stored in the `migrations/` directory
- Always use transactions for operations that modify multiple tables:
```rust
conn.transaction(|conn| {
// Your database operations here
Ok(())
})
```
### Concurrency Guidelines
- Prioritize concurrent operations, especially for:
- API requests
- Database transactions
- File operations
- Optimize database connection usage:
- Batch operations where possible
- Build queries/parameters before executing database operations
- Use bulk inserts/updates instead of individual operations
```rust
// Preferred: Bulk operation
let items: Vec<_> = prepare_items();
diesel::insert_into(table)
.values(&items)
.execute(conn)?;
// Avoid: Individual operations in a loop
for item in items {
diesel::insert_into(table)
.values(&item)
.execute(conn)?;
}
```
### Error Handling
- Never use `.unwrap()` or `.expect()` in production code
- Always handle errors appropriately using:
- The `?` operator for error propagation
- `match` statements when specific error cases need different handling
- Use `anyhow` for error handling:
- Prefer `anyhow::Result<T>` as the return type for functions that can fail
- Use `anyhow::Error` for error types
- Use `anyhow!` macro for creating custom errors
```rust
use anyhow::{Result, anyhow};
// Example of proper error handling
pub async fn process_data(input: &str) -> Result<Data> {
// Use ? for error propagation
let parsed = parse_input(input)?;
// Use match when specific error cases need different handling
match validate_data(&parsed) {
Ok(valid_data) => Ok(valid_data),
Err(e) => Err(anyhow!("Data validation failed: {}", e))
}
}
// Avoid this:
// let data = parse_input(input).unwrap(); // ❌ Never use unwrap
```
### API Design
- REST endpoints should be in `routes/rest/routes/`
- WebSocket handlers should be in `routes/ws/`
- Use proper HTTP status codes
- Implement proper validation for incoming requests
### Testing
- Write unit tests for critical functionality
- Use integration tests for API endpoints
- Mock external dependencies when appropriate
## Common Patterns
### Database Queries
```rust
use diesel::prelude::*;
// Example of a typical database query
pub async fn get_item(id: i32) -> Result<Item> {
let pool = get_pg_pool();
let conn = pool.get().await?;
items::table
.filter(items::id.eq(id))
.first(&conn)
.map_err(Into::into)
}
```
### Concurrent Operations
```rust
use futures::future::try_join_all;
// Example of concurrent processing
let futures: Vec<_> = items
.into_iter()
.map(|item| process_item(item))
.collect();
let results = try_join_all(futures).await?;
```
Remember to always consider:
1. Connection pool limits when designing concurrent operations
2. Transaction boundaries for data consistency
3. Error propagation and cleanup
4. Memory usage and ownership

131
api/.cursor/rules/libs.mdc Normal file
View File

@ -0,0 +1,131 @@
---
description: This is helpful for building libs for our web server to interact with.
globs: libs/*
---
# Library Construction Guide
## Directory Structure
```
libs/
├── my_lib/
│ ├── Cargo.toml # Library-specific manifest
│ ├── src/
│ │ ├── lib.rs # Library root
│ │ ├── models/ # Data structures and types
│ │ ├── utils/ # Utility functions
│ │ └── errors.rs # Custom error types
│ └── tests/ # Integration tests
```
## Cargo.toml Template
```toml
[package]
name = "my_lib"
version = "0.1.0"
edition.workspace = true
authors.workspace = true
license.workspace = true
# Inherit workspace dependencies
# This ensures consistent versions across the project
[dependencies]
serde.workspace = true # If defined in workspace
tokio.workspace = true # If defined in workspace
thiserror.workspace = true # If defined in workspace
# Library-specific dependencies (not in workspace)
some-specific-dep = "1.0"
# Development dependencies
[dev-dependencies]
tokio-test.workspace = true # If defined in workspace
assert_matches.workspace = true # If defined in workspace
# Feature flags - can inherit from workspace or be lib-specific
[features]
default = []
async = ["tokio"] # Example of a library-specific feature
```
## Best Practices
### 1. Workspace Integration
- Use `.workspace = true` for common fields and dependencies
- Only specify library-specific versions for unique dependencies
- Inherit common development dependencies from workspace
- Keep feature flags modular and specific to the library's needs
### 2. Library Structure
- Keep the library focused on a single responsibility
- Use clear module hierarchies
- Export public API through `lib.rs`
- Follow the workspace's common patterns
Example `lib.rs`:
```rust
//! My Library documentation
//!
//! This library provides...
// Re-export common workspace types if needed
pub use common_types::{Result, Error};
pub mod models;
pub mod utils;
mod errors;
// Re-exports
pub use errors::Error;
pub use models::{ImportantType, AnotherType};
```
### 3. Error Handling
- Use the workspace's common error types where appropriate
- Define library-specific errors only when needed
- Implement conversions to/from workspace error types
Example `errors.rs`:
```rust
use thiserror::Error;
use common_types::Error as WorkspaceError;
#[derive(Error, Debug)]
pub enum Error {
#[error("library specific error: {0}")]
LibrarySpecific(String),
#[error(transparent)]
Workspace(#[from] WorkspaceError),
}
```
### 4. Testing
- Follow workspace testing conventions
- Use shared test utilities from workspace when available
- Keep library-specific test helpers in the library
- Use workspace-defined test macros if available
### 5. Documentation
- Follow workspace documentation style
- Link to related workspace documentation
- Document workspace integration points
- Include examples showing workspace type usage
### 6. Integration Points
- Define clear boundaries with other workspace crates
- Use workspace traits and interfaces
- Share common utilities through workspace-level crates
- Consider cross-crate testing
### 7. Development Workflow
- Run workspace-level tests when making changes
- Update workspace documentation if needed
- Follow workspace versioning strategy
- Use workspace-level CI/CD pipelines
### 8. Dependencies
- Prefer workspace-level dependencies
- Only add library-specific dependencies when necessary
- Keep dependencies minimal and focused
- Document any deviations from workspace versions