Some checks failed
Go Tests / Run Tests (1.24.2) (push) Failing after 5m4s
316 lines
8.4 KiB
Markdown
316 lines
8.4 KiB
Markdown
# Interfaces Package Documentation
|
|
|
|
The `interfaces` package defines the core contract between components in the Kevo engine's facade-based architecture. It provides clear, well-defined interfaces that enable modularity, testability, and separation of concerns.
|
|
|
|
## Overview
|
|
|
|
Interfaces are a crucial part of the engine's architecture, forming the boundaries between different subsystems. By defining clear interface contracts, the engine can achieve high cohesion within components and loose coupling between them.
|
|
|
|
Key responsibilities of the interfaces package include:
|
|
- Defining the Engine interface used by clients
|
|
- Specifying the contract for specialized managers (Storage, Transaction, Compaction)
|
|
- Establishing common patterns for component interaction
|
|
- Enabling dependency injection and testability
|
|
- Providing backward compatibility through interface contracts
|
|
|
|
## Core Interfaces
|
|
|
|
### Engine Interface
|
|
|
|
The `Engine` interface is the primary entry point for all client interactions:
|
|
|
|
```go
|
|
type Engine interface {
|
|
// Data operations
|
|
Put(key, value []byte) error
|
|
Get(key []byte) ([]byte, error)
|
|
Delete(key []byte) error
|
|
IsDeleted(key []byte) (bool, error)
|
|
|
|
// Iterator operations
|
|
GetIterator() (iterator.Iterator, error)
|
|
GetRangeIterator(startKey, endKey []byte) (iterator.Iterator, error)
|
|
|
|
// Transaction support
|
|
BeginTransaction(readOnly bool) (Transaction, error)
|
|
|
|
// Management operations
|
|
ApplyBatch(entries []*wal.Entry) error
|
|
FlushImMemTables() error
|
|
TriggerCompaction() error
|
|
CompactRange(startKey, endKey []byte) error
|
|
GetCompactionStats() (map[string]interface{}, error)
|
|
GetStats() map[string]interface{}
|
|
Close() error
|
|
}
|
|
```
|
|
|
|
This interface provides all core functionality expected of a storage engine.
|
|
|
|
### Manager Interfaces
|
|
|
|
The engine defines specialized manager interfaces for specific responsibilities:
|
|
|
|
#### StorageManager Interface
|
|
|
|
```go
|
|
type StorageManager interface {
|
|
// Data operations
|
|
Get(key []byte) ([]byte, error)
|
|
Put(key, value []byte) error
|
|
Delete(key []byte) error
|
|
IsDeleted(key []byte) (bool, error)
|
|
|
|
// Iterator operations
|
|
GetIterator() (iterator.Iterator, error)
|
|
GetRangeIterator(startKey, endKey []byte) (iterator.Iterator, error)
|
|
|
|
// Management operations
|
|
FlushMemTables() error
|
|
ApplyBatch(entries []*wal.Entry) error
|
|
Close() error
|
|
|
|
// Statistics
|
|
GetStorageStats() map[string]interface{}
|
|
}
|
|
```
|
|
|
|
Responsible for all data storage and retrieval operations.
|
|
|
|
#### TransactionManager Interface
|
|
|
|
```go
|
|
type TransactionManager interface {
|
|
// Transaction operations
|
|
BeginTransaction(readOnly bool) (Transaction, error)
|
|
|
|
// Statistics
|
|
GetTransactionStats() map[string]interface{}
|
|
}
|
|
```
|
|
|
|
Handles transaction creation and management.
|
|
|
|
#### CompactionManager Interface
|
|
|
|
```go
|
|
type CompactionManager interface {
|
|
// Compaction operations
|
|
TriggerCompaction() error
|
|
CompactRange(startKey, endKey []byte) error
|
|
|
|
// Lifecycle management
|
|
Start() error
|
|
Stop() error
|
|
|
|
// Tombstone tracking
|
|
TrackTombstone(key []byte)
|
|
|
|
// Statistics
|
|
GetCompactionStats() map[string]interface{}
|
|
}
|
|
```
|
|
|
|
Manages background compaction processes.
|
|
|
|
### Transaction Interfaces
|
|
|
|
The transaction system defines its own set of interfaces:
|
|
|
|
#### Transaction Interface
|
|
|
|
```go
|
|
type Transaction interface {
|
|
// Data operations
|
|
Get(key []byte) ([]byte, error)
|
|
Put(key, value []byte) error
|
|
Delete(key []byte) error
|
|
|
|
// Iterator operations
|
|
NewIterator() iterator.Iterator
|
|
NewRangeIterator(startKey, endKey []byte) iterator.Iterator
|
|
|
|
// Transaction control
|
|
Commit() error
|
|
Rollback() error
|
|
|
|
// Status check
|
|
IsReadOnly() bool
|
|
}
|
|
```
|
|
|
|
Represents an active transaction with data operations and lifecycle methods.
|
|
|
|
## Interface Implementation
|
|
|
|
### Implementation Strategies
|
|
|
|
The package defines interfaces that are implemented by concrete types in their respective packages:
|
|
|
|
1. **Facade Pattern**:
|
|
- The `EngineFacade` implements the `Engine` interface
|
|
- Provides a simplified interface to complex subsystems
|
|
|
|
2. **Manager Pattern**:
|
|
- Specialized managers handle their respective areas of concern
|
|
- Each implements the appropriate manager interface
|
|
- Clear separation of responsibilities
|
|
|
|
3. **Backward Compatibility**:
|
|
- Type aliasing connects the new interfaces to legacy code
|
|
- Adapters bridge between legacy systems and new components
|
|
|
|
### Dependency Injection
|
|
|
|
The interfaces enable clean dependency injection:
|
|
|
|
```go
|
|
// The EngineFacade depends on interface contracts, not concrete implementations
|
|
type EngineFacade struct {
|
|
storage interfaces.StorageManager
|
|
txManager interfaces.TransactionManager
|
|
compaction interfaces.CompactionManager
|
|
// Other fields...
|
|
}
|
|
```
|
|
|
|
This makes components replaceable and testable in isolation.
|
|
|
|
## Interface Evolution
|
|
|
|
### Versioning Strategy
|
|
|
|
The interfaces package follows a careful versioning strategy:
|
|
|
|
1. **Interface Stability**:
|
|
- Interface contracts should remain stable
|
|
- Additions are allowed, but existing methods shouldn't change
|
|
|
|
2. **Backward Compatibility**:
|
|
- New methods can be added to interfaces
|
|
- Legacy systems can adapt to new interfaces via composition or wrapper types
|
|
|
|
3. **Type Aliasing**:
|
|
- Uses Go's type aliasing for smooth transitions
|
|
- For example: `type Engine = EngineFacade`
|
|
|
|
### Interface Design Principles
|
|
|
|
The interfaces follow several design principles:
|
|
|
|
1. **Single Responsibility**:
|
|
- Each interface has a specific area of concern
|
|
- Avoids bloated interfaces with mixed responsibilities
|
|
|
|
2. **Interface Segregation**:
|
|
- Clients only depend on methods they actually use
|
|
- Smaller, specialized interfaces
|
|
|
|
3. **Composition**:
|
|
- Interfaces can be composed of other interfaces
|
|
- Creates a hierarchy of capabilities
|
|
|
|
## Testing Support
|
|
|
|
The interface-based design enables easier testing:
|
|
|
|
1. **Mock Implementations**:
|
|
- Interfaces can be mocked for unit testing
|
|
- Tests can verify interactions with dependencies
|
|
|
|
2. **Stub Components**:
|
|
- Simplified implementations for testing specific behaviors
|
|
- Reduces test complexity
|
|
|
|
3. **Testable Design**:
|
|
- Clear boundaries make integration testing more targeted
|
|
- Each component can be tested in isolation
|
|
|
|
## Common Usage Patterns
|
|
|
|
### Client Usage
|
|
|
|
Clients interact with the engine through the Engine interface:
|
|
|
|
```go
|
|
// Create the engine
|
|
eng, err := engine.NewEngineFacade(dbPath)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer eng.Close()
|
|
|
|
// Use the interface methods
|
|
err = eng.Put([]byte("key"), []byte("value"))
|
|
value, err := eng.Get([]byte("key"))
|
|
```
|
|
|
|
The interface hides the implementation details.
|
|
|
|
### Component Integration
|
|
|
|
Components integrate with each other through interfaces:
|
|
|
|
```go
|
|
// Transaction manager depends on storage manager
|
|
func NewManager(storage interfaces.StorageManager, stats stats.Collector) interfaces.TransactionManager {
|
|
return &Manager{
|
|
storage: storage,
|
|
stats: stats,
|
|
}
|
|
}
|
|
```
|
|
|
|
This enables loose coupling between components.
|
|
|
|
### Extending Functionality
|
|
|
|
New functionality can be added by expanding interfaces or adding adapters:
|
|
|
|
```go
|
|
// Add a new capability through composition
|
|
type ExtendedEngine interface {
|
|
interfaces.Engine
|
|
|
|
// New methods
|
|
GetStatistics() Statistics
|
|
ApplySnapshot(snapshot []byte) error
|
|
}
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### Interface Design
|
|
|
|
When working with the interfaces package:
|
|
|
|
1. **Keep Interfaces Minimal**:
|
|
- Only include methods that are essential for the interface contract
|
|
- Avoid bloating interfaces with methods used only by a subset of clients
|
|
|
|
2. **Interface Cohesion**:
|
|
- Methods in an interface should relate to a single responsibility
|
|
- Prefer multiple small interfaces over single large ones
|
|
|
|
3. **Naming Conventions**:
|
|
- Interface names should describe behavior, not implementation
|
|
- Use method names that clearly communicate the action
|
|
|
|
### Implementing Interfaces
|
|
|
|
When implementing interfaces:
|
|
|
|
1. **Verify Implementation**:
|
|
- Use Go's compile-time verification of interface implementation:
|
|
```go
|
|
var _ interfaces.Engine = (*EngineFacade)(nil)
|
|
```
|
|
|
|
2. **Document interface contracts**:
|
|
- Document performance expectations
|
|
- Document threading and concurrency guarantees
|
|
- Document error conditions and behaviors
|
|
|
|
3. **Consistent Error Handling**:
|
|
- Use consistent error types across implementations
|
|
- Document which errors can be returned by each method |