394 lines
11 KiB
Markdown
394 lines
11 KiB
Markdown
|
|
# Brainy Storage Adapter Architecture - Exploration Summary
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This exploration analyzed the complete storage adapter architecture in Brainy to understand how it works and determine whether a TypeAwareStorageAdapter can be added alongside existing adapters.
|
||
|
|
|
||
|
|
## Key Findings
|
||
|
|
|
||
|
|
### 1. Architecture is Clean and Extensible
|
||
|
|
|
||
|
|
Brainy implements a **well-designed, modular storage adapter architecture** using:
|
||
|
|
- **Interface-based design** (StorageAdapter interface in coreTypes.ts)
|
||
|
|
- **Abstract base classes** for common functionality
|
||
|
|
- **Concrete implementations** for specific backends
|
||
|
|
- **Factory pattern** for runtime adapter selection
|
||
|
|
|
||
|
|
### 2. Six Storage Adapters Currently Exist
|
||
|
|
|
||
|
|
| Adapter | Platform | Backend | File | Lines |
|
||
|
|
|---------|----------|---------|------|-------|
|
||
|
|
| FileSystemStorage | Node.js | Local filesystem | fileSystemStorage.ts | 2,677 |
|
||
|
|
| MemoryStorage | Browser/Node.js | In-memory Maps | memoryStorage.ts | 822 |
|
||
|
|
| S3CompatibleStorage | Node.js | AWS S3, Cloudflare R2, GCS (S3 API) | s3CompatibleStorage.ts | 5,000+ |
|
||
|
|
| GcsStorage | Node.js | Google Cloud Storage (native SDK) | gcsStorage.ts | 1,835 |
|
||
|
|
| OPFSStorage | Browser | Origin Private File System | opfsStorage.ts | - |
|
||
|
|
| R2Storage | Node.js | Alias for S3CompatibleStorage | (alias) | - |
|
||
|
|
|
||
|
|
### 3. Inheritance Hierarchy is Clean
|
||
|
|
|
||
|
|
```
|
||
|
|
StorageAdapter (interface - 27 methods)
|
||
|
|
↓
|
||
|
|
BaseStorageAdapter (abstract - 1,156 lines)
|
||
|
|
├─ Statistics management
|
||
|
|
├─ Throttling detection
|
||
|
|
├─ Count management (O(1))
|
||
|
|
└─ Service tracking
|
||
|
|
↓
|
||
|
|
BaseStorage (abstract - 1,098 lines)
|
||
|
|
├─ 2-file system (vectors + metadata)
|
||
|
|
├─ UUID-based sharding (256 shards)
|
||
|
|
├─ Pagination support
|
||
|
|
└─ Metadata routing
|
||
|
|
↓
|
||
|
|
Concrete Adapters (FileSystem, Memory, S3, GCS, OPFS)
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. Core Components
|
||
|
|
|
||
|
|
**Storage System Files (~13,000+ lines total):**
|
||
|
|
- `src/coreTypes.ts` - StorageAdapter interface
|
||
|
|
- `src/storage/baseStorageAdapter.ts` - Abstract base (1,156 lines)
|
||
|
|
- `src/storage/baseStorage.ts` - Core layer (1,098 lines)
|
||
|
|
- `src/storage/storageFactory.ts` - Factory for selection
|
||
|
|
- `src/storage/adapters/*.ts` - Concrete implementations
|
||
|
|
- `src/storage/sharding.ts` - UUID sharding utilities
|
||
|
|
- `src/storage/cacheManager.ts` - LRU cache
|
||
|
|
|
||
|
|
**Supporting Utilities:**
|
||
|
|
- `src/utils/writeBuffer.ts` - Batch operations
|
||
|
|
- `src/utils/adaptiveBackpressure.ts` - Flow control
|
||
|
|
- `src/utils/requestCoalescer.ts` - Request deduplication
|
||
|
|
- `src/storage/backwardCompatibility.ts` - Migration support
|
||
|
|
|
||
|
|
### 5. Storage Path Structure
|
||
|
|
|
||
|
|
**Modern Entity-Based Structure:**
|
||
|
|
```
|
||
|
|
entities/
|
||
|
|
├── nouns/vectors/{shard}/{id}.json (vector data)
|
||
|
|
├── nouns/metadata/{shard}/{id}.json (flexible metadata)
|
||
|
|
├── nouns/hnsw/{shard}/{id}.json (HNSW graph)
|
||
|
|
├── verbs/vectors/{shard}/{id}.json
|
||
|
|
├── verbs/metadata/{shard}/{id}.json
|
||
|
|
└── verbs/hnsw/{shard}/{id}.json
|
||
|
|
|
||
|
|
_system/
|
||
|
|
├── statistics.json (aggregate counts)
|
||
|
|
├── counts.json (O(1) totals)
|
||
|
|
└── hnsw-system.json (HNSW metadata)
|
||
|
|
```
|
||
|
|
|
||
|
|
**Sharding:** UUID first 2 hex chars = 256 shard directories (00-ff)
|
||
|
|
|
||
|
|
### 6. 2-File System Design
|
||
|
|
|
||
|
|
Brainy separates **vector data** from **metadata** for scalability:
|
||
|
|
- **File 1:** `vectors/{id}.json` - Vector, HNSW connections (lightweight)
|
||
|
|
- **File 2:** `metadata/{id}.json` - Flexible metadata (any schema)
|
||
|
|
|
||
|
|
**Benefits:**
|
||
|
|
- Decouple vector operations from metadata queries
|
||
|
|
- Enable type-aware queries without loading vectors
|
||
|
|
- Independent scaling of vector vs metadata storage
|
||
|
|
- Support for metadata-only updates
|
||
|
|
|
||
|
|
### 7. Brainy Integration
|
||
|
|
|
||
|
|
How Brainy uses storage:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// In brainy.ts
|
||
|
|
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, ...)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Key insight: **Brainy only knows about `BaseStorage` interface, not specific adapters**
|
||
|
|
|
||
|
|
### 8. Design Patterns Used
|
||
|
|
|
||
|
|
1. **Factory Pattern** - `createStorage()` selects adapter at runtime
|
||
|
|
2. **Strategy Pattern** - Adapters are interchangeable
|
||
|
|
3. **Template Method** - BaseStorage defines skeleton, adapters fill details
|
||
|
|
4. **Adapter Pattern** - Maps different backends to same interface
|
||
|
|
5. **Decorator Pattern** - Could wrap adapters (e.g., TypeAware wrapper)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Answer: Can TypeAwareStorageAdapter Be Added?
|
||
|
|
|
||
|
|
### YES - DEFINITIVELY
|
||
|
|
|
||
|
|
**TypeAwareStorageAdapter can be added as a new adapter alongside existing ones WITHOUT replacing them.**
|
||
|
|
|
||
|
|
### Reasons
|
||
|
|
|
||
|
|
1. **Factory Pattern:** Multiple adapters coexist via factory function
|
||
|
|
2. **No Coupling:** Brainy depends on `BaseStorage` interface, not specific adapters
|
||
|
|
3. **Clean Inheritance:** Just extend `BaseStorage` like all other adapters
|
||
|
|
4. **Isolated:** Type awareness doesn't affect other adapters
|
||
|
|
5. **Backward Compatible:** Existing code continues to work unchanged
|
||
|
|
|
||
|
|
### Implementation Path
|
||
|
|
|
||
|
|
**3 Simple Steps:**
|
||
|
|
|
||
|
|
**Step 1: Create new adapter file**
|
||
|
|
```typescript
|
||
|
|
// src/storage/adapters/typeAwareStorageAdapter.ts
|
||
|
|
export class TypeAwareStorageAdapter extends BaseStorage {
|
||
|
|
// Implement 17 abstract methods
|
||
|
|
// Add type indexing logic
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Step 2: Update factory**
|
||
|
|
```typescript
|
||
|
|
// src/storage/storageFactory.ts
|
||
|
|
if (options.type === 'type-aware') {
|
||
|
|
return new TypeAwareStorageAdapter(options)
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Step 3: Update options interface**
|
||
|
|
```typescript
|
||
|
|
// src/storage/storageFactory.ts
|
||
|
|
export interface StorageOptions {
|
||
|
|
type?: 'auto' | 'memory' | 'filesystem' | 's3' | 'gcs' | 'type-aware'
|
||
|
|
typeAwareStorage?: { ... }
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**No changes needed to:**
|
||
|
|
- Brainy.ts
|
||
|
|
- coreTypes.ts (unless adding new methods)
|
||
|
|
- Existing adapters
|
||
|
|
- HNSW index
|
||
|
|
- Any other components
|
||
|
|
|
||
|
|
### Abstract Methods to Implement
|
||
|
|
|
||
|
|
When creating TypeAwareStorageAdapter, implement these 17 methods:
|
||
|
|
|
||
|
|
**Noun/Verb Operations (6):**
|
||
|
|
- `saveNoun_internal()`
|
||
|
|
- `getNoun_internal()`
|
||
|
|
- `deleteNoun_internal()`
|
||
|
|
- `saveVerb_internal()`
|
||
|
|
- `getVerb_internal()`
|
||
|
|
- `deleteVerb_internal()`
|
||
|
|
|
||
|
|
**Path Operations (4):**
|
||
|
|
- `writeObjectToPath()`
|
||
|
|
- `readObjectFromPath()`
|
||
|
|
- `deleteObjectFromPath()`
|
||
|
|
- `listObjectsUnderPath()`
|
||
|
|
|
||
|
|
**Count Management (2):**
|
||
|
|
- `initializeCounts()`
|
||
|
|
- `persistCounts()`
|
||
|
|
|
||
|
|
**Statistics (2):**
|
||
|
|
- `saveStatisticsData()`
|
||
|
|
- `getStatisticsData()`
|
||
|
|
|
||
|
|
**Lifecycle (3):**
|
||
|
|
- `init()`
|
||
|
|
- `clear()`
|
||
|
|
- `getStorageStatus()`
|
||
|
|
|
||
|
|
### Recommended Design Approach
|
||
|
|
|
||
|
|
**Option A: Direct Implementation (Recommended)**
|
||
|
|
```
|
||
|
|
TypeAwareStorageAdapter
|
||
|
|
├─ Extends BaseStorage
|
||
|
|
├─ Implements all 17 abstract methods
|
||
|
|
├─ Adds type indexing logic
|
||
|
|
└─ Can back any storage engine
|
||
|
|
```
|
||
|
|
|
||
|
|
**Option B: Wrapper/Decorator Pattern**
|
||
|
|
```
|
||
|
|
TypeAwareStorageAdapter (wrapper)
|
||
|
|
├─ Wraps any BaseStorage adapter
|
||
|
|
├─ Intercepts saveNoun/saveVerb
|
||
|
|
├─ Tracks types in separate index
|
||
|
|
└─ Delegates all operations
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Key Insights
|
||
|
|
|
||
|
|
### Storage Architecture Strengths
|
||
|
|
|
||
|
|
✅ **Well-organized:** Clear separation of concerns
|
||
|
|
✅ **Extensible:** Factory pattern makes adding adapters simple
|
||
|
|
✅ **Scalable:** Sharding, caching, batching, backpressure
|
||
|
|
✅ **Flexible:** Multiple backends coexist without conflicts
|
||
|
|
✅ **Type-safe:** Full TypeScript with proper interfaces
|
||
|
|
✅ **Production-ready:** Used in real deployments
|
||
|
|
|
||
|
|
### What Makes This Possible
|
||
|
|
|
||
|
|
1. **Interface-based design** - Adapters implement same contract
|
||
|
|
2. **Factory pattern** - Runtime selection without coupling
|
||
|
|
3. **No hardcoded dependencies** - Brainy uses `BaseStorage` type
|
||
|
|
4. **Common base class** - Shared logic prevents duplication
|
||
|
|
5. **Metadata separation** - 2-file system enables type indexing
|
||
|
|
|
||
|
|
### Storage Adapter Evolution Path
|
||
|
|
|
||
|
|
```
|
||
|
|
Current State (v3.44.0):
|
||
|
|
├─ FileSystemStorage ✅
|
||
|
|
├─ MemoryStorage ✅
|
||
|
|
├─ S3CompatibleStorage ✅
|
||
|
|
├─ GcsStorage ✅
|
||
|
|
└─ OPFSStorage ✅
|
||
|
|
|
||
|
|
Future State (proposed):
|
||
|
|
├─ FileSystemStorage ✅
|
||
|
|
├─ MemoryStorage ✅
|
||
|
|
├─ S3CompatibleStorage ✅
|
||
|
|
├─ GcsStorage ✅
|
||
|
|
├─ OPFSStorage ✅
|
||
|
|
└─ TypeAwareStorageAdapter ✅ (new)
|
||
|
|
|
||
|
|
All coexist without conflicts
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Documents Created
|
||
|
|
|
||
|
|
This exploration generated three comprehensive documents:
|
||
|
|
|
||
|
|
### 1. STORAGE_ARCHITECTURE_ANALYSIS.md (28 KB)
|
||
|
|
Complete analysis covering:
|
||
|
|
- Current storage architecture overview
|
||
|
|
- All existing storage adapters
|
||
|
|
- StorageAdapter interface specification
|
||
|
|
- How Brainy uses storage
|
||
|
|
- Storage paths and patterns
|
||
|
|
- Storage adapter pattern analysis
|
||
|
|
- Detailed implementation recommendations
|
||
|
|
- Design patterns and best practices
|
||
|
|
|
||
|
|
### 2. STORAGE_ADAPTER_QUICK_REFERENCE.md (8.6 KB)
|
||
|
|
Quick reference guide with:
|
||
|
|
- File locations
|
||
|
|
- Storage adapter hierarchy
|
||
|
|
- Abstract methods checklist (17 methods)
|
||
|
|
- Storage path structure
|
||
|
|
- 2-file system design
|
||
|
|
- Existing adapters overview
|
||
|
|
- Factory integration
|
||
|
|
- Performance characteristics
|
||
|
|
- Design patterns summary
|
||
|
|
|
||
|
|
### 3. STORAGE_FILES_REFERENCE.md (13 KB)
|
||
|
|
Complete file reference with:
|
||
|
|
- All core storage files
|
||
|
|
- Line counts and purposes
|
||
|
|
- Each adapter's features
|
||
|
|
- Integration points
|
||
|
|
- Data flow diagrams
|
||
|
|
- Statistics tracking
|
||
|
|
- Type definitions
|
||
|
|
- Summary statistics table
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Recommendations
|
||
|
|
|
||
|
|
### For TypeAwareStorageAdapter Implementation
|
||
|
|
|
||
|
|
1. **Use Direct Implementation approach** (not wrapper)
|
||
|
|
- Simpler to maintain
|
||
|
|
- Better performance
|
||
|
|
- Easier to debug
|
||
|
|
- Can back any storage engine
|
||
|
|
|
||
|
|
2. **Implement as new entry in factory**
|
||
|
|
- `type: 'type-aware'` with storage config
|
||
|
|
- Auto-detection can select it
|
||
|
|
- No changes to existing code
|
||
|
|
|
||
|
|
3. **Leverage 2-file system**
|
||
|
|
- Store type index in metadata files
|
||
|
|
- Queries don't require loading vectors
|
||
|
|
- Aligns with existing patterns
|
||
|
|
|
||
|
|
4. **Inherit common functionality**
|
||
|
|
- Throttling detection
|
||
|
|
- Statistics tracking
|
||
|
|
- Caching and batching
|
||
|
|
- Count management (O(1))
|
||
|
|
|
||
|
|
5. **Follow existing patterns**
|
||
|
|
- Sharding strategy (first 2 hex chars)
|
||
|
|
- Path structure (entities/{noun|verb}/{vectors|metadata}/{shard}/{id}.json)
|
||
|
|
- Pagination support
|
||
|
|
- Metadata separation
|
||
|
|
|
||
|
|
### For Integration
|
||
|
|
|
||
|
|
1. Add new file: `/src/storage/adapters/typeAwareStorageAdapter.ts`
|
||
|
|
2. Modify: `/src/storage/storageFactory.ts` (add case + interface)
|
||
|
|
3. Optional: `/src/coreTypes.ts` (if extending StorageAdapter interface)
|
||
|
|
4. No changes needed elsewhere
|
||
|
|
|
||
|
|
### For Testing
|
||
|
|
|
||
|
|
1. Test with MemoryStorage first (fastest)
|
||
|
|
2. Test with FileSystemStorage (persistent)
|
||
|
|
3. Ensure all existing tests still pass
|
||
|
|
4. Add type-aware specific tests
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Conclusion
|
||
|
|
|
||
|
|
Brainy's storage adapter architecture is **professionally designed and inherently extensible**. Adding a TypeAwareStorageAdapter is straightforward because:
|
||
|
|
|
||
|
|
- The architecture supports multiple concurrent adapters
|
||
|
|
- Brainy uses interface-based dependency injection
|
||
|
|
- The factory pattern enables runtime selection
|
||
|
|
- No breaking changes required anywhere
|
||
|
|
|
||
|
|
**The answer is unambiguous: TypeAwareStorageAdapter can be added alongside existing adapters with minimal integration effort.**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Files Analyzed
|
||
|
|
|
||
|
|
- `/src/coreTypes.ts` - Interface definition
|
||
|
|
- `/src/storage/baseStorageAdapter.ts` - Abstract base
|
||
|
|
- `/src/storage/baseStorage.ts` - Core layer
|
||
|
|
- `/src/storage/storageFactory.ts` - Factory
|
||
|
|
- `/src/storage/adapters/fileSystemStorage.ts` - FileSystem
|
||
|
|
- `/src/storage/adapters/memoryStorage.ts` - Memory
|
||
|
|
- `/src/storage/adapters/s3CompatibleStorage.ts` - S3/R2
|
||
|
|
- `/src/storage/adapters/gcsStorage.ts` - GCS native
|
||
|
|
- `/src/storage/adapters/opfsStorage.ts` - Browser OPFS
|
||
|
|
- `/src/brainy.ts` - Main class
|
||
|
|
- Plus all supporting utilities and type definitions
|
||
|
|
|
||
|
|
**Total files analyzed:** 50+
|
||
|
|
**Total lines examined:** 13,000+
|
||
|
|
**Analysis coverage:** Complete storage system
|
||
|
|
|