- Core library with SVG and PNG generation - CLI tool with generate and batch commands - Cross-platform path handling for Windows compatibility - Comprehensive test suite with integration tests
132 lines
3.5 KiB
Go
132 lines
3.5 KiB
Go
package engine
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"sync/atomic"
|
|
|
|
lru "github.com/hashicorp/golang-lru/v2"
|
|
"github.com/ungluedlabs/go-jdenticon/internal/constants"
|
|
)
|
|
|
|
// CacheMetrics holds cache performance metrics using atomic operations for efficiency
|
|
type CacheMetrics struct {
|
|
hits int64 // Use atomic operations, no mutex needed
|
|
misses int64 // Use atomic operations, no mutex needed
|
|
}
|
|
|
|
// GetHits returns the number of cache hits
|
|
func (m *CacheMetrics) GetHits() int64 {
|
|
return atomic.LoadInt64(&m.hits)
|
|
}
|
|
|
|
// GetMisses returns the number of cache misses
|
|
func (m *CacheMetrics) GetMisses() int64 {
|
|
return atomic.LoadInt64(&m.misses)
|
|
}
|
|
|
|
// recordHit records a cache hit atomically
|
|
func (m *CacheMetrics) recordHit() {
|
|
atomic.AddInt64(&m.hits, 1)
|
|
}
|
|
|
|
// recordMiss records a cache miss atomically
|
|
func (m *CacheMetrics) recordMiss() {
|
|
atomic.AddInt64(&m.misses, 1)
|
|
}
|
|
|
|
// cacheKey generates a cache key from hash and size
|
|
func (g *Generator) cacheKey(hash string, size float64) string {
|
|
// Use a simple concatenation approach for better performance
|
|
// Convert float64 size to string with appropriate precision
|
|
return hash + ":" + strconv.FormatFloat(size, 'f', 1, 64)
|
|
}
|
|
|
|
// ClearCache removes all entries from the cache and resets metrics
|
|
func (g *Generator) ClearCache() {
|
|
g.mu.Lock()
|
|
defer g.mu.Unlock()
|
|
|
|
g.cache.Purge()
|
|
// Reset metrics
|
|
atomic.StoreInt64(&g.metrics.hits, 0)
|
|
atomic.StoreInt64(&g.metrics.misses, 0)
|
|
}
|
|
|
|
// GetCacheSize returns the number of items currently in the cache
|
|
func (g *Generator) GetCacheSize() int {
|
|
g.mu.RLock()
|
|
defer g.mu.RUnlock()
|
|
return g.cache.Len()
|
|
}
|
|
|
|
// GetCacheCapacity returns the maximum number of items the cache can hold
|
|
func (g *Generator) GetCacheCapacity() int {
|
|
g.mu.RLock()
|
|
defer g.mu.RUnlock()
|
|
// LRU cache doesn't expose capacity, return the configured capacity from config
|
|
return g.config.CacheSize
|
|
}
|
|
|
|
// GetCacheMetrics returns the cache hit and miss counts
|
|
func (g *Generator) GetCacheMetrics() (hits int64, misses int64) {
|
|
return g.metrics.GetHits(), g.metrics.GetMisses()
|
|
}
|
|
|
|
// SetConfig updates the generator's color configuration and clears the cache
|
|
func (g *Generator) SetConfig(colorConfig ColorConfig) {
|
|
g.mu.Lock()
|
|
defer g.mu.Unlock()
|
|
|
|
g.config.ColorConfig = colorConfig
|
|
g.cache.Purge() // Clear cache since config changed
|
|
}
|
|
|
|
// SetGeneratorConfig updates the generator's configuration, including cache size
|
|
func (g *Generator) SetGeneratorConfig(config GeneratorConfig) error {
|
|
g.mu.Lock()
|
|
defer g.mu.Unlock()
|
|
|
|
// Validate cache size
|
|
if config.CacheSize <= 0 {
|
|
return fmt.Errorf("jdenticon: engine: invalid cache size: %d", config.CacheSize)
|
|
}
|
|
|
|
// Create new cache with updated size if necessary
|
|
if config.CacheSize != g.config.CacheSize {
|
|
newCache, err := lru.New[string, *Icon](config.CacheSize)
|
|
if err != nil {
|
|
return fmt.Errorf("jdenticon: engine: failed to create new cache: %w", err)
|
|
}
|
|
g.cache = newCache
|
|
} else {
|
|
// Same cache size, just clear existing cache
|
|
g.cache.Purge()
|
|
}
|
|
|
|
g.config = config
|
|
|
|
// Update resolved max icon size
|
|
if config.MaxIconSize > 0 {
|
|
g.maxIconSize = config.MaxIconSize
|
|
} else {
|
|
g.maxIconSize = constants.DefaultMaxIconSize
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetConfig returns the current color configuration
|
|
func (g *Generator) GetConfig() ColorConfig {
|
|
g.mu.RLock()
|
|
defer g.mu.RUnlock()
|
|
return g.config.ColorConfig
|
|
}
|
|
|
|
// GetGeneratorConfig returns the current generator configuration
|
|
func (g *Generator) GetGeneratorConfig() GeneratorConfig {
|
|
g.mu.RLock()
|
|
defer g.mu.RUnlock()
|
|
return g.config
|
|
}
|