4.9 KiB
post3 — Pluggable S3-Compatible Storage
Project Overview
post3 = PostgreSQL + S3. An S3-compatible storage system with pluggable backends. Objects can be stored in PostgreSQL (split into 1 MiB blocks in bytea columns) or on the local filesystem.
Architecture
crates/post3/— Core library crate. Contains theStorageBackendtrait,PostgresBackend,FilesystemBackend, repository layer, models, error types, and SQL migrations.crates/post3-server/— Binary + lib crate. S3-compatible HTTP server using axum. Generic overB: StorageBackend— works with any backend.crates/post3-sdk/— Client SDK wrappingaws-sdk-s3with ergonomic defaults (dummy creds, path-style, us-east-1). Re-exportsaws_sdk_s3for advanced use.ci/— Custom CI pipeline usingdagger-sdkdirectly. Builds, tests, and packages in containers.
Development Commands (mise)
mise run up # Start PostgreSQL (docker compose)
mise run down # Stop PostgreSQL + remove volumes
mise run check # cargo check --workspace
mise run dev # Run the server (localhost:9000)
mise run test # Run all tests (starts PG first)
mise run test:integration # Run S3 integration tests only
mise run db:shell # psql into dev database
mise run db:reset # Wipe and restart PostgreSQL
mise run build # Release build
mise run ci:pr # Run CI PR pipeline via Dagger
mise run ci:main # Run CI main pipeline via Dagger
mise run example:basic # Run basic SDK example (requires server)
mise run example:metadata # Run metadata example (requires server)
mise run example:aws-sdk # Run raw aws-sdk-s3 example (requires server)
mise run example:cli # Run AWS CLI example (requires server + aws CLI)
mise run example:curl # Run curl example (requires server)
mise run example:large # Run large file stress test (requires server)
Environment
- DATABASE_URL:
postgresql://devuser:devpassword@localhost:5435/post3_dev - POST3_HOST:
127.0.0.1:9000 - PostgreSQL 18 on port 5435 (avoids conflicts with other projects)
Key Patterns
StorageBackendtrait — Pluggable storage viaimpl Future<...> + Senddesugared async methods (edition 2024). Server is generic overB: StorageBackend.PostgresBackend(aliasStore) — PostgreSQL backend using sqlx repos + 1 MiB block chunksFilesystemBackend— Local filesystem backend using percent-encoded keys, JSON metadata, atomic writes- notmad 0.11 for component lifecycle (native async traits, no async_trait)
- sqlx with
PgPoolfor database access; migrations atcrates/post3/migrations/ - axum 0.8 with
{param}path syntax and{*wildcard}for nested keys - Trailing slash routes duplicated for AWS SDK compatibility (
/{bucket}+/{bucket}/) - Body limit set to 5 GiB via
DefaultBodyLimit - S3 multipart upload supported: CreateMultipartUpload, UploadPart, CompleteMultipartUpload, AbortMultipartUpload, ListParts, ListMultipartUploads
- Query param dispatch: PUT/GET/DELETE/POST on
/{bucket}/{*key}dispatch by?uploads,?uploadId,?partNumber - Handlers use turbofish
::<B>in router for generic dispatch - Tests use
aws-sdk-s3withforce_path_style(true)and dummy credentials
Database Schema
7 tables: buckets, objects, object_metadata (KV registry), blocks (1 MiB chunks), multipart_uploads, multipart_upload_metadata, upload_parts. All use ON DELETE CASCADE for cleanup.
Testing
- PostgreSQL integration tests in
crates/post3-server/tests/s3_integration.rs— spin up a real server per test on an ephemeral port. Each test gets its ownPgPooland cleans the database. Tests must run with--test-threads=1to avoid DB conflicts. - Filesystem integration tests in
crates/post3-server/tests/fs_integration.rs— same HTTP-level tests but usingFilesystemBackendwith a temp directory. No PostgreSQL required. - Filesystem unit tests in
crates/post3/src/fs.rs— direct backend method tests.
Roadmap (see todos/)
- POST3-008: Client SDK crate — Done (
crates/post3-sdk/) - POST3-009: CI pipeline — Done (custom
ci/crate usingdagger-sdkdirectly) - POST3-010: Production Docker Compose (Dockerfile, health endpoint, compose)
- POST3-011: Usage examples — Done (Rust examples, AWS CLI, curl, large file stress test)
- POST3-012: Authentication (SigV4 verification, API keys table, admin CLI)
CI Pattern
Custom ci/ crate using dagger-sdk (v0.19) directly — self-contained, no external dagger-components dependency. Subcommands: pr (check + test + build + package) and main (same, no publish yet). Uses PostgreSQL 18 as a Dagger service container for integration tests. Skeleton source + dependency-only prebuild for cargo layer caching. mold linker for fast linking. Final image: debian:bookworm-slim.