dog-blob
Production-ready blob storage infrastructure for DogRS applications
dog-blob provides streaming-first, resumable, range-friendly blob storage for DogRS applications with zero boilerplate. It's designed to eliminate all the routine media handling code that services shouldn't have to write.
Perfect for: Video streaming, file uploads, media processing, document storage, backup systems, and any application that needs reliable blob handling.
Features
- Streaming-first: Handle huge video files without buffering
- Multipart/resumable uploads: Built-in coordination for large files
- Range requests: First-class support for video/audio scrubbing
- Storage agnostic: Works with any backend (memory, filesystem, S3, etc.)
- Server agnostic: No HTTP coupling - works with any protocol
- Zero boilerplate: Services focus on business logic, not media mechanics
Table of Contents
- Quick Start
- Core Concepts
- Storage Backends
- Advanced Features
- Real-World Examples
- API Reference
- Performance & Best Practices
Quick Start
Add to your Cargo.toml:
[]
= { = "../dog-blob" }
# For S3 support:
# dog-blob = { path = "../dog-blob", features = ["s3"] }
30-Second Example
use *;
use ReaderStream;
use Cursor;
async
Core Concepts
dog-blob is built around four key concepts:
BlobAdapter- The main interface you embed in your servicesBlobStore- Pluggable storage backend (S3, filesystem, memory, etc.)BlobCtx- Tenant/user context for multi-tenant applicationsBlobReceipt- Portable metadata returned after successful storage
Service Integration
The key insight: BlobAdapter is infrastructure, not a service. You embed it in your services:
Architecture
dog-blob follows a clean separation of concerns:
┌─────────────────┐
│ Your Service │ ← Business logic only
├─────────────────┤
│ BlobAdapter │ ← Media coordination
├─────────────────┤
│ BlobStore │ ← Storage primitives
└─────────────────┘
Core Types
BlobAdapter: Main interface - embed this in your servicesBlobStore: Storage backend trait (implement for new storage types)BlobReceipt: Portable metadata returned after storageBlobCtx: Tenant/user context for multi-tenant apps
Storage Backends
dog-blob supports multiple storage backends through the BlobStore trait:
S3-Compatible Store (Production Ready)
Works with AWS S3, MinIO, DigitalOcean Spaces, and other S3-compatible services:
use ;
// From environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, etc.)
let store = from_env?;
// Or configure manually
let config = new
.with_region
.with_endpoint
.with_credentials;
let store = new?;
let adapter = new;
Features:
- ✅ Native multipart uploads
- ✅ Signed URL generation
- ✅ Range request support
- ✅ Server-side encryption
- ✅ Cross-region replication
Memory Store (Testing & Development)
Perfect for unit tests and development:
use MemoryBlobStore;
let store = new;
let adapter = new;
Features:
- ✅ Zero configuration
- ✅ Fast in-memory operations
- ✅ Automatic cleanup
- ❌ Not persistent (data lost on restart)
Custom Storage Implementation
Implement BlobStore for your own storage backend:
use ;
use async_trait;
Advanced Features
Multipart/Resumable Uploads
dog-blob handles multipart uploads automatically for large files:
use *;
// Configure multipart thresholds
let config = new
.with_multipart_threshold // 16MB threshold
.with_upload_rules;
let adapter = new;
// For files > 16MB, this automatically becomes multipart
let large_file = open?;
let stream = new;
let put_request = new
.with_content_type
.with_filename;
// Automatically handles multipart coordination
let receipt = adapter.put.await?;
Manual multipart control:
// Begin multipart upload
let session = adapter.begin_multipart.await?;
// Upload parts (can be done in parallel, out of order)
let part1 = adapter.upload_part.await?;
let part2 = adapter.upload_part.await?;
// Complete upload
let receipt = adapter.complete_multipart.await?;
The coordinator automatically handles:
- ✅ Native multipart (when storage supports it)
- ✅ Staged assembly (universal fallback)
- ✅ Part validation and ordering
- ✅ Cleanup on abort/failure
- ✅ Resume from partial uploads
Range Requests (Video Streaming)
Perfect for video/audio scrubbing and progressive downloads:
use ;
// Request specific byte range (bytes 1024-2048)
let range = new;
let opened = adapter.open.await?;
match opened.content
Common use cases:
- 🎥 Video seeking/scrubbing
- 🎵 Audio preview generation
- 📄 PDF page extraction
- 🖼️ Image thumbnail generation
- 📊 Large file sampling
Metadata and Custom Fields
Store rich metadata alongside your blobs:
use json;
let put_request = new
.with_content_type
.with_filename
.with_metadata;
let receipt = adapter.put.await?;
// Retrieve metadata later
let info = adapter.info.await?;
println!;
Configuration
let config = new
.with_max_blob_bytes // 5GB limit
.with_multipart_threshold // 16MB threshold
.with_upload_rules;
Comparison to feathers-blob
| Feature | feathers-blob | dog-blob |
|---|---|---|
| Input model | Buffer/data-URI | Streaming ByteStream |
| Large files | Manual | First-class |
| Multipart | External middleware | Built-in coordination |
| Resumable | Not native | Native |
| Range reads | App-implemented | First-class API |
| Storage abstraction | abstract-blob-store | Pluggable traits |
| Metadata storage | Service-specific | Portable receipts |
| Server coupling | HTTP-centric | Server-agnostic |
Design Philosophy
- Media is infrastructure, not a service - BlobAdapter is a capability you embed
- Streaming everywhere - Never buffer entire files in memory
- Storage agnostic - Switch backends without changing service code
- Server agnostic - Works with HTTP, gRPC, CLI, background jobs
- Zero opinions - You decide metadata schema, ACL, business logic
Real-World Examples
Video Streaming Service
use *;
use json;
Document Management System
Backup Service with Chunked Uploads
API Reference
Core Types
BlobAdapter
The main interface for blob operations.
BlobCtx
Context for multi-tenant operations.
BlobPut
Request builder for blob uploads.
Performance & Best Practices
Streaming Best Practices
- Always stream large files - Never load entire files into memory
- Use appropriate buffer sizes - 8MB chunks work well for most cases
- Enable multipart for large files - Set threshold around 16-100MB
- Implement backpressure - Don't overwhelm slower storage backends
// ✅ Good: Streaming from disk
let file = open.await?;
let stream = new;
let receipt = adapter.put.await?;
// ❌ Bad: Loading entire file into memory
let data = read.await?;
let stream = once;
let receipt = adapter.put.await?;
Configuration Tuning
// For high-throughput video streaming
let config = new
.with_multipart_threshold // 50MB
.with_upload_rules;
// For document storage (smaller files)
let config = new
.with_multipart_threshold // 10MB
.with_upload_rules;
Error Handling
use ;
match adapter.put.await
Monitoring and Observability
// Enable tracing for observability
use ;
Examples
The dog-examples/ directory contains real-world implementations:
music-blobs/- Complete music streaming application with waveform visualization- Demonstrates S3-compatible storage integration
- Shows multipart upload handling for large audio files
- Implements range requests for audio scrubbing
- Features real-time waveform generation using Symphonia audio decoding
- Production-ready service architecture with dog-blob integration
Roadmap
- S3-compatible store implementation ✅
- Multipart upload coordination ✅
- Range request support ✅
- Production examples (music-blobs) ✅
- Filesystem store implementation
- Video processing pipeline (optional)
- Signed URL support
- Compression support
- Deduplication support
License
MIT OR Apache-2.0