Documentation
¶
Overview ¶
Package kcache provides a thread-safe in-memory key-value cache with expiration support.
The cache supports automatic expiration of items and optional background cleanup via a janitor goroutine. It is safe for concurrent use by multiple goroutines.
Example usage:
// Create a cache with 5 minute default expiration and cleanup every 10 minutes
c := kcache.New(5*time.Minute, 10*time.Minute)
// Set a value with default expiration
c.Set("key", "value", kcache.DefaultExpiration)
// Get a value
if val, found := c.Get("key"); found {
fmt.Println(val)
}
// Set a value that never expires
c.Set("permanent", "data", kcache.NoExpiration)
Example (AtomicCounter) ¶
Example_atomicCounter demonstrates implementing a thread-safe counter.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
// Initialize counter if it doesn't exist
c.GetOrSet("page_views", 0, kcache.NoExpiration)
// Atomic increment using compare-and-swap
for {
current, found := c.Get("page_views")
if !found {
current = 0
}
newValue := current.(int) + 1
if c.CompareAndSwap("page_views", current, newValue, kcache.NoExpiration) {
fmt.Printf("Page views: %d\n", newValue)
break
}
// If CAS failed, another goroutine updated it, retry
}
}
Output: Page views: 1
Example (BatchOperations) ¶
Example_batchOperations demonstrates efficient batch processing.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
// Efficiently load multiple items
users := map[string]any{
"user:1": map[string]string{"name": "Alice", "role": "admin"},
"user:2": map[string]string{"name": "Bob", "role": "user"},
"user:3": map[string]string{"name": "Charlie", "role": "user"},
}
c.SetMultiple(users, 10*time.Minute)
// Efficiently retrieve multiple items
keys := []string{"user:1", "user:2", "user:3"}
results := c.GetMultiple(keys)
fmt.Printf("Loaded %d users\n", len(results))
}
Output: Loaded 3 users
Example (CacheMonitoring) ¶
Example_cacheMonitoring demonstrates monitoring cache performance.
package main
import (
"fmt"
"log"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
// Simulate some cache operations
c.Set("key1", "value1", kcache.DefaultExpiration)
c.Get("key1") // Hit
c.Get("key2") // Miss
// Check performance
stats := c.Stats()
if stats.HitRate < 0.8 {
log.Printf("Warning: Low cache hit rate: %.2f%%", stats.HitRate*100)
}
fmt.Printf("Cache efficiency: %.0f%%\n", stats.HitRate*100)
}
Output: Cache efficiency: 50%
Example (PrefixOperations) ¶
Example_prefixOperations demonstrates managing related cache entries.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
// Store session data
c.Set("session:user1:token", "token1", kcache.DefaultExpiration)
c.Set("session:user1:data", "data1", kcache.DefaultExpiration)
c.Set("session:user2:token", "token2", kcache.DefaultExpiration)
// Find all sessions for user1
user1Sessions := c.KeysByPrefix("session:user1:")
fmt.Printf("User1 sessions: %d\n", len(user1Sessions))
// Logout user1 - delete all their sessions
deleted := c.DeleteByPrefix("session:user1:")
fmt.Printf("Deleted %d session entries\n", deleted)
}
Output: User1 sessions: 2 Deleted 2 session entries
Example (SlidingExpiration) ¶
Example_slidingExpiration demonstrates implementing sliding expiration pattern.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
// Set initial session
c.Set("session:123", "user_data", 30*time.Minute)
// On each access, extend the expiration
if value, found := c.Get("session:123"); found {
// User is active, extend session
c.Touch("session:123", 30*time.Minute)
fmt.Printf("Session active: %v\n", value)
}
}
Output: Session active: user_data
Index ¶
- Constants
- Variables
- type Cache
- func (c Cache) Add(key string, value any, expiration time.Duration) error
- func (c Cache) CompareAndSwap(key string, oldValue, newValue any, expiration time.Duration) bool
- func (c Cache) Decrement(key string, n int64) error
- func (c Cache) Delete(key string)
- func (c Cache) DeleteByPrefix(prefix string) int
- func (c Cache) DeleteExpired()
- func (c Cache) DeleteMultiple(keys []string)
- func (c Cache) Flush()
- func (c Cache) Get(key string) (any, bool)
- func (c Cache) GetMultiple(keys []string) map[string]any
- func (c Cache) GetOrSet(key string, value any, expiration time.Duration) (any, bool)
- func (c Cache) GetTTL(key string) (time.Duration, error)
- func (c Cache) GetWithExpiration(key string) (any, time.Time, bool)
- func (c Cache) Increment(key string, n int64) error
- func (c Cache) ItemCount() int
- func (c Cache) Items() map[string]Item
- func (c Cache) Keys() []string
- func (c Cache) KeysByPrefix(prefix string) []string
- func (c Cache) Load(r io.Reader) error
- func (c Cache) LoadFile(filename string) error
- func (c Cache) OnEvicted(fn func(key string, value any))
- func (c Cache) Replace(key string, val any, expiration time.Duration) error
- func (c Cache) ResetStats()
- func (c Cache) Set(key string, value any, expiration time.Duration)
- func (c Cache) SetDefault(k string, value any)
- func (c Cache) SetMultiple(items map[string]any, expiration time.Duration)
- func (c Cache) Stats() Statistics
- func (c Cache) Touch(key string, expiration time.Duration) error
- func (c Cache) Write(w io.Writer) (err error)
- func (c Cache) WriteFile(filename string) error
- type CacheStats
- type Item
- type Statistics
Examples ¶
- Package (AtomicCounter)
- Package (BatchOperations)
- Package (CacheMonitoring)
- Package (PrefixOperations)
- Package (SlidingExpiration)
- Cache.CompareAndSwap
- Cache.DeleteByPrefix
- Cache.DeleteMultiple
- Cache.GetMultiple
- Cache.GetOrSet
- Cache.GetTTL
- Cache.Keys
- Cache.KeysByPrefix
- Cache.ResetStats
- Cache.SetMultiple
- Cache.Stats
- Cache.Touch
Constants ¶
const ( // NoExpiration indicates that a cache item should never expire. // Use this value when calling Set, Add, or Replace to create items // that persist until explicitly deleted. NoExpiration time.Duration = -1 // DefaultExpiration indicates that the cache's default expiration time // should be used. The default expiration is set when creating a new cache // with New or NewFrom. DefaultExpiration time.Duration = 0 )
Variables ¶
var ( // ErrItemNotFound is returned when attempting to access a cache item that doesn't exist or has expired. ErrItemNotFound = errors.New("item not found") // ErrItemExists is returned by Add when attempting to add an item with a key that already exists. ErrItemExists = errors.New("item already exists") // ErrNotNumeric is returned by Increment or Decrement when the cached value is not a numeric type. ErrNotNumeric = errors.New("item value is not a numeric type") )
Functions ¶
This section is empty.
Types ¶
type Cache ¶
type Cache struct {
// contains filtered or unexported fields
}
Cache is a thread-safe in-memory key-value store with expiration support. It wraps the internal cache implementation and provides a public API for cache operations. All methods are safe for concurrent use.
func New ¶
New creates and returns a new cache with the specified default expiration duration and cleanup interval.
Parameters:
- defaultExpiration: The default expiration duration for cache items. If set to 0 or negative, items will not expire by default unless explicitly set with an expiration.
- cleanupInterval: How often the janitor goroutine runs to remove expired items. If less than or equal to 0, no automatic cleanup occurs and expired items must be removed manually by calling DeleteExpired().
Returns a new Cache instance ready for use.
Example:
// Cache with 5 minute default expiration, cleanup every 10 minutes c := kcache.New(5*time.Minute, 10*time.Minute) // Cache with no expiration and no automatic cleanup c := kcache.New(kcache.NoExpiration, 0)
func NewFrom ¶
NewFrom creates and returns a new cache initialized with the provided items map.
This function is useful for:
- Restoring a cache from a previously serialized state (e.g., loaded via Load or LoadFile)
- Pre-allocating a cache with a known minimum size for better performance
- Starting with a pre-populated set of cache items
Parameters:
- defaultExpiration: The default expiration duration for cache items. If set to 0 or negative, items will not expire by default unless explicitly set with an expiration.
- cleanupInterval: How often the janitor goroutine runs to remove expired items. If less than or equal to 0, no automatic cleanup occurs.
- items: A map of cache items to initialize the cache with. The map will be used directly as the underlying storage (not copied).
Returns a new Cache instance initialized with the provided items.
Example:
// Create cache from deserialized items items := make(map[string]kcache.Item) // ... load items from file ... c := kcache.NewFrom(5*time.Minute, 10*time.Minute, items)
func (Cache) Add ¶
Add adds a new item to the cache only if the key doesn't already exist.
If the key already exists (even if expired), this method returns an error and does not update the value.
Parameters:
- key: The cache key
- value: The value to cache (can be any type)
- expiration: The expiration duration (same semantics as Set)
Returns ErrItemExists if the key already exists, nil otherwise.
This method is safe for concurrent use.
Example:
err := c.Add("user:123", userData, 5*time.Minute)
if errors.Is(err, kcache.ErrItemExists) {
// Key already exists
}
func (Cache) CompareAndSwap ¶
CompareAndSwap atomically compares the current value with an expected value and swaps it with a new value if they match.
This method implements a compare-and-swap (CAS) operation under a write lock, ensuring thread safety in concurrent environments. The comparison uses deep equality checking via reflect.DeepEqual.
Parameters:
- key: The cache key
- oldValue: The expected current value
- newValue: The new value to set if the comparison succeeds
- expiration: The expiration duration for the new value. Special values:
- DefaultExpiration (0): Use the cache's default expiration time
- NoExpiration (-1): Item never expires
- Any positive duration: Item expires after that duration from now
Returns:
- true if the comparison succeeded and the value was swapped
- false if the key doesn't exist, has expired, or the current value doesn't match oldValue
This method is safe for concurrent use.
Example:
// Atomically update a counter only if it has the expected value
success := c.CompareAndSwap("counter", 5, 6, kcache.NoExpiration)
if success {
fmt.Println("Counter updated from 5 to 6")
} else {
fmt.Println("Counter value was not 5, update failed")
}
Example ¶
ExampleCache_CompareAndSwap demonstrates atomic compare-and-swap operation.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
c.Set("counter", 5, kcache.NoExpiration)
// Try to update from 5 to 6 - should succeed
success := c.CompareAndSwap("counter", 5, 6, kcache.NoExpiration)
fmt.Printf("Update 5->6: %v\n", success)
// Try to update from 5 to 7 - should fail (current value is 6)
success = c.CompareAndSwap("counter", 5, 7, kcache.NoExpiration)
fmt.Printf("Update 5->7: %v\n", success)
// Verify final value
if val, found := c.Get("counter"); found {
fmt.Printf("Final value: %v\n", val)
}
}
Output: Update 5->6: true Update 5->7: false Final value: 6
func (Cache) Decrement ¶
Decrement subtracts a delta from a numeric value in the cache.
The cached value must be one of the supported numeric types: int, int8, int16, int32, int64, uint, uintptr, uint8, uint16, uint32, uint64, float32, float64
Parameters:
- key: The cache key
- n: The delta to subtract (can be negative to add)
Returns:
- ErrItemNotFound if the key doesn't exist or has expired
- ErrNotNumeric if the cached value is not a supported numeric type
Note: This operation can overflow/underflow for integer types.
This method is safe for concurrent use.
Example:
c.Set("counter", 10, kcache.NoExpiration)
err := c.Decrement("counter", 3) // counter is now 7
if errors.Is(err, kcache.ErrNotNumeric) {
// Value is not numeric
}
func (Cache) Delete ¶
func (c Cache) Delete(key string)
Delete removes an item from the cache.
If the key doesn't exist, this method does nothing (no error is returned). If an OnEvicted callback is set, it will be called with the deleted key and value.
Parameters:
- key: The cache key to delete
This method is safe for concurrent use.
func (Cache) DeleteByPrefix ¶
DeleteByPrefix removes all items from the cache whose keys start with the given prefix.
This method is useful for bulk deletion of related cache items. If an OnEvicted callback is set, it will be called for each deleted item after the lock is released.
Parameters:
- prefix: The prefix string to match against cache keys
Returns the number of items deleted.
This method is safe for concurrent use.
Example:
// Delete all user-related cache entries
count := c.DeleteByPrefix("user:")
fmt.Printf("Deleted %d user entries\n", count)
Example ¶
ExampleCache_DeleteByPrefix demonstrates bulk deletion by prefix.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
c.Set("temp:1", "data1", kcache.DefaultExpiration)
c.Set("temp:2", "data2", kcache.DefaultExpiration)
c.Set("perm:1", "data3", kcache.DefaultExpiration)
// Delete all temporary items
deleted := c.DeleteByPrefix("temp:")
fmt.Printf("Deleted %d items\n", deleted)
fmt.Printf("Remaining items: %d\n", c.ItemCount())
}
Output: Deleted 2 items Remaining items: 1
func (Cache) DeleteExpired ¶
func (c Cache) DeleteExpired()
DeleteExpired removes all expired items from the cache.
This method scans all items in the cache and removes those that have expired. If an OnEvicted callback is set, it will be called for each expired item.
This method is automatically called by the janitor goroutine if automatic cleanup is enabled. It can also be called manually for on-demand cleanup.
This method is safe for concurrent use.
func (Cache) DeleteMultiple ¶
func (c Cache) DeleteMultiple(keys []string)
DeleteMultiple removes multiple items from the cache in a single operation.
This method is more efficient than calling Delete multiple times because it acquires the write lock only once for all items.
If an OnEvicted callback is set, it will be called for each deleted item after the lock is released.
Parameters:
- keys: A slice of keys to delete from the cache
This method is safe for concurrent use.
Example:
keys := []string{"user:1", "user:2", "user:3"}
c.DeleteMultiple(keys)
Example ¶
ExampleCache_DeleteMultiple demonstrates batch deletion of multiple cache items.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
// Set up some test data
c.Set("temp:1", "data1", kcache.DefaultExpiration)
c.Set("temp:2", "data2", kcache.DefaultExpiration)
c.Set("temp:3", "data3", kcache.DefaultExpiration)
fmt.Printf("Items before: %d\n", c.ItemCount())
// Delete multiple items at once
keys := []string{"temp:1", "temp:2", "temp:3"}
c.DeleteMultiple(keys)
fmt.Printf("Items after: %d\n", c.ItemCount())
}
Output: Items before: 3 Items after: 0
func (Cache) Flush ¶
func (c Cache) Flush()
Flush removes all items from the cache.
This operation clears the entire cache. Unlike Delete() and DeleteExpired(), the OnEvicted callback is NOT called for items removed by Flush.
This method is safe for concurrent use.
func (Cache) Get ¶
Get retrieves an item from the cache by key.
Returns the cached value and true if the key exists and has not expired. Returns nil and false if the key doesn't exist or has expired.
Expired items are not automatically removed by this method; they are simply treated as non-existent. Use DeleteExpired() or enable automatic cleanup to remove expired items from memory.
This method is safe for concurrent use and updates cache statistics.
func (Cache) GetMultiple ¶
GetMultiple retrieves multiple items from the cache in a single operation.
This method is more efficient than calling Get multiple times because it acquires the read lock only once for all items.
Parameters:
- keys: A slice of keys to retrieve from the cache
Returns a map containing only the keys that exist and have not expired. Keys that don't exist or have expired are not included in the result.
This method is safe for concurrent use and updates cache statistics.
Example:
keys := []string{"user:1", "user:2", "user:3"}
results := c.GetMultiple(keys)
for key, value := range results {
fmt.Printf("%s: %v\n", key, value)
}
Example ¶
ExampleCache_GetMultiple demonstrates batch retrieval of multiple cache items.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
// Set up some test data
c.Set("user:1", "Alice", kcache.DefaultExpiration)
c.Set("user:2", "Bob", kcache.DefaultExpiration)
c.Set("user:3", "Charlie", kcache.DefaultExpiration)
// Get multiple items at once
keys := []string{"user:1", "user:2", "user:3", "user:4"}
results := c.GetMultiple(keys)
// user:4 doesn't exist, so it won't be in results
fmt.Printf("Found %d items\n", len(results))
fmt.Println(results["user:1"])
}
Output: Found 3 items Alice
func (Cache) GetOrSet ¶
GetOrSet atomically gets an existing value or sets a new value if the key doesn't exist.
This method performs a get-or-set operation in a single atomic operation under a write lock, ensuring thread safety in concurrent environments.
Parameters:
- key: The cache key
- value: The value to set if the key doesn't exist
- expiration: The expiration duration for the new value. Special values:
- DefaultExpiration (0): Use the cache's default expiration time
- NoExpiration (-1): Item never expires
- Any positive duration: Item expires after that duration from now
Returns:
- The actual value in the cache (either existing or newly set)
- true if a new value was set, false if an existing value was returned
This method is safe for concurrent use and updates cache statistics.
Example:
// Initialize a counter if it doesn't exist
value, wasSet := c.GetOrSet("counter", 0, kcache.NoExpiration)
if wasSet {
fmt.Println("Counter initialized to 0")
} else {
fmt.Printf("Counter already exists with value: %v\n", value)
}
Example ¶
ExampleCache_GetOrSet demonstrates atomic get-or-set operation.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
// First call sets the value
value, wasSet := c.GetOrSet("counter", 0, kcache.NoExpiration)
fmt.Printf("Value: %v, Was set: %v\n", value, wasSet)
// Second call returns existing value
value, wasSet = c.GetOrSet("counter", 100, kcache.NoExpiration)
fmt.Printf("Value: %v, Was set: %v\n", value, wasSet)
}
Output: Value: 0, Was set: true Value: 0, Was set: false
func (Cache) GetTTL ¶
GetTTL returns the remaining time-to-live for a cache item.
This method calculates how much time remains before the item expires.
Parameters:
- key: The cache key to check
Returns:
- The remaining duration until expiration
- nil error if the key exists and hasn't expired
- ErrItemNotFound if the key doesn't exist or has already expired
Special cases:
- If the item has NoExpiration, returns -1 (indicating it never expires)
- If the item has already expired, returns ErrItemNotFound
This method is safe for concurrent use.
Example:
ttl, err := c.GetTTL("session:123")
if err == nil {
if ttl == -1 {
fmt.Println("Session never expires")
} else {
fmt.Printf("Session expires in %v\n", ttl)
}
}
Example ¶
ExampleCache_GetTTL demonstrates checking remaining time-to-live.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
c.Set("key", "value", 10*time.Second)
ttl, err := c.GetTTL("key")
if err == nil {
fmt.Printf("Expires in approximately %v\n", ttl.Round(time.Second))
}
// Check item with no expiration
c.Set("permanent", "data", kcache.NoExpiration)
ttl, _ = c.GetTTL("permanent")
if ttl == -1 {
fmt.Println("Item never expires")
}
}
Output: Expires in approximately 10s Item never expires
func (Cache) GetWithExpiration ¶
GetWithExpiration retrieves an item from the cache along with its expiration time.
Returns:
- The cached value
- The expiration time as a time.Time (zero value if item never expires)
- true if the key exists and has not expired, false otherwise
If the item has no expiration (NoExpiration), the returned time.Time will be the zero value (time.Time{}).
This method is safe for concurrent use.
func (Cache) Increment ¶
Increment adds a delta to a numeric value in the cache.
The cached value must be one of the supported numeric types: int, int8, int16, int32, int64, uint, uintptr, uint8, uint16, uint32, uint64, float32, float64
Parameters:
- key: The cache key
- n: The delta to add (can be negative to subtract)
Returns:
- ErrItemNotFound if the key doesn't exist or has expired
- ErrNotNumeric if the cached value is not a supported numeric type
Note: This operation can overflow/underflow for integer types.
This method is safe for concurrent use.
Example:
c.Set("counter", 10, kcache.NoExpiration)
err := c.Increment("counter", 5) // counter is now 15
if errors.Is(err, kcache.ErrNotNumeric) {
// Value is not numeric
}
func (Cache) ItemCount ¶
func (c Cache) ItemCount() int
ItemCount returns the total number of items in the cache.
Note: This count may include expired items that haven't been cleaned up yet. To get an accurate count of only valid items, call DeleteExpired() first or use len(c.Items()).
This method is safe for concurrent use.
func (Cache) Items ¶
Items returns a copy of all non-expired items in the cache.
The returned map is a snapshot of the cache at the time of the call. Expired items are automatically filtered out and not included in the result. Modifying the returned map does not affect the cache.
Returns a new map containing copies of all non-expired cache items.
This method is safe for concurrent use.
Example:
items := c.Items()
for key, item := range items {
fmt.Printf("%s: %v\n", key, item.Object)
}
func (Cache) Keys ¶
func (c Cache) Keys() []string
Keys returns a slice of all non-expired keys in the cache.
Expired items are automatically filtered out and not included in the result. The order of keys in the returned slice is not guaranteed.
Returns a slice containing all non-expired cache keys.
This method is safe for concurrent use.
Example:
keys := c.Keys()
fmt.Printf("Cache contains %d keys\n", len(keys))
for _, key := range keys {
fmt.Println(key)
}
Example ¶
ExampleCache_Keys demonstrates retrieving all cache keys.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
c.Set("user:1", "Alice", kcache.DefaultExpiration)
c.Set("user:2", "Bob", kcache.DefaultExpiration)
c.Set("session:1", "data", kcache.DefaultExpiration)
keys := c.Keys()
fmt.Printf("Total keys: %d\n", len(keys))
}
Output: Total keys: 3
func (Cache) KeysByPrefix ¶
KeysByPrefix returns a slice of all non-expired keys that start with the given prefix.
Expired items are automatically filtered out and not included in the result. The order of keys in the returned slice is not guaranteed.
Parameters:
- prefix: The prefix string to match against cache keys
Returns a slice containing all non-expired cache keys that start with the prefix. If no keys match the prefix, an empty slice is returned.
This method is safe for concurrent use.
Example:
// Get all user-related keys
userKeys := c.KeysByPrefix("user:")
for _, key := range userKeys {
fmt.Println(key) // e.g., "user:1", "user:2", etc.
}
Example ¶
ExampleCache_KeysByPrefix demonstrates finding keys by prefix.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
c.Set("user:1", "Alice", kcache.DefaultExpiration)
c.Set("user:2", "Bob", kcache.DefaultExpiration)
c.Set("session:1", "data", kcache.DefaultExpiration)
// Get only user keys
userKeys := c.KeysByPrefix("user:")
fmt.Printf("User keys: %d\n", len(userKeys))
}
Output: User keys: 2
func (Cache) Load ¶
Load deserializes cache items from an io.Reader and adds them to the cache.
Items are loaded using Gob decoding. If a key already exists in the cache and hasn't expired, it will NOT be overwritten by the loaded value. Only new keys or keys with expired values will be updated.
Parameters:
- r: The reader to deserialize from
Returns an error if deserialization fails.
This method is safe for concurrent use (the cache is locked during loading).
Example:
file, err := os.Open("/tmp/cache.dat")
if err != nil {
log.Fatal(err)
}
defer file.Close()
err = c.Load(file)
func (Cache) LoadFile ¶
LoadFile deserializes cache items from a file and adds them to the cache.
Items are loaded using Gob decoding. If a key already exists in the cache and hasn't expired, it will NOT be overwritten by the loaded value. Only new keys or keys with expired values will be updated.
Parameters:
- filename: The path to the file to read from
Returns an error if the file cannot be opened or if deserialization fails.
This method is safe for concurrent use (the cache is locked during loading).
Example:
err := c.LoadFile("/tmp/cache.dat")
if err != nil {
log.Fatal(err)
}
func (Cache) OnEvicted ¶
OnEvicted sets a callback function that is called when an item is evicted from the cache.
The callback is invoked when items are removed via:
- Delete() - explicit deletion
- DeleteExpired() - automatic or manual cleanup of expired items
The callback is NOT invoked when items are removed via:
- Flush() - bulk deletion of all items
- Replace() - updating an existing item
Parameters:
- fn: A function that receives the key and value of the evicted item. The function is called outside of the cache lock, so it's safe to perform cache operations within the callback.
This method is safe for concurrent use.
Example:
c.OnEvicted(func(key string, value any) {
log.Printf("Item %s was evicted", key)
})
func (Cache) Replace ¶
Replace updates an existing item in the cache.
If the key doesn't exist or has expired, this method returns an error and does not create a new item.
Parameters:
- key: The cache key
- val: The new value to cache (can be any type)
- expiration: The new expiration duration (same semantics as Set)
Returns ErrItemNotFound if the key doesn't exist or has expired, nil otherwise.
This method is safe for concurrent use.
Example:
err := c.Replace("user:123", newUserData, 5*time.Minute)
if errors.Is(err, kcache.ErrItemNotFound) {
// Key doesn't exist
}
func (Cache) ResetStats ¶
func (c Cache) ResetStats()
ResetStats resets all cache statistics counters to zero.
This method resets the hits, misses, and evictions counters but does not affect the actual cache contents or the item count.
This method is safe for concurrent use.
Example:
c.ResetStats() // All statistics counters are now zero
Example ¶
ExampleCache_ResetStats demonstrates resetting cache statistics.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
c.Set("key", "value", kcache.DefaultExpiration)
c.Get("key") // Hit
stats := c.Stats()
fmt.Printf("Hits before reset: %d\n", stats.Hits)
c.ResetStats()
stats = c.Stats()
fmt.Printf("Hits after reset: %d\n", stats.Hits)
}
Output: Hits before reset: 1 Hits after reset: 0
func (Cache) Set ¶
Set adds or updates an item in the cache.
If the key already exists, its value and expiration are updated. If the key doesn't exist, a new item is created.
Parameters:
- key: The cache key
- value: The value to cache (can be any type)
- expiration: The expiration duration. Special values:
- DefaultExpiration (0): Use the cache's default expiration time
- NoExpiration (-1): Item never expires
- Any positive duration: Item expires after that duration from now
This method is safe for concurrent use.
Example:
c.Set("user:123", userData, 5*time.Minute) // Expires in 5 minutes
c.Set("config", configData, kcache.NoExpiration) // Never expires
c.Set("temp", tempData, kcache.DefaultExpiration) // Uses cache default
func (Cache) SetDefault ¶
SetDefault adds or updates an item in the cache using the default expiration time.
This is a convenience method equivalent to calling Set with DefaultExpiration.
Parameters:
- k: The cache key
- value: The value to cache (can be any type)
This method is safe for concurrent use.
func (Cache) SetMultiple ¶
SetMultiple adds or updates multiple items in the cache in a single operation.
This method is more efficient than calling Set multiple times because it acquires the write lock only once for all items.
Parameters:
- items: A map of key-value pairs to set in the cache
- expiration: The expiration duration for all items. Special values:
- DefaultExpiration (0): Use the cache's default expiration time
- NoExpiration (-1): Items never expire
- Any positive duration: Items expire after that duration from now
This method is safe for concurrent use.
Example:
items := map[string]any{
"user:1": userData1,
"user:2": userData2,
"user:3": userData3,
}
c.SetMultiple(items, 5*time.Minute)
Example ¶
ExampleCache_SetMultiple demonstrates batch setting of multiple cache items.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
// Set multiple items at once - more efficient than individual Set calls
items := map[string]any{
"user:1": "Alice",
"user:2": "Bob",
"user:3": "Charlie",
}
c.SetMultiple(items, 5*time.Minute)
// Verify items were set
if val, found := c.Get("user:1"); found {
fmt.Println(val)
}
}
Output: Alice
func (Cache) Stats ¶
func (c Cache) Stats() Statistics
Stats returns a snapshot of the current cache statistics.
The returned Statistics struct includes:
- Hits: Number of successful cache retrievals
- Misses: Number of failed cache retrievals (key not found or expired)
- Evictions: Number of items evicted from the cache
- Items: Current number of items in the cache
- HitRate: Cache hit rate calculated as hits / (hits + misses), or 0 if no operations
This method is safe for concurrent use.
Example:
stats := c.Stats()
fmt.Printf("Hit rate: %.2f%%\n", stats.HitRate*100)
Example ¶
ExampleCache_Stats demonstrates monitoring cache performance.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
// Perform some operations
c.Set("key1", "value1", kcache.DefaultExpiration)
c.Set("key2", "value2", kcache.DefaultExpiration)
c.Get("key1") // Hit
c.Get("key2") // Hit
c.Get("key3") // Miss
// Get statistics
stats := c.Stats()
fmt.Printf("Hits: %d\n", stats.Hits)
fmt.Printf("Misses: %d\n", stats.Misses)
fmt.Printf("Hit Rate: %.0f%%\n", stats.HitRate*100)
}
Output: Hits: 2 Misses: 1 Hit Rate: 67%
func (Cache) Touch ¶
Touch updates the expiration time of an existing cache item without changing its value.
This method is useful for extending the lifetime of cache items that are still being actively used, implementing a "sliding expiration" pattern.
Parameters:
- key: The cache key to update
- expiration: The new expiration duration. Special values:
- DefaultExpiration (0): Use the cache's default expiration time
- NoExpiration (-1): Item never expires
- Any positive duration: Item expires after that duration from now
Returns ErrItemNotFound if the key doesn't exist or has already expired.
This method is safe for concurrent use.
Example:
// Extend the expiration of a session by 30 minutes
err := c.Touch("session:123", 30*time.Minute)
if errors.Is(err, kcache.ErrItemNotFound) {
// Session doesn't exist or has expired
}
Example ¶
ExampleCache_Touch demonstrates updating item expiration time.
package main
import (
"fmt"
"time"
"github.com/kydenul/kcache"
)
func main() {
c := kcache.New(5*time.Minute, 10*time.Minute)
c.Set("session:123", "user_data", 1*time.Second)
// Extend the expiration before it expires
time.Sleep(500 * time.Millisecond)
err := c.Touch("session:123", 5*time.Minute)
if err == nil {
fmt.Println("Session expiration extended")
}
}
Output: Session expiration extended
func (Cache) Write ¶
Write serializes the cache's items to an io.Writer using Gob encoding.
All items in the cache (including expired ones) are serialized. The cache automatically registers all item types with the Gob encoder.
Parameters:
- w: The writer to serialize to
Returns an error if serialization fails (e.g., if an item contains an unserializable type like a channel).
This method is safe for concurrent use (the cache is locked during serialization).
Example:
var buf bytes.Buffer
err := c.Write(&buf)
if err != nil {
log.Fatal(err)
}
func (Cache) WriteFile ¶
WriteFile serializes the cache's items to a file using Gob encoding.
If the file doesn't exist, it will be created. If it exists, it will be overwritten.
Parameters:
- filename: The path to the file to write to
Returns an error if the file cannot be created or if serialization fails.
This method is safe for concurrent use (the cache is locked during serialization).
Example:
err := c.WriteFile("/tmp/cache.dat")
if err != nil {
log.Fatal(err)
}
type CacheStats ¶
type CacheStats struct {
// contains filtered or unexported fields
}
CacheStats holds statistics about cache operations. All fields use atomic operations for thread-safe updates.
type Item ¶
type Item struct {
// Object is the cached value. It can be of any type.
Object any
// Expiration is the Unix timestamp (in nanoseconds) when this item expires.
// A value of 0 means the item never expires.
Expiration int64
}
Item represents a single cache entry containing a value and its expiration time. Items are stored in the cache and can be retrieved, updated, or deleted.
type Statistics ¶
type Statistics struct {
Hits uint64 // Number of cache hits
Misses uint64 // Number of cache misses
Evictions uint64 // Number of evicted items
Items int // Current number of items in cache
HitRate float64 // Cache hit rate (hits / (hits + misses))
}
Statistics represents a snapshot of cache statistics.