refactor: replace snapshot design with SQLite-inspired reader-writer lock approach

This commit is contained in:
Jeremy Tregunna 2025-04-19 23:45:19 -06:00
parent 68283a5fed
commit 5dbcc0d54e
Signed by: jer
GPG Key ID: 1278B36BA6F5D5E4
3 changed files with 23 additions and 20 deletions

View File

@ -23,13 +23,14 @@ Build a clean, composable, and educational storage engine in Go that follows Log
- Support reproducible startup states across restarts - Support reproducible startup states across restarts
### 4. Composable Primitives ### 4. Composable Primitives
- Design clean interfaces for fundamental operations (reads, writes, snapshots, iteration) - Design clean interfaces for fundamental operations (reads, writes, iteration, transactions)
- Enable building of higher-level abstractions (SQL, Gremlin, custom query languages) - Enable building of higher-level abstractions (SQL, Gremlin, custom query languages)
- Support both transactional and analytical workloads - Support both transactional and analytical workloads
- Provide simple atomic write primitives that can be built upon: - Provide simple atomic write primitives that can be built upon:
- Leverage read snapshots from immutable LSM structure - Leverage reader-writer lock for concurrency control (SQLite-inspired approach)
- Support basic atomic batch operations - Support basic atomic batch operations
- Ensure crash recovery through proper WAL handling - Ensure crash recovery through proper WAL handling
- Enable read operations during writes via WAL (following SQLite's concurrency model)
## Target Use Cases ## Target Use Cases

22
PLAN.md
View File

@ -37,8 +37,7 @@ go-storage/
│ │ └── footer/ # File footer and metadata │ │ └── footer/ # File footer and metadata
│ ├── compaction/ # Compaction strategies │ ├── compaction/ # Compaction strategies
│ ├── iterator/ # Merged iterator implementation │ ├── iterator/ # Merged iterator implementation
│ ├── transaction/ # Transaction management with Snapshot + WAL │ ├── transaction/ # Transaction management with WAL and locks
│ │ ├── snapshot/ # Read snapshot implementation
│ │ └── txbuffer/ # Transaction write buffer │ │ └── txbuffer/ # Transaction write buffer
│ └── engine/ # Main engine implementation with single-writer architecture │ └── engine/ # Main engine implementation with single-writer architecture
@ -98,9 +97,10 @@ go-storage/
### Phase F: Basic Atomicity and Advanced Features (2-3 weeks) ### Phase F: Basic Atomicity and Advanced Features (2-3 weeks)
1. Implement merged iterator across all levels 1. Implement merged iterator across all levels
2. Add snapshot capability for reads: 2. Implement SQLite-inspired reader-writer concurrency:
- Point-in-time view of the database - Reader-writer lock for basic isolation
- Consistent reads across MemTable and SSTables - WAL-based reads for active transactions
- Support for read operations during writes
3. Implement simple atomic batch operations: 3. Implement simple atomic batch operations:
- Support atomic multi-key writes - Support atomic multi-key writes
- Ensure proper crash recovery for batch operations - Ensure proper crash recovery for batch operations
@ -137,15 +137,17 @@ go-storage/
### Concurrency ### Concurrency
- Implement single-writer architecture for the main write path - Implement single-writer architecture for the main write path
- Allow concurrent readers (snapshots) to proceed without blocking - Allow concurrent readers through reader-writer lock mechanism
- Use appropriate synchronization for reader-writer coordination - Use SQLite-inspired WAL approach for reader-writer coordination:
- Ensure proper isolation between transactions - Writers write to WAL, readers can read from either main database or WAL
- Use appropriate synchronization with reader-writer lock
- Ensure proper isolation between transactions through lock-based exclusion
### Batch Operation Management ### Batch Operation Management
- Use WAL for atomic batch operation durability - Use WAL for atomic batch operation durability
- Leverage LSM's natural versioning for snapshots - Leverage reader-writer lock for transactional isolation
- Provide simple interfaces that can be built upon for transactions - Provide simple interfaces that can be built upon for transactions
- Ensure proper crash recovery for batch operations - Ensure proper crash recovery for batch operations through WAL replay
### Go Idioms ### Go Idioms
- Follow standard Go project layout - Follow standard Go project layout

16
TODO.md
View File

@ -43,12 +43,12 @@ This document outlines the implementation tasks for the Go Storage Engine, organ
- [x] Connect WAL replay to MemTable - [x] Connect WAL replay to MemTable
- [x] Create recovery logic to rebuild MemTable from WAL - [x] Create recovery logic to rebuild MemTable from WAL
- [x] Implement consistent snapshot reads during recovery - [x] Implement consistent state reconstruction during recovery
- [x] Handle errors during replay with appropriate fallbacks - [x] Handle errors during replay with appropriate fallbacks
- [x] Test concurrent read/write scenarios - [x] Test concurrent read/write scenarios
- [x] Verify reader isolation during writes - [x] Verify reader isolation during writes
- [x] Test snapshot consistency guarantees - [x] Test consistency guarantees with concurrent operations
- [x] Benchmark read/write performance under load - [x] Benchmark read/write performance under load
## Phase C: Persistent Storage ## Phase C: Persistent Storage
@ -121,11 +121,11 @@ This document outlines the implementation tasks for the Go Storage Engine, organ
- [x] Add efficient seeking capabilities - [x] Add efficient seeking capabilities
- [x] Implement proper cleanup for resources - [x] Implement proper cleanup for resources
- [ ] Add snapshot capability - [ ] Implement SQLite-inspired reader-writer concurrency
- [ ] Create point-in-time view mechanism - [ ] Add reader-writer lock for basic isolation
- [ ] Implement consistent reads across all data sources - [ ] Implement WAL-based reads during active write transactions
- [ ] Add resource tracking and cleanup - [ ] Design clean API for transaction handling
- [ ] Test isolation guarantees - [ ] Test concurrent read/write operations
- [ ] Implement atomic batch operations - [ ] Implement atomic batch operations
- [ ] Create batch data structure for multiple operations - [ ] Create batch data structure for multiple operations
@ -186,7 +186,7 @@ This document outlines the implementation tasks for the Go Storage Engine, organ
- [ ] `Delete(ctx context.Context, key []byte, opts ...WriteOption) error` - [ ] `Delete(ctx context.Context, key []byte, opts ...WriteOption) error`
- [ ] `Batch(ctx context.Context, ops []Operation, opts ...WriteOption) error` - [ ] `Batch(ctx context.Context, ops []Operation, opts ...WriteOption) error`
- [ ] `NewIterator(opts IteratorOptions) Iterator` - [ ] `NewIterator(opts IteratorOptions) Iterator`
- [ ] `Snapshot() Snapshot` - [ ] `BeginTransaction(readOnly bool) (Transaction, error)`
- [ ] `Close() error` - [ ] `Close() error`
- [ ] Implement error types - [ ] Implement error types