Reorganize project structure to improve maintainability and add comprehensive testing documentation and tooling support.
14 KiB
Claude Code Style Guide for MinIO Rust SDK
- Only provide actionable feedback.
- Exclude code style comments on generated files. These will have a header signifying that.
- Use github markdown folded sections for all items.
- Do not use emojis.
- Do not add a "feel good" section.
CRITICAL: Benchmark and Performance Data
NEVER fabricate, estimate, or make up benchmark results. EVER.
Rules:
- ONLY report actual measured data from running benchmarks with real code
- If you have NOT run a benchmark, explicitly state: "NO BENCHMARK RUN - THEORETICAL PROJECTION ONLY"
- Clearly distinguish between:
- Measured: Real data from
cargo benchor timing measurements - Projected: Theoretical calculations based on assumptions (MUST be labeled as such)
- Measured: Real data from
- If benchmarking is not possible (e.g., requires live S3), state that explicitly
- Never present theoretical speedups as if they were real measurements
- When in doubt, do NOT include performance numbers
Violation of this rule is lying and completely unacceptable.
Copyright Header
All source files that haven't been generated MUST include the following copyright header:
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
// Copyright 20?? MinIO, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Code Style Guidelines
Ignore files
- Ignore files from processing mentioned under '.gitignore'
Comments
- NO redundant comments - Code should be self-documenting
- Avoid obvious comments like
// Set x to 5forlet x = 5; - Only add comments when they explain WHY, not WHAT
- Document complex algorithms or non-obvious business logic
Critical Code Patterns
Builder Pattern
All S3 API requests MUST use the builder pattern, with documentation similar to the following example (adapted for each specific API)
/// Argument builder for the [`AppendObject`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-objects-append.html) S3 API operation.
///
/// This struct constructs the parameters required for the [`Client::append_object`](crate::s3::client::Client::append_object) method.
Key Requirements:
- The aws docs url must exist.
Error Handling Pattern
All Rust SDK methods should follow consistent error handling patterns:
impl Client {
pub async fn operation_name(&self, args: &OperationArgs) -> Result<OperationResponse, Error> {
// Validate inputs early
args.validate()?;
// Build request
let request = self.build_request(args)?;
// Execute with proper error propagation
let response = self.execute(request).await?;
// Parse and return
OperationResponse::from_response(response)
}
}
Rust-Specific Best Practices
-
Ownership and Borrowing
- Prefer
&strover&Stringin function parameters - Use
AsRef<str>orInto<String>for flexible string parameters - Return owned types from functions unless lifetime annotations are clear
- Prefer
-
Type Safety
- Use
#[must_use]attribute for functions returning important values - Prefer strong typing over primitive obsession
- Use newtypes for domain-specific values
- Use
-
Unsafe Code
- Avoid
unsafecode unless absolutely necessary - Document all safety invariants when
unsafeis required - Isolate
unsafeblocks and keep them minimal
- Avoid
-
Performance
- Use
Cow<'_, str>to avoid unnecessary allocations - Prefer iterators over collecting into intermediate vectors
- Use
Box<dyn Trait>sparingly; prefer generics when possible
- Use
-
Async Patterns
- Use
tokio::select!for concurrent operations - Avoid blocking operations in async contexts
- Use
async-traitfor async trait methods
- Use
Code Quality Principles
Why Code Quality Standards Are Mandatory
Code quality standards are critical business requirements for MinIO Rust SDK:
- Enterprise Data Safety: A single bug can corrupt terabytes of customer data across distributed systems
- Code Efficiency: MinIO Rust SDK code must be efficient and performant
- Scalability: MinIO Rust SDK must be able to handle thousands of concurrent requests
- High Availability: Systems must handle failures gracefully - unpredictable code creates cascading failures
- Developer Velocity: New team members must understand complex distributed systems quickly and safely
Predictable Code Requirements
Code must exhibit deterministic behavior to ensure system reliability:
- Managed State: Use Arc<Mutex<>> or Arc<RwLock<>> for shared state that needs thread-safe access across async operations
- Explicit Dependencies: Business logic dependencies should be passed as parameters or dependency injection
- Deterministic Operations: Avoid time-dependent logic, random values, or platform-specific behavior in core paths
- Consistent Error Handling: Same error conditions must always produce identical error responses
- Idempotent Operations: Operations should be safely repeatable without unintended side effects
Readability Standards
Complex distributed systems code must remain human-readable:
- Self-Documenting Code: Function and variable names should clearly express business intent
- Consistent Patterns: Follow established patterns (HTTP handlers, error handling, logging)
- Logical Flow: Code should read as a clear narrative from top to bottom
- Minimal Cognitive Load: Each function should have a single, well-defined responsibility
- Clear Abstractions: Break complex operations into well-named, focused helper functions
Separation of Concerns
Architectural layers must maintain clear boundaries:
- Handler Layer: HTTP request/response processing, input validation, context creation
- Service Layer: Business logic orchestration, data transformation
- Storage Layer: Data persistence, replication, consistency management
- Utility Layer: Reusable helpers with no business logic dependencies
- Shared State Coordination: Use thread-safe primitives (Arc, Mutex, RwLock) for components needing consistent views
Functions and Methods
- Keep functions focused on a single responsibility
- Use descriptive names that clearly indicate purpose and business intent
- Prefer early returns to reduce nesting complexity
- Error handling should be immediate and explicit
- Function length guideline: Most functions should be under 100 lines; handlers may be longer due to validation logic
- Parameter limits: Prefer structs over long parameter lists for better maintainability
Variables
- Use meaningful variable names that reflect business concepts
- Variable names should reflect usage frequency: frequent variables can be shorter
- Constants should use SCREAMING_SNAKE_CASE (e.g.,
MAX_RETRIES,DEFAULT_TIMEOUT) - Static variables should be clearly identified with proper safety documentation
- Prefer
constoverstaticwhen possible for compile-time constants
Developer Documentation
All significant features must include developer documentation in the docs/ directory:
- API Documentation: New endpoints must have usage examples in
docs/ - Architecture Decisions: Complex algorithms or design patterns should be documented
- Configuration Changes: New config options must be documented with examples
- Integration Guides: External system integrations need clear setup instructions
- Future Developer Context: Document WHY decisions were made, not just WHAT was implemented
Testing Requirements
Why Unit Tests Are Mandatory
Unit tests are non-negotiable in this project for critical business reasons:
- Data Integrity: MinIO Rust SDK handles enterprise-critical data. A single bug can cause data loss affecting thousands of users
- Security Compliance: Financial and healthcare customers require verifiable code quality. Tests provide audit trails
- Multi-tenant Reliability: One customer's workload cannot impact another's. Tests ensure proper isolation
- Performance SLAs: Enterprise customers have strict performance requirements. Tests validate behavior under load
- API Stability: Breaking changes can affect thousands of applications. Tests prevent regressions
- Distributed System Complexity: Complex interactions between storage nodes require comprehensive testing
Mandatory Unit Tests
EVERY implementation MUST include unit tests without being explicitly asked. Follow these patterns:
- Test functions must use
#[test]or#[tokio::test]attributes - Use parameterized tests or loop through test cases for multiple scenarios
- Cover both success and error cases, including edge conditions
- Mock external dependencies appropriately
- Test coverage guideline: Aim for comprehensive coverage of new code paths
- Include negative tests for error conditions and boundary cases
- Add benchmarks for performance-critical code paths
Improvement Suggestions
Claude will periodically analyze the codebase and suggest:
- Missing test coverage areas
- Performance optimizations
- Code refactoring opportunities
- Security improvements
- Documentation gaps
Testing Commands
Pre-commit Checklist
MANDATORY: ALL steps must pass before submitting any PR. No warnings or errors are acceptable.
Before any code changes:
- ✅ Format code: Run
cargo fmt --allto fix all formatting issues - ✅ Fix clippy warnings: Run
cargo clippy --fix --allow-dirty --allow-staged --all-targetsto auto-fix lints - ✅ Verify clippy clean: Run
cargo clippy --all-targetsand ensure ZERO warnings - ✅ Run all tests: Run
cargo testto ensure all tests pass - ✅ Build everything: Run
cargo build --all-targetsto verify all code compiles - ✅ Test coverage: Ensure new code has appropriate test coverage
- ✅ No redundant comments: Verify no redundant comments are added
Note: If clippy shows warnings, you MUST fix them. Use cargo clippy --fix or fix manually.
MinIO Server Setup for Testing
Running a Local MinIO Server
For testing S3 Tables / Iceberg features, you need a running MinIO AIStor server. You can start one using the MinIO source code.
Starting MinIO Server
Prerequisites:
- MinIO server source code at
C:\source\minio\eos - Fresh data directory (recommended for clean tests)
Basic Server Start:
cd C:\source\minio\eos
MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=minioadmin ./minio.exe server C:/minio-test-data --console-address ":9001"
Server Start with Logging (for debugging):
cd C:\source\minio\eos
MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=minioadmin ./minio.exe server C:/minio-test-data --console-address ":9001" 2>&1 | tee minio.log
Background Server Management
Start in Background:
# Using Bash tool with run_in_background parameter
cd "C:\source\minio\eos" && MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=minioadmin ./minio.exe server C:/minio-test-data --console-address ":9001" 2>&1
Monitor Background Server:
# Use BashOutput tool with the shell_id returned from background start
# This shows server logs including errors and API calls
Stop Background Server:
# Use KillShell tool with the shell_id
Server Configuration
Default Credentials:
- Access Key:
minioadmin - Secret Key:
minioadmin - API Endpoint:
http://localhost:9000 - Console:
http://localhost:9001
Fresh Start (Clean Slate):
# Remove old data and start fresh
rm -rf C:/minio-test-data && mkdir C:/minio-test-data
cd C:\source\minio\eos
MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=minioadmin ./minio.exe server C:/minio-test-data --console-address ":9001"
Common Issues
Port Already in Use:
- Error: "bind: Only one usage of each socket address"
- Solution: Close existing MinIO server (Ctrl+C) before starting new one
- Use
netstat -ano | findstr :9000to find processes using port 9000
Credential Errors:
- Error: "The Access Key Id you provided does not exist"
- Solution: Ensure MINIO_ROOT_USER and MINIO_ROOT_PASSWORD are set correctly
- Verify example code uses matching credentials
Testing S3 Tables Features
After Starting Server:
# Run S3 Tables examples
cd C:\Source\minio\minio-rs
cargo run --example s3tables_complete --features data-access
# Monitor server logs in the terminal where MinIO is running
# Look for API calls like:
# - POST /_iceberg/v1/warehouses
# - POST /_iceberg/v1/{warehouse}/namespaces
# - POST /_iceberg/v1/{warehouse}/namespaces/{namespace}/tables/{table}/commit
Debugging Failed Commits:
- Start MinIO with logging (see above)
- Run the Rust SDK test
- Check MinIO logs for error details
- Look for stack traces showing the exact failure point
Integration Test Setup
For running integration tests against MinIO:
- Start MinIO server in background
- Run test suite:
cargo test --features data-access - Server logs will show all API interactions
- Stop server when tests complete
Directory Structure Conventions
/src- Main library source code/tests- Integration tests/examples- Example usage code/docs- Documentation/benches- Performance benchmarks
Common Patterns to Follow
Logging
Use the log crate with appropriate macros:
use log::{debug, error, info, trace, warn};
// Examples:
info!("Starting operation: {}", operation_name);
debug!("Request details: {:?}", request);
error!("Operation failed: {}", err);
Error Handling
Use the Result type with proper error propagation:
use crate::s3::error::Error;
fn operation() -> Result<Response, Error> {
let result = risky_operation()?;
Ok(process(result))
}
Quick Reference
- Fix formatting:
cargo fmt --all - Auto-fix clippy:
cargo clippy --fix --allow-dirty --allow-staged --all-targets - Check clippy:
cargo clippy --all-targets(must show zero warnings) - Run tests:
cargo test - Run specific test:
cargo test test_name - Build all:
cargo build --all-targets - Build release:
cargo build --release - Generate docs:
cargo doc --open