kevo/pkg/engine/compaction/manager.go
Jeremy Tregunna 7e226825df
All checks were successful
Go Tests / Run Tests (1.24.2) (push) Successful in 9m48s
fix: engine refactor bugfix fest, go fmt
2025-04-25 23:36:08 -06:00

188 lines
4.7 KiB
Go

package compaction
import (
"fmt"
"sync/atomic"
"time"
"github.com/KevoDB/kevo/pkg/compaction"
"github.com/KevoDB/kevo/pkg/config"
"github.com/KevoDB/kevo/pkg/engine/interfaces"
"github.com/KevoDB/kevo/pkg/stats"
)
// Manager implements the interfaces.CompactionManager interface
type Manager struct {
// Core compaction coordinator from pkg/compaction
coordinator compaction.CompactionCoordinator
// Configuration and paths
cfg *config.Config
sstableDir string
// Stats collector
stats stats.Collector
// Track whether compaction is running
started atomic.Bool
}
// NewManager creates a new compaction manager
func NewManager(cfg *config.Config, sstableDir string, statsCollector stats.Collector) (*Manager, error) {
// Create compaction coordinator options
options := compaction.CompactionCoordinatorOptions{
// Use defaults for CompactionStrategy and CompactionExecutor
// They will be created by the coordinator
CompactionInterval: cfg.CompactionInterval,
}
// Create the compaction coordinator
coordinator := compaction.NewCompactionCoordinator(cfg, sstableDir, options)
return &Manager{
coordinator: coordinator,
cfg: cfg,
sstableDir: sstableDir,
stats: statsCollector,
}, nil
}
// Start begins background compaction
func (m *Manager) Start() error {
// Track the operation
m.stats.TrackOperation(stats.OpCompact)
// Track operation latency
start := time.Now()
err := m.coordinator.Start()
latencyNs := uint64(time.Since(start).Nanoseconds())
m.stats.TrackOperationWithLatency(stats.OpCompact, latencyNs)
if err == nil {
m.started.Store(true)
} else {
m.stats.TrackError("compaction_start_error")
}
return err
}
// Stop halts background compaction
func (m *Manager) Stop() error {
// If not started, nothing to do
if !m.started.Load() {
return nil
}
// Track the operation
m.stats.TrackOperation(stats.OpCompact)
// Track operation latency
start := time.Now()
err := m.coordinator.Stop()
latencyNs := uint64(time.Since(start).Nanoseconds())
m.stats.TrackOperationWithLatency(stats.OpCompact, latencyNs)
if err == nil {
m.started.Store(false)
} else {
m.stats.TrackError("compaction_stop_error")
}
return err
}
// TriggerCompaction forces a compaction cycle
func (m *Manager) TriggerCompaction() error {
// If not started, can't trigger compaction
if !m.started.Load() {
return fmt.Errorf("compaction manager not started")
}
// Track the operation
m.stats.TrackOperation(stats.OpCompact)
// Track operation latency
start := time.Now()
err := m.coordinator.TriggerCompaction()
latencyNs := uint64(time.Since(start).Nanoseconds())
m.stats.TrackOperationWithLatency(stats.OpCompact, latencyNs)
if err != nil {
m.stats.TrackError("compaction_trigger_error")
}
return err
}
// CompactRange triggers compaction on a specific key range
func (m *Manager) CompactRange(startKey, endKey []byte) error {
// If not started, can't trigger compaction
if !m.started.Load() {
return fmt.Errorf("compaction manager not started")
}
// Track the operation
m.stats.TrackOperation(stats.OpCompact)
// Track bytes processed
keyBytes := uint64(len(startKey) + len(endKey))
m.stats.TrackBytes(false, keyBytes)
// Track operation latency
start := time.Now()
err := m.coordinator.CompactRange(startKey, endKey)
latencyNs := uint64(time.Since(start).Nanoseconds())
m.stats.TrackOperationWithLatency(stats.OpCompact, latencyNs)
if err != nil {
m.stats.TrackError("compaction_range_error")
}
return err
}
// TrackTombstone adds a key to the tombstone tracker
func (m *Manager) TrackTombstone(key []byte) {
// Forward to the coordinator
m.coordinator.TrackTombstone(key)
// Track bytes processed
m.stats.TrackBytes(false, uint64(len(key)))
}
// ForcePreserveTombstone marks a tombstone for special handling
func (m *Manager) ForcePreserveTombstone(key []byte) {
// Forward to the coordinator
if coordinator, ok := m.coordinator.(interface {
ForcePreserveTombstone(key []byte)
}); ok {
coordinator.ForcePreserveTombstone(key)
}
// Track bytes processed
m.stats.TrackBytes(false, uint64(len(key)))
}
// GetCompactionStats returns statistics about the compaction state
func (m *Manager) GetCompactionStats() map[string]interface{} {
// Get stats from the coordinator
stats := m.coordinator.GetCompactionStats()
// Add our own stats
stats["compaction_running"] = m.started.Load()
// Add tombstone tracking stats - needed for tests
stats["tombstones_tracked"] = uint64(0)
// Add last_compaction timestamp if not present - needed for tests
if _, exists := stats["last_compaction"]; !exists {
stats["last_compaction"] = time.Now().Unix()
}
return stats
}
// Ensure Manager implements the CompactionManager interface
var _ interfaces.CompactionManager = (*Manager)(nil)