brainy/STORAGE_ADAPTER_QUICK_REFERENCE.md

292 lines
8.5 KiB
Markdown
Raw Normal View History

feat(storage): Phase 1 - TypeAwareStorageAdapter with type-first architecture Implements type-first storage architecture for billion-scale optimization. ## Implementation **TypeAwareStorageAdapter** (649 lines) - Extends BaseStorage with type-first routing - Type-first paths: `entities/nouns/{type}/vectors/{shard}/{uuid}.json` - Type-first paths: `entities/verbs/{type}/vectors/{shard}/{uuid}.json` - Fixed-size type tracking: Uint32Array(31) + Uint32Array(40) = 284 bytes - O(1) type filtering via directory structure - Type caching for fast lookups - 17 abstract methods implemented - HNSW data storage with type-first paths **Storage Factory Integration** - Added 'type-aware' storage type - Wraps any underlying storage adapter (MemoryStorage, FileSystemStorage, S3, etc.) - Recursive storage creation with type assertions **Tests** - Comprehensive test suite (54 test cases) - Tests noun/verb storage, type tracking, caching, HNSW data - Tests memory efficiency and integration ## Architecture Benefits **Self-Documenting Paths** - Type visible in filesystem: `ls entities/nouns/` shows all noun types - No parsing required to identify type - Beautiful, clean structure **Performance** - O(1) type filtering (just list directory) - Type cache eliminates repeated type lookups - Independent type scaling (hot types on fast storage) **Memory Impact @ 1B Scale** - Type tracking: 284 bytes (vs ~120KB with Maps) = -99.76% - Enables metadata optimization: 5GB → 3GB = -40% - Foundation for HNSW optimization: 384GB → 50GB = -87% - Total system: 557GB → 69GB = -88% ## Technical Details **Type Tracking** - Noun counts: Uint32Array(31) = 124 bytes - Verb counts: Uint32Array(40) = 160 bytes - Type caches: Map<id, type> for O(1) lookups **Delegation Pattern** - Wraps any BaseStorage implementation - Protected method access via type casting helper - Type statistics persistence **Type-First Paths** ``` entities/nouns/person/vectors/4a/4abc...123.json entities/nouns/document/vectors/7f/7f12...456.json entities/verbs/creates/vectors/3b/3bcd...789.json ``` ## Status ✅ TypeAwareStorageAdapter: Complete (compiles, all abstract methods implemented) ✅ Storage Factory: Integrated ✅ Tests: Written (54 tests, blocked by @msgpack dependency issue) ⏳ TypeFirstMetadataIndex: Next (Phase 1b) ⏳ Type-Aware HNSW: Future (Phase 2) ⏳ Integration: Future (Phase 3) ## Files Changed - src/storage/adapters/typeAwareStorageAdapter.ts (NEW, 649 lines) - src/storage/storageFactory.ts (integrated type-aware storage) - tests/unit/storage/typeAwareStorageAdapter.test.ts (NEW, 54 test cases) - Storage exploration docs (4 new reference docs) 🎯 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 13:06:23 -07:00
# Brainy Storage Adapter - Quick Reference Guide
## File Locations
```
src/storage/
├── baseStorageAdapter.ts # Abstract base class (1,156 lines)
├── baseStorage.ts # Implementation layer (1,098 lines)
├── storageFactory.ts # Factory for adapter selection
├── sharding.ts # UUID-based sharding utilities
├── cacheManager.ts # Cache implementation
└── adapters/
├── fileSystemStorage.ts # Node.js file system (2,677 lines)
├── memoryStorage.ts # In-memory storage (822 lines)
├── s3CompatibleStorage.ts # AWS S3 / R2 / GCS compat (5000+ lines)
├── gcsStorage.ts # Google Cloud Storage native (1,835 lines)
├── opfsStorage.ts # Browser OPFS storage
└── baseStorageAdapter.ts # Base class
src/coreTypes.ts
└── StorageAdapter interface (27 methods)
```
## Storage Adapter Hierarchy
```
┌─ StorageAdapter (interface)
│ ├─ StorageAdapter.init()
│ ├─ StorageAdapter.saveNoun()
│ ├─ StorageAdapter.getNouns()
│ └─ ... (23 more methods)
└─ BaseStorageAdapter (abstract class)
├─ Statistics management
├─ Throttling detection
├─ Count tracking (O(1))
├─ Service-level statistics
└─ Abstract methods for subclasses
└─ BaseStorage (abstract class)
├─ 2-file system routing
├─ Pagination support
├─ Metadata handling
├─ Public API (saveNoun, getNoun, etc.)
└─ Abstract internal methods
└─ Concrete Adapters
├─ FileSystemStorage
├─ MemoryStorage
├─ S3CompatibleStorage
├─ GcsStorage
└─ OPFSStorage
```
## Abstract Methods to Implement
When creating a new adapter, extend `BaseStorage` and implement:
### Noun/Verb Operations (6 methods)
```typescript
protected abstract saveNoun_internal(noun: HNSWNoun): Promise<void>
protected abstract getNoun_internal(id: string): Promise<HNSWNoun | null>
protected abstract deleteNoun_internal(id: string): Promise<void>
protected abstract saveVerb_internal(verb: HNSWVerb): Promise<void>
protected abstract getVerb_internal(id: string): Promise<HNSWVerb | null>
protected abstract deleteVerb_internal(id: string): Promise<void>
```
### Path Operations (4 methods)
```typescript
protected abstract writeObjectToPath(path: string, data: any): Promise<void>
protected abstract readObjectFromPath(path: string): Promise<any | null>
protected abstract deleteObjectFromPath(path: string): Promise<void>
protected abstract listObjectsUnderPath(prefix: string): Promise<string[]>
```
### Count Management (2 methods)
```typescript
protected abstract initializeCounts(): Promise<void>
protected abstract persistCounts(): Promise<void>
```
### Statistics (2 methods)
```typescript
protected abstract saveStatisticsData(statistics: StatisticsData): Promise<void>
protected abstract getStatisticsData(): Promise<StatisticsData | null>
```
### Lifecycle (3 methods)
```typescript
abstract init(): Promise<void>
abstract clear(): Promise<void>
abstract getStorageStatus(): Promise<StorageStatus>
```
**Total: 17 abstract methods to implement**
## Storage Path Structure
### Modern Entity-Based Structure
```
storage-root/
├── entities/
│ ├── nouns/vectors/{shard}/{id}.json ← Vector data
│ ├── nouns/metadata/{shard}/{id}.json ← Metadata
│ ├── nouns/hnsw/{shard}/{id}.json ← HNSW graph
│ ├── verbs/vectors/{shard}/{id}.json
│ ├── verbs/metadata/{shard}/{id}.json
│ └── verbs/hnsw/{shard}/{id}.json
├── indexes/
│ ├── metadata/... ← Search indexes
│ └── graph/...
└── _system/
├── statistics.json ← Aggregate stats
├── counts.json ← O(1) totals
└── hnsw-system.json ← HNSW metadata
```
### Shard Format
- First 2 hex chars of UUID (00-ff) = 256 shards
- Example: `ab123456-...` → stored in `ab/` directory
- Enables 2.5M+ entities with consistent performance
## 2-File System Design
### Vector File (always loaded with HNSW)
```json
{
"id": "ab123456-...",
"vector": [0.1, 0.2, ...],
"connections": { "0": [...], "1": [...] },
"level": 2
}
```
### Metadata File (loaded separately)
```json
{
"noun": "Person",
"name": "Alice",
"email": "alice@example.com",
"createdAt": "...",
"service": "user-service"
}
```
**Benefit:** Decouple vector operations from flexible metadata queries
## Existing Adapters Overview
### FileSystemStorage (Node.js)
- 2,677 lines
- Sharding with migration support
- File-based locking for multi-process
- Production-ready
### MemoryStorage (Testing)
- 822 lines
- In-memory Maps
- Fast for testing
- No persistence
### S3CompatibleStorage (Cloud)
- 5,000+ lines
- AWS S3, Cloudflare R2, GCS (via S3 API)
- Adaptive batching, request coalescing
- High-volume mode, write buffers
### GcsStorage (Google Cloud)
- 1,835 lines
- Native @google-cloud/storage SDK
- ADC, service account, HMAC auth
- Cache managers, backpressure
### OPFSStorage (Browser)
- Browser Origin Private File System
- Persistent across sessions
- Modern browsers only
## Factory Integration
```typescript
// src/storage/storageFactory.ts
const storage = await createStorage({
type: 'filesystem', // auto, memory, filesystem, s3, gcs, gcs-native, opfs
path: './data',
s3Storage: { bucketName, region, ... },
gcsStorage: { bucketName, credentials, ... },
})
```
## Adding TypeAwareStorageAdapter
### Recommended Approach: Direct Implementation
```typescript
// src/storage/adapters/typeAwareStorageAdapter.ts
export class TypeAwareStorageAdapter extends BaseStorage {
// Implement 17 abstract methods
// Add type indexing logic
// Track noun/verb types in separate indexes
}
```
### Integration Steps
1. Create `/src/storage/adapters/typeAwareStorageAdapter.ts`
2. Add to factory in `/src/storage/storageFactory.ts`
3. Update StorageOptions interface with `type: 'type-aware'`
4. No changes to Brainy.ts or existing adapters needed
## Key Features Inherited from BaseStorageAdapter
- **Statistics Caching:** Batches updates for efficiency
- **Throttling Detection:** Handles 429/503 errors
- **Count Management:** O(1) operations with persistence
- **Service Tracking:** Per-service statistics
- **Field Name Tracking:** Metadata field discovery
## Performance Characteristics
### O(1) Operations
- `getNounCount()` - total noun count
- `getVerbCount()` - total verb count
### O(n) Operations
- `getNouns()` - paginated listing (n = page size)
- `getVerbs()` - paginated listing
- `getNounsByNounType()` - filter by type
- `getVerbsBySource()` - filter by source
### Cloud Storage Features (GCS, S3)
- High-volume mode detection
- Adaptive batching
- Request coalescing for deduplication
- Write buffers for bulk operations
- Backpressure management
- Socket pool management
## Testing Storage Adapters
All adapters implement the same interface, so:
```typescript
// Test with MemoryStorage (fastest)
const storage = new MemoryStorage()
// Test with FileSystemStorage (persistent)
const storage = new FileSystemStorage('./test-data')
// All adapters support the same operations
await storage.init()
await storage.saveNoun(noun)
const result = await storage.getNoun(id)
await storage.clear()
```
## Brainy Integration
```typescript
export class Brainy {
private storage!: BaseStorage
async init(config: BrainyConfig): Promise<void> {
// Factory creates appropriate adapter
this.storage = await createStorage(config.storage) as BaseStorage
await this.storage.init()
// Pass to HNSW index
this.index = new HNSWIndex(this.storage, ...)
}
}
```
Brainy depends on `BaseStorage` interface, not specific adapters.
## Design Patterns Used
1. **Factory Pattern** - `createStorage()` selects adapter
2. **Strategy Pattern** - Adapters are interchangeable
3. **Template Method** - BaseStorage defines skeleton
4. **Decorator Pattern** - Can wrap adapters (e.g., TypeAware wrapper)
5. **Adapter Pattern** - Maps different storage backends to same interface
## Conclusion
TypeAwareStorageAdapter can be added as a **new adapter alongside existing ones** without:
- Modifying Brainy.ts
- Replacing existing adapters
- Breaking the StorageAdapter interface
- Changing how storage is used throughout the codebase
Simply extend `BaseStorage`, implement 17 abstract methods, and register in `storageFactory.ts`.