Skip to content

Commit 55acda0

Browse files
committed
use crate TypedBuilder for builders
bugfixes WIP doc updated
1 parent 25d424b commit 55acda0

File tree

206 files changed

+3489
-3203
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

206 files changed

+3489
-3203
lines changed

.claude/settings.local.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(grep:*)"
5+
],
6+
"deny": []
7+
},
8+
"$schema": "https://json.schemastore.org/claude-code-settings.json"
9+
}

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CLAUDE.md

CLAUDE.md

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
# Claude Code Style Guide for MinIO Rust SDK
2+
3+
- Only provide actionable feedback.
4+
- Exclude code style comments on generated files. These will have a header signifying that.
5+
- Use github markdown folded sections for all items.
6+
- Do not use emojis.
7+
- Do not add a "feel good" section.
8+
9+
## Copyright Header
10+
11+
All source files that haven't been generated MUST include the following copyright header:
12+
13+
```go
14+
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
15+
// Copyright 20?? MinIO, Inc.
16+
//
17+
// Licensed under the Apache License, Version 2.0 (the "License");
18+
// you may not use this file except in compliance with the License.
19+
// You may obtain a copy of the License at
20+
//
21+
// http://www.apache.org/licenses/LICENSE-2.0
22+
//
23+
// Unless required by applicable law or agreed to in writing, software
24+
// distributed under the License is distributed on an "AS IS" BASIS,
25+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26+
// See the License for the specific language governing permissions and
27+
// limitations under the License.
28+
```
29+
30+
## Code Style Guidelines
31+
32+
### Ignore files
33+
- Ignore files from processing mentioned under '.gitignore'
34+
35+
### Comments
36+
- **NO redundant comments** - Code should be self-documenting
37+
- Avoid obvious comments like `// Set x to 5` for `x := 5`
38+
- Only add comments when they explain WHY, not WHAT
39+
- Document complex algorithms or non-obvious business logic
40+
41+
## Critical Code Patterns
42+
43+
### Builder Pattern
44+
All S3 API requests MUST use the builder pattern, with the following documentation but then for the appropriate API
45+
46+
```rust
47+
/// Argument builder for the [`AppendObject`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-buckets-objects-append.html) S3 API operation.
48+
///
49+
/// This struct constructs the parameters required for the [`Client::append_object`](crate::s3::client::Client::append_object) method.
50+
```
51+
52+
**Key Requirements:**
53+
1. The aws docs url must exist.
54+
55+
### Admin API Handler Pattern
56+
Handler methods for `adminAPIHandlers` do not follow the previous pattern as it is handled in a middleware function.
57+
Instead, they should follow this pattern:
58+
59+
```go
60+
func (a adminAPIHandlers) HandlerName(w http.ResponseWriter, r *http.Request) {
61+
ctx := r.Context()
62+
63+
// Option 1 for objectAPI fetch
64+
objectAPI := newObjectLayerFn()
65+
if objectAPI == nil || globalNotificationSys == nil {
66+
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL)
67+
return
68+
}
69+
70+
// Option 2 for objectAPI fetch
71+
objectAPI, _ := validateAdminReq(ctx, w, r, policy.DeletePolicyAdminAction)
72+
if objectAPI == nil {
73+
return
74+
}
75+
76+
// Implementation here
77+
78+
// Error handling pattern:
79+
if err != nil {
80+
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
81+
return
82+
}
83+
}
84+
```
85+
86+
## Code Quality Principles
87+
88+
### Why Code Quality Standards Are Mandatory
89+
90+
Code quality standards are **critical business requirements** for MinIO Rust SDK:
91+
92+
1. **Enterprise Data Safety**: A single bug can corrupt terabytes of customer data across distributed systems
93+
2. **Code Efficientcy**: MinIO Rust SDK code must be efficient and performant
94+
3. **Scalability**: MinIO Rust SDK must be able to handle thousands of concurrent requests
95+
4. **High Availability**: Systems must handle failures gracefully - unpredictable code creates cascading failures
96+
5**Developer Velocity**: New team members must understand complex distributed systems quickly and safely
97+
98+
### Predictable Code Requirements
99+
100+
Code must exhibit **deterministic behavior** to ensure system reliability:
101+
102+
1. **Managed Global State**: Global variables are acceptable for system-wide shared state (e.g., `globalObjectLayer`, `globalNotificationSys`, `globalSiteReplicationSys`) that all layers need consistent access to
103+
2. **Explicit Dependencies**: Business logic dependencies should be passed as parameters or dependency injection
104+
3. **Deterministic Operations**: Avoid time-dependent logic, random values, or platform-specific behavior in core paths
105+
4. **Consistent Error Handling**: Same error conditions must always produce identical error responses
106+
5. **Idempotent Operations**: Operations should be safely repeatable without unintended side effects
107+
108+
### Readability Standards
109+
110+
Complex distributed systems code must remain **human-readable**:
111+
112+
1. **Self-Documenting Code**: Function and variable names should clearly express business intent
113+
2. **Consistent Patterns**: Follow established patterns (HTTP handlers, error handling, logging)
114+
3. **Logical Flow**: Code should read as a clear narrative from top to bottom
115+
4. **Minimal Cognitive Load**: Each function should have a single, well-defined responsibility
116+
5. **Clear Abstractions**: Break complex operations into well-named, focused helper functions
117+
118+
### Separation of Concerns
119+
120+
**Architectural layers must maintain clear boundaries**:
121+
122+
1. **Handler Layer**: HTTP request/response processing, input validation, context creation
123+
2. **Service Layer**: Business logic orchestration, data transformation
124+
3. **Storage Layer**: Data persistence, replication, consistency management
125+
4. **Utility Layer**: Reusable helpers with no business logic dependencies
126+
5. **Global Coordination**: Shared state management via global variables where all components need consistent views
127+
128+
### Functions and Methods
129+
- Keep functions focused on a single responsibility
130+
- Use descriptive names that clearly indicate purpose and business intent
131+
- Prefer early returns to reduce nesting complexity
132+
- Error handling should be immediate and explicit
133+
- **Function length guideline**: Most functions should be under 100 lines; handlers may be longer due to validation logic
134+
- **Parameter limits**: Prefer structs over long parameter lists for better maintainability
135+
136+
### Variables
137+
- Use meaningful variable names that reflect business concepts
138+
- Variable names should reflect usage frequency: frequent variables can be shorter
139+
- Constants should follow Rust patterns
140+
- Global variables should be clearly identified and documented for their system-wide purpose
141+
142+
### Developer Documentation
143+
144+
**All significant features must include developer documentation** in the `docs/` directory:
145+
146+
1. **API Documentation**: New endpoints must have usage examples in `docs/`
147+
2. **Architecture Decisions**: Complex algorithms or design patterns should be documented
148+
3. **Configuration Changes**: New config options must be documented with examples
149+
4. **Integration Guides**: External system integrations need clear setup instructions
150+
5. **Future Developer Context**: Document WHY decisions were made, not just WHAT was implemented
151+
152+
## Testing Requirements
153+
154+
### Why Unit Tests Are Mandatory
155+
156+
Unit tests are **non-negotiable** in this project for critical business reasons:
157+
158+
1. **Data Integrity**: MinIO EOS handles enterprise-critical data. A single bug can cause data loss affecting thousands of users
159+
2. **Security Compliance**: Financial and healthcare customers require verifiable code quality. Tests provide audit trails
160+
3. **Multi-tenant Reliability**: One customer's workload cannot impact another's. Tests ensure proper isolation
161+
4. **Performance SLAs**: Enterprise customers have strict performance requirements. Tests validate behavior under load
162+
5. **API Stability**: Breaking changes can affect thousands of applications. Tests prevent regressions
163+
6. **Distributed System Complexity**: Complex interactions between storage nodes require comprehensive testing
164+
165+
### Mandatory Unit Tests
166+
**EVERY implementation MUST include unit tests** without being explicitly asked. Follow these patterns:
167+
168+
1. Test files must be named `*_test.go`
169+
2. Test functions must start with `Test`
170+
3. Use table-driven tests for multiple scenarios
171+
4. Cover both success and error cases, including edge conditions
172+
5. Mock external dependencies appropriately
173+
6. **Test coverage guideline**: Aim for comprehensive coverage of new code paths
174+
7. Include negative tests for error conditions and boundary cases
175+
8. Add benchmarks for performance-critical code paths
176+
177+
178+
## Testing Commands
179+
180+
## Pre-commit Checklist
181+
182+
Before any code changes:
183+
1. ✅ Run `make lint` to check code style
184+
2. ✅ Run `make test` to ensure all tests pass
185+
3. ✅ Run `make lint-fix` to auto-fix linting issues
186+
4. ✅ Ensure new code has appropriate test coverage
187+
5. ✅ Verify no redundant comments are added
188+
189+
## Generated Code Management
190+
191+
**CRITICAL**: This codebase has 54+ auto-generated files ending in `_gen.go`.
192+
193+
### When to Regenerate:
194+
- After modifying generator templates
195+
- When adding new API endpoints
196+
- When changing data structures used by generators
197+
198+
### Required Steps:
199+
```bash
200+
# 1. Generate code
201+
go generate ./...
202+
203+
# 2. MUST commit generated files (they are NOT in .gitignore)
204+
git add *_gen.go
205+
206+
# 3. Verify no uncommitted generated files remain
207+
git diff --name-only | grep '_gen.go$' || echo "All generated files committed"
208+
```
209+
210+
### Generated File Pattern:
211+
- Files ending in `_gen.go` are auto-generated
212+
- **DO NOT edit these files manually**
213+
- Always commit generated changes with your PR
214+
- CI will fail if generated files are out of sync
215+
216+
## Directory Structure Conventions
217+
218+
- `/cmd` - Main application code and server components
219+
- `/internal` - Internal packages not meant for external use
220+
- `/pkg` - Public packages that can be imported by external projects
221+
- `/docs` - Documentation and scripts
222+
- `/buildscripts` - Build and CI/CD scripts
223+
224+
## Common Patterns to Follow
225+
226+
### Logging
227+
Use the log package
228+
229+
```go
230+
log::info!("life cycle settings before setting: resp={resp:?}");
231+
```
232+
233+
## Improvement Suggestions
234+
235+
Claude will periodically analyze the codebase and suggest:
236+
- Missing test coverage areas
237+
- Performance optimizations
238+
- Code refactoring opportunities
239+
- Security improvements
240+
- Documentation gaps
241+
242+
## Quick Reference
243+
244+
- **Fix linting**: `cargo fmt --all`
245+
- **Run specific test**: `cargo test --test TestName`

Cargo.toml

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -33,41 +33,42 @@ bytes = { workspace = true }
3333
async-std = { workspace = true, features = ["attributes"] }
3434
reqwest = { workspace = true, features = ["stream"] }
3535

36-
async-recursion = "1.1.1"
37-
async-stream = "0.3.6"
38-
async-trait = "0.1.88"
39-
base64 = "0.22.1"
40-
chrono = "0.4.41"
41-
crc = "3.3.0"
36+
async-recursion = "1.1"
37+
async-stream = "0.3"
38+
async-trait = "0.1"
39+
base64 = "0.22"
40+
chrono = "0.4"
41+
crc = "3.3"
4242
dashmap = "6.1.0"
43-
env_logger = "0.11.8"
44-
hmac = { version = "0.12.1", optional = true }
45-
hyper = { version = "1.6.0", features = ["full"] }
46-
lazy_static = "1.5.0"
47-
log = "0.4.27"
48-
md5 = "0.8.0"
49-
multimap = "0.10.1"
50-
percent-encoding = "2.3.1"
51-
url = "2.5.4"
52-
regex = "1.11.1"
53-
ring = { version = "0.17.14", optional = true, default-features = false, features = ["alloc"] }
54-
serde = { version = "1.0.219", features = ["derive"] }
55-
serde_json = "1.0.142"
56-
sha2 = { version = "0.10.9", optional = true }
57-
urlencoding = "2.1.3"
58-
xmltree = "0.11.0"
59-
http = "1.3.1"
60-
thiserror = "2.0.14"
43+
env_logger = "0.11"
44+
hmac = { version = "0.12", optional = true }
45+
hyper = { version = "1.7", features = ["full"] }
46+
lazy_static = "1.5"
47+
log = "0.4"
48+
md5 = "0.8"
49+
multimap = "0.10"
50+
percent-encoding = "2.3"
51+
url = "2.5"
52+
regex = "1.11"
53+
ring = { version = "0.17", optional = true, default-features = false, features = ["alloc"] }
54+
serde = { version = "1.0", features = ["derive"] }
55+
serde_json = "1.0"
56+
sha2 = { version = "0.10", optional = true }
57+
urlencoding = "2.1"
58+
xmltree = "0.11"
59+
http = "1.3"
60+
thiserror = "2.0"
61+
typed-builder = "0.21"
6162

6263
[dev-dependencies]
6364
minio-common = { path = "./common" }
6465
minio-macros = { path = "./macros" }
65-
tokio = { version = "1.47.1", features = ["full"] }
66-
async-std = { version = "1.13.1", features = ["attributes", "tokio1"] }
67-
clap = { version = "4.5.44", features = ["derive"] }
68-
rand = { version = "0.9.2", features = ["small_rng"] }
69-
quickcheck = "1.0.3"
70-
criterion = "0.7.0"
66+
tokio = { version = "1.47", features = ["full"] }
67+
async-std = { version = "1.13", features = ["attributes", "tokio1"] }
68+
clap = { version = "4.5", features = ["derive"] }
69+
rand = { version = "0.9", features = ["small_rng"] }
70+
quickcheck = "1.0"
71+
criterion = "0.7"
7172

7273
[lib]
7374
name = "minio"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use minio::s3::response::BucketExistsResponse;
2424
2525
#[tokio::main]
2626
async fn main() {
27-
let client: Client = Default::default(); // configure your client
28-
27+
let client = Client::create_client_on_localhost().unwrap(); // configure your client here
28+
2929
let exists: BucketExistsResponse = client
3030
.bucket_exists("my-bucket")
3131
.send()

benches/s3/bench_bucket_exists.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ pub(crate) fn bench_bucket_exists(criterion: &mut Criterion) {
2323
"bucket_exists",
2424
criterion,
2525
|| async { Ctx2::new().await },
26-
|ctx| BucketExists::new(ctx.client.clone(), ctx.bucket.clone()),
26+
|ctx| {
27+
BucketExists::builder()
28+
.client(ctx.client.clone())
29+
.bucket(ctx.bucket.clone())
30+
.build()
31+
},
2732
);
2833
}

0 commit comments

Comments
 (0)