Skip to content

Commit 6204d9a

Browse files
committed
Add in-memory cache, locking, and SQLite repositories
Introduces in-memory cache implementation for single-node deployments, memory-based and no-op locking abstractions, and SQLite-based repositories for access keys, blobs, buckets, objects, and users. Updates configuration example to support new GC, metrics, and rate limiting options. Updates documentation to mark Phase 7 as completed and outlines new architecture improvements for Phase 8.
1 parent 21a632a commit 6204d9a

18 files changed

Lines changed: 2863 additions & 29 deletions

File tree

MEMORY_BANK.md

Lines changed: 87 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,72 @@ GET /bucket?uploads → ListMultipartUploads
186186
GET /bucket/key?uploadId=X → ListParts
187187
```
188188

189-
### Phase 7: Operations & Observability ⚠️ NEXT PHASE
190-
- [ ] Garbage collection for orphan blobs
191-
- [ ] Prometheus metrics
192-
- [ ] Health check endpoints
193-
- [ ] Request tracing
194-
- [ ] Rate limiting
189+
### Phase 7: Operations & Observability ✅ COMPLETED
190+
- [x] Garbage collection for orphan blobs - `internal/service/gc_service.go`
191+
- [x] Prometheus metrics - `internal/metrics/metrics.go`
192+
- [x] Health check endpoints - `internal/handler/health.go`
193+
- [x] Request tracing - `internal/middleware/tracing.go`
194+
- [x] Rate limiting - `internal/middleware/ratelimit.go`
195+
196+
**Implementation Details:**
197+
198+
**Garbage Collection:**
199+
- Automatic background GC with configurable interval (default: 1 hour)
200+
- Grace period prevents deleting blobs during active uploads (default: 24 hours)
201+
- Batch processing with configurable size (default: 1000 blobs per run)
202+
- Dry run mode for testing without actual deletion
203+
- Tracks orphan blobs (ref_count = 0) and cleans up both DB and storage
204+
205+
**Prometheus Metrics:**
206+
- Separate metrics server on configurable port (default: 9091)
207+
- HTTP request metrics: total, duration, in-flight, response size
208+
- Storage metrics: operations, duration, bytes transferred
209+
- Auth metrics: attempts, failures with reasons
210+
- GC metrics: runs, blobs deleted, bytes freed, duration
211+
- Rate limiting metrics: requests limited by type
212+
213+
**Health Endpoints:**
214+
```
215+
GET /health → Full component health with latency
216+
GET /healthz → Kubernetes liveness probe
217+
GET /readyz → Kubernetes readiness probe
218+
```
219+
- Component-level status (database, storage)
220+
- Cached responses for efficiency (default: 5s TTL)
221+
- Status levels: healthy, degraded, unhealthy
222+
223+
**Request Tracing:**
224+
- Automatic request ID generation (X-Request-ID header)
225+
- Trace ID propagation for distributed tracing
226+
- S3-compatible headers (x-amz-request-id, x-amz-id-2)
227+
- Structured logging with request context
228+
- Path normalization for low-cardinality metrics
229+
230+
**Rate Limiting:**
231+
- Token bucket algorithm per client IP
232+
- Configurable rate (default: 100 req/s) and burst (default: 200)
233+
- S3-compatible SlowDown error response
234+
- Automatic bucket cleanup for stale clients
235+
- Optional bandwidth limiting support
236+
237+
**Configuration:**
238+
```yaml
239+
metrics:
240+
enabled: true
241+
port: 9091
242+
path: /metrics
243+
244+
rate_limit:
245+
enabled: true
246+
requests_per_second: 100
247+
burst_size: 200
248+
249+
gc:
250+
enabled: true
251+
interval: 1h
252+
grace_period: 24h
253+
batch_size: 1000
254+
```
195255
196256
### Phase 8: Architecture Improvements (Community Requested)
197257
> **Community Feedback**: "PostgreSQL + Redis is overkill for single-node deployments."
@@ -206,6 +266,8 @@ GET /bucket/key?uploadId=X → ListParts
206266
- [ ] Cross-region replication
207267
- [ ] Server-side encryption
208268
- [ ] Object locking (WORM)
269+
- [ ] WEB Dashboard (webui)
270+
- [ ] Python and PHP sdk
209271
210272
---
211273
@@ -408,13 +470,13 @@ Path: /data/ab/cd/abcdef1234567890...
408470
## Section 4: Current Context
409471
410472
### Active Development Phase
411-
**Phase 7: Operations & Observability**
473+
**Phase 8: Architecture Improvements**
412474
413475
### Current Task
414-
Planning next phase: Garbage collection, metrics, health checks
476+
Planning next phase: Embedded database support, single-node optimization
415477
416478
### Last Updated
417-
2025-01-08
479+
2025-12-04
418480
419481
### Completed Phases
420482
- ✅ Phase 1: Core Infrastructure
@@ -423,20 +485,26 @@ Planning next phase: Garbage collection, metrics, health checks
423485
- ✅ Phase 4: Object Operations
424486
- ✅ Phase 5: Versioning
425487
- ✅ Phase 6: Multipart Upload
488+
- ✅ Phase 7: Operations & Observability
426489
427490
### Files Modified This Session
428-
- `internal/service/multipart_service.go` - Complete multipart upload service
429-
- `internal/service/multipart_service_test.go` - Unit tests (15 tests passing)
430-
- `internal/handler/multipart_handler.go` - HTTP handlers with S3 XML responses
431-
- `internal/handler/router.go` - Multipart upload routing
432-
- `cmd/alexander-server/main.go` - Wired MultipartService and MultipartHandler
433-
- `MEMORY_BANK.md` - Updated with Phase 6 completion
491+
- `internal/metrics/metrics.go` - Prometheus metrics definitions
492+
- `internal/middleware/ratelimit.go` - Token bucket rate limiting
493+
- `internal/middleware/tracing.go` - Request tracing and correlation IDs
494+
- `internal/service/gc_service.go` - Garbage collection service
495+
- `internal/handler/health.go` - Enhanced health check endpoints
496+
- `internal/handler/router.go` - Integrated new middleware
497+
- `internal/config/config.go` - Added metrics, rate_limit, gc config sections
498+
- `internal/storage/interfaces.go` - Added HealthCheck method
499+
- `internal/storage/filesystem/storage.go` - Implemented HealthCheck
500+
- `internal/storage/errors.go` - Added IsNotFound helper
501+
- `cmd/alexander-server/main.go` - Wired GC, metrics server, middleware
502+
- `MEMORY_BANK.md` - Updated with Phase 7 completion
434503
435504
### Pending Tasks
436-
1. Garbage collection for orphan blobs (Phase 7)
437-
2. Prometheus metrics (Phase 7)
438-
3. Health check endpoints (Phase 7)
439-
4. Add embedded database option (Phase 8)
505+
1. Embedded database support (SQLite/BadgerDB) - Phase 8
506+
2. Memory-based locking for single-node mode - Phase 8
507+
3. Single binary deployment mode - Phase 8
440508
441509
### Known Issues
442510
None currently.

configs/config.yaml.example

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ gc:
8181
interval: 1h
8282
# Grace period before deleting orphan blobs
8383
grace_period: 24h
84+
# Number of blobs to process per run
85+
batch_size: 1000
86+
# Dry run mode (log without deleting)
87+
dry_run: false
8488

8589
# Logging
8690
logging:
@@ -92,9 +96,22 @@ logging:
9296
# Metrics (Prometheus)
9397
metrics:
9498
enabled: true
99+
port: 9091
95100
path: "/metrics"
96101

97-
# Health check
98-
health:
99-
path: "/health"
100-
detailed: true
102+
# Rate limiting
103+
rate_limit:
104+
enabled: true
105+
# Requests per second per client
106+
requests_per_second: 100
107+
# Burst capacity (max requests before limiting)
108+
burst_size: 200
109+
# Bandwidth limiting (optional)
110+
bandwidth_enabled: false
111+
bytes_per_second: 104857600 # 100 MB/s
112+
113+
# Health check endpoints
114+
# Available endpoints:
115+
# GET /health - Full component status with latency
116+
# GET /healthz - Kubernetes liveness probe
117+
# GET /readyz - Kubernetes readiness probe

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.24.0
55
require (
66
github.com/google/uuid v1.6.0
77
github.com/jackc/pgx/v5 v5.7.6
8+
github.com/prometheus/client_golang v1.23.2
89
github.com/redis/go-redis/v9 v9.17.2
910
github.com/rs/zerolog v1.33.0
1011
github.com/spf13/viper v1.19.0
@@ -29,7 +30,6 @@ require (
2930
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
3031
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
3132
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
32-
github.com/prometheus/client_golang v1.23.2 // indirect
3333
github.com/prometheus/client_model v0.6.2 // indirect
3434
github.com/prometheus/common v0.66.1 // indirect
3535
github.com/prometheus/procfs v0.16.1 // indirect

go.sum

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z
1818
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
1919
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
2020
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
21-
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
22-
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
21+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
22+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
2323
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
2424
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
2525
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
@@ -32,10 +32,14 @@ github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
3232
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
3333
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
3434
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
35+
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
36+
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
3537
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
3638
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
3739
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
3840
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
41+
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
42+
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
3943
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
4044
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
4145
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
@@ -63,8 +67,8 @@ github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzM
6367
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
6468
github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI=
6569
github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
66-
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
67-
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
70+
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
71+
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
6872
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
6973
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
7074
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
@@ -92,13 +96,15 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
9296
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
9397
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
9498
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
95-
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
9699
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
100+
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
97101
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
98102
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
99103
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
100104
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
101105
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
106+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
107+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
102108
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
103109
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
104110
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=

0 commit comments

Comments
 (0)