{"id":24719518,"url":"https://github.com/pnguyen215/cachify","last_synced_at":"2025-03-22T11:43:08.304Z","repository":{"id":273637765,"uuid":"920097413","full_name":"pnguyen215/cachify","owner":"pnguyen215","description":"cachify is a lightweight, high-performance, thread-safe Least Recently Used (LRU) cache library for Go. It is designed for in-memory caching with optional support for expiration, eviction callbacks, and dynamic capacity adjustment.","archived":false,"fork":false,"pushed_at":"2025-01-22T04:22:17.000Z","size":7,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-22T04:26:39.218Z","etag":null,"topics":["cache","cache-service","cache-storage","go","golang","lru-algorithm","lru-cache","lru-caches","lru-eviction","lru-implementation"],"latest_commit_sha":null,"homepage":"https://github.com/pnguyen215/cachify","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pnguyen215.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-21T15:03:22.000Z","updated_at":"2025-01-22T04:23:28.000Z","dependencies_parsed_at":"2025-01-22T04:36:46.416Z","dependency_job_id":null,"html_url":"https://github.com/pnguyen215/cachify","commit_stats":null,"previous_names":["pnguyen215/cachify"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pnguyen215%2Fcachify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pnguyen215%2Fcachify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pnguyen215%2Fcachify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pnguyen215%2Fcachify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pnguyen215","download_url":"https://codeload.github.com/pnguyen215/cachify/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244952571,"owners_count":20537468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","cache-service","cache-storage","go","golang","lru-algorithm","lru-cache","lru-caches","lru-eviction","lru-implementation"],"created_at":"2025-01-27T11:18:06.265Z","updated_at":"2025-03-22T11:43:08.277Z","avatar_url":"https://github.com/pnguyen215.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1\u003ecachify\u003c/h1\u003e\n\n`cachify` is a lightweight, high-performance, thread-safe **Least Recently Used (LRU)** cache library for Go. It is designed for in-memory caching with optional support for expiration, eviction callbacks, and dynamic capacity adjustment.\n\nWhether you're optimizing resource usage, caching frequently accessed data, or adding session management, `cachify` simplifies your task with an intuitive and flexible API.\n\n---\n\n# Getting Started\n\n## Requirements\n\nGo version **1.19** or higher\n\n## Installation\n\nTo start using `cachify`, run `go get`:\n\n- For a specific version:\n\n  ```bash\n  go get https://github.com/pnguyen215/cachify@v0.0.1\n  ```\n\n- For the latest version (globally):\n  ```bash\n  go get -u https://github.com/pnguyen215/cachify@latest\n  ```\n\n## Key Features\n\n- **LRU Eviction Policy:** Automatically removes the least recently used (LRU) items when the cache reaches capacity.\n- **Expiration Support:** Set time-to-live (TTL) for cache entries for automatic expiration.\n- **Custom Eviction Callback:** Trigger custom logic whenever an item is evicted.\n- **Thread-safe Design:** Built for concurrent access with `sync.RWMutex`.\n- **Dynamic Capacity Adjustment:** Adjust the cache capacity on the fly.\n- **Comprehensive API:** Includes utility methods to inspect and manage cache state.\n\n## API Documentation\n\n### Cache Initialization\n\n- `NewLRU(capacity int)`: Create an LRU cache with a fixed capacity.\n- `NewLRUCallback(capacity int, callback OnCallback)`: Add a callback for evictions.\n- `NewLRUExpires(capacity int, expiry time.Duration)`: Add entry expiration.\n\n### Cache Operations\n\n- `Get(key string) (value interface{}, ok bool)`: Retrieve an entry by key.\n- `GetAll() map[string]interface{}`: Retrieve all key-value pairs.\n- `Set(key string, value interface{})`: Add or update an entry.\n- `Update(key string, value interface{})`: Update the value associated with a specific key in the cache.\n- `Remove(key string)`: Remove a specific entry.\n- `Clear()`: Clear all entries.\n- `Len() int`: Get the number of entries in the cache.\n- `IsEmpty() bool`: Check if the cache is empty.\n- `IsExpired(key string) bool`: Check if a specific key has expired.\n- `Contains(key string) bool`: Check if a key exists.\n- `Pairs() (key string, value interface{}, ok bool)`: Get the least recently used pair.\n\n### Advanced Features\n\n- `SetCapacity(capacity int)`: Dynamically adjust the capacity.\n- `SetCallback(callback OnCallback)`: Set the eviction callback function.\n- `SetExpiry(expiry time.Duration)`: Update the expiration time for cache entries.\n- `GetStates() []state`: Get metadata for all entries.\n- `GetState() (m *state, ok bool)`: Get state returns the metadata of the least recently used item without removing it from the cache.\n- `IsMostRecentlyUsed(key string) bool`: Check if a key is the most recently used.\n- `GetMostRecentlyUsed() (state *state, ok bool)`: Retrieve the most recently used item.\n- `ExpandExpiry(key string, expiry time.Duration)`: Extend the expiration time for a key.\n- `PersistExpiry(key string) (remain time.Duration, ok bool)`: PersistExpiry returns the remaining time until expiration for a specific key.\n\n## Usage\n\n### Cache Initialization\n\n`NewLRU(capacity int)`: Create an LRU cache with a fixed capacity.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\t// Create an LRU cache with a capacity of 3\n\tcache := cachify.NewLRU(3)\n\n\t// Add entries to the cache\n\tcache.Set(\"a\", \"alpha\")\n\tcache.Set(\"b\", \"beta\")\n\tcache.Set(\"c\", \"gamma\")\n\n\t// Adding another entry will evict the least recently used ('a')\n\tcache.Set(\"d\", \"delta\")\n\n\t// Inspect the cache state\n\tfmt.Println(cache.GetAll())\n\t// Output: map[b:beta c:gamma d:delta]\n}\n```\n\n`NewLRUCallback(capacity int, callback OnCallback)`: Create an LRU cache with a custom eviction callback.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc onEviction(key string, value interface{}) {\n\tfmt.Printf(\"Evicted: Key=%s, Value=%v\\n\", key, value)\n}\n\nfunc main() {\n\t// Create an LRU cache with a capacity of 2 and a custom callback\n\tcache := cachify.NewLRUCallback(2, onEviction)\n\n\tcache.Set(\"x\", \"X-ray\")\n\tcache.Set(\"y\", \"Yankee\")\n\n\t// Adding a third entry triggers eviction of the least recently used ('x')\n\tcache.Set(\"z\", \"Zulu\")\n\t// Output: Evicted: Key=x, Value=X-ray\n}\n```\n\n`NewLRUExpires(capacity int, expiry time.Duration)`: Create an LRU cache with expiration.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\t// Create an LRU cache with expiration (5 seconds)\n\tcache := cachify.NewLRUExpires(2, 5*time.Second)\n\n\tcache.Set(\"k\", \"keep\")\n\n\t// Retrieve the key before expiration\n\tif val, ok := cache.Get(\"k\"); ok {\n\t\tfmt.Println(\"Value:\", val) // Output: Value: keep\n\t}\n\n\t// Wait for the key to expire\n\ttime.Sleep(6 * time.Second)\n\n\t// Attempt to retrieve the key after expiration\n\tif _, ok := cache.Get(\"k\"); !ok {\n\t\tfmt.Println(\"Key expired.\") // Output: Key expired.\n\t}\n}\n```\n\n### Cache Operations\n\n`Get(key string)`: Retrieve an entry by key.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\tcache.Set(\"a\", \"alpha\")\n\n\t// Retrieve an existing key\n\tif value, ok := cache.Get(\"a\"); ok {\n\t\tfmt.Println(\"Value:\", value) // Output: Value: alpha\n\t}\n\n\t// Attempt to retrieve a non-existing key\n\tif _, ok := cache.Get(\"b\"); !ok {\n\t\tfmt.Println(\"Key not found.\") // Output: Key not found.\n\t}\n}\n```\n\n`GetAll()`: Retrieve all key-value pairs.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\tcache.Set(\"a\", \"alpha\")\n\tcache.Set(\"b\", \"beta\")\n\n\t// Get all key-value pairs\n\tfmt.Println(\"Cache state:\", cache.GetAll())\n\t// Output: Cache state: map[a:alpha b:beta]\n}\n```\n\n`Set(key string, value interface{})`: Add or update an entry.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(2)\n\n\t// Add entries to the cache\n\tcache.Set(\"a\", \"alpha\")\n\tcache.Set(\"b\", \"beta\")\n\n\t// Update an existing key\n\tcache.Set(\"a\", \"updated_alpha\")\n\n\t// Inspect the cache state\n\tfmt.Println(cache.GetAll())\n\t// Output: map[a:updated_alpha b:beta]\n}\n```\n\n`Update(key string, value interface{})`: Update an existing entry without altering order.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\n\tcache.Set(\"x\", \"X-ray\")\n\tcache.Update(\"x\", \"Updated X-ray\")\n\n\t// Confirm the update\n\tif value, ok := cache.Get(\"x\"); ok {\n\t\tfmt.Println(\"Updated value:\", value) // Output: Updated value: Updated X-ray\n\t}\n}\n```\n\n`Remove(key string)`: Remove a specific entry.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\n\tcache.Set(\"a\", \"alpha\")\n\tcache.Set(\"b\", \"beta\")\n\n\t// Remove an entry\n\tcache.Remove(\"a\")\n\n\t// Attempt to retrieve the removed entry\n\tif _, ok := cache.Get(\"a\"); !ok {\n\t\tfmt.Println(\"Key 'a' removed.\") // Output: Key 'a' removed.\n\t}\n}\n```\n\n`Clear()`: Clear all entries from the cache.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\n\tcache.Set(\"x\", \"X-ray\")\n\tcache.Set(\"y\", \"Yankee\")\n\n\t// Clear the cache\n\tcache.Clear()\n\n\t// Confirm the cache is empty\n\tif cache.Len() == 0 {\n\t\tfmt.Println(\"Cache cleared.\") // Output: Cache cleared.\n\t}\n}\n```\n\n`Len()`: Get the number of entries in the cache.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\n\tcache.Set(\"a\", \"alpha\")\n\tcache.Set(\"b\", \"beta\")\n\n\tfmt.Println(\"Cache length:\", cache.Len())\n\t// Output: Cache length: 2\n}\n```\n\n`IsEmpty()`: Check if the cache is empty.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\n\tfmt.Println(\"Is cache empty?\", cache.IsEmpty())\n\t// Output: Is cache empty? true\n}\n```\n\n`Pairs()`: Retrieve the least recently used pair.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\n\tcache.Set(\"a\", \"alpha\")\n\tcache.Set(\"b\", \"beta\")\n\n\t// Retrieve the least recently used pair\n\tif key, value, ok := cache.Pairs(); ok {\n\t\tfmt.Printf(\"Least Recently Used: Key=%s, Value=%v\\n\", key, value)\n\t\t// Output: Least Recently Used: Key=a, Value=alpha\n\t}\n}\n```\n\n### Advanced Features\n\n`SetCapacity(capacity int)`: Dynamically adjust the cache capacity.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(2)\n\n\tcache.Set(\"a\", \"alpha\")\n\tcache.Set(\"b\", \"beta\")\n\n\t// Increase capacity to 3\n\tcache.SetCapacity(3)\n\tcache.Set(\"c\", \"gamma\")\n\n\tfmt.Println(\"Cache state after capacity increase:\", cache.GetAll())\n\t// Output: Cache state after capacity increase: map[a:alpha b:beta c:gamma]\n\n\t// Decrease capacity back to 2, evicting the least recently used ('a')\n\tcache.SetCapacity(2)\n\tfmt.Println(\"Cache state after capacity decrease:\", cache.GetAll())\n\t// Output: Cache state after capacity decrease: map[b:beta c:gamma]\n}\n```\n\n`SetCallback(callback OnCallback)`: Set or update the eviction callback function.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc evictionLogger(key string, value interface{}) {\n\tfmt.Printf(\"Evicted: Key=%s, Value=%v\\n\", key, value)\n}\n\nfunc main() {\n\tcache := cachify.NewLRU(2)\n\n\t// Set a callback for evictions\n\tcache.SetCallback(evictionLogger)\n\n\tcache.Set(\"x\", \"X-ray\")\n\tcache.Set(\"y\", \"Yankee\")\n\tcache.Set(\"z\", \"Zulu\")\n\t// Output: Evicted: Key=x, Value=X-ray\n}\n```\n\n`SetExpiry(expiry time.Duration)`: Update the expiration time for all cache entries.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRUExpires(2, 5*time.Second)\n\n\tcache.Set(\"a\", \"alpha\")\n\n\t// Update the expiration time to 10 seconds\n\tcache.SetExpiry(10 * time.Second)\n\n\ttime.Sleep(2 * time.Second)\n\tif val, ok := cache.Get(\"a\"); ok {\n\t\tfmt.Println(\"Value still exists:\", val) // Output: Value still exists: alpha\n\t}\n}\n```\n\n`GetStates()`: Get metadata for all entries.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\n\tcache.Set(\"x\", \"X-ray\")\n\tcache.Set(\"y\", \"Yankee\")\n\tcache.Set(\"z\", \"Zulu\")\n\n\t// Retrieve metadata for all entries\n\tfor _, state := range cache.GetStates() {\n\t\tfmt.Printf(\"Key: %v, Value: %v, LastAccess: %v\\n\", state.Key(), state.Value(), state.AccessTime())\n\t}\n}\n```\n\n`GetState()`: Get metadata for the least recently used item.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\n\tcache.Set(\"x\", \"X-ray\")\n\tcache.Set(\"y\", \"Yankee\")\n\n\t// Retrieve metadata for the least recently used item\n\tif state, ok := cache.GetState(); ok {\n\t\tfmt.Printf(\"LRU State: Key=%s, Value=%v, LastAccess=%v\\n\", state.Key(), state.Value(), state.AccessTime())\n\t}\n}\n```\n\n`IsMostRecentlyUsed(key string)`: Check if a key is the most recently used.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\n\tcache.Set(\"a\", \"alpha\")\n\tcache.Set(\"b\", \"beta\")\n\tcache.Set(\"c\", \"gamma\")\n\n\tif cache.IsMostRecentlyUsed(\"c\") {\n\t\tfmt.Println(\"Key 'c' is the most recently used.\") // Output: Key 'c' is the most recently used.\n\t}\n}\n```\n\n`GetMostRecentlyUsed()`: Retrieve the most recently used item.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRU(3)\n\n\tcache.Set(\"a\", \"alpha\")\n\tcache.Set(\"b\", \"beta\")\n\tcache.Set(\"c\", \"gamma\")\n\n\t// Retrieve the most recently used item\n\tif state, ok := cache.GetMostRecentlyUsed(); ok {\n\t\tfmt.Printf(\"Most Recently Used: Key=%s, Value=%v\\n\", state.Key(), state.Value())\n\t\t// Output: Most Recently Used: Key=c, Value=gamma\n\t}\n}\n```\n\n`ExpandExpiry(key string, expiry time.Duration)`: Extend the expiration time for a specific key.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRUExpires(2, 5*time.Second)\n\n\tcache.Set(\"a\", \"alpha\")\n\n\t// Extend the expiration time by 10 seconds\n\tcache.ExpandExpiry(\"a\", 10*time.Second)\n\n\ttime.Sleep(2 * time.Second)\n\tif val, ok := cache.Get(\"a\"); ok {\n\t\tfmt.Println(\"Value after extended expiry:\", val) // Output: Value after extended expiry: alpha\n\t}\n}\n```\n\n`PersistExpiry(key string)`: Retrieve the remaining time until expiration for a key.\n\neg.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\t\"github.com/pnguyen215/cachify\"\n)\n\nfunc main() {\n\tcache := cachify.NewLRUExpires(2, 10*time.Second)\n\n\tcache.Set(\"a\", \"alpha\")\n\n\t// Check remaining time for expiration\n\tif remain, ok := cache.PersistExpiry(\"a\"); ok {\n\t\tfmt.Printf(\"Time until expiration: %v\\n\", remain)\n\t\t// Output: Time until expiration: ~9s (actual value may vary slightly)\n\t}\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpnguyen215%2Fcachify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpnguyen215%2Fcachify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpnguyen215%2Fcachify/lists"}