{"id":16443392,"url":"https://github.com/0exp/any_cache","last_synced_at":"2025-03-23T08:32:03.636Z","repository":{"id":52476715,"uuid":"145338671","full_name":"0exp/any_cache","owner":"0exp","description":"A powerful cache wrapper that provides a minimalistic generic interface for all well-known cache storages. You can use any cache implementation in ANY project easily.","archived":false,"fork":false,"pushed_at":"2021-04-27T20:58:12.000Z","size":267,"stargazers_count":5,"open_issues_count":4,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-18T19:29:03.012Z","etag":null,"topics":["activesupport-cache","cache","dalli","dalli-cache-store","file-cache-store","memcached","memory-cache-store","rails-cache","redis","redis-cache-store","redis-store","ruby-cache"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0exp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-19T21:26:02.000Z","updated_at":"2024-02-26T22:17:57.000Z","dependencies_parsed_at":"2022-09-06T12:41:00.332Z","dependency_job_id":null,"html_url":"https://github.com/0exp/any_cache","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0exp%2Fany_cache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0exp%2Fany_cache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0exp%2Fany_cache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0exp%2Fany_cache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0exp","download_url":"https://codeload.github.com/0exp/any_cache/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245078067,"owners_count":20557274,"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":["activesupport-cache","cache","dalli","dalli-cache-store","file-cache-store","memcached","memory-cache-store","rails-cache","redis","redis-cache-store","redis-store","ruby-cache"],"created_at":"2024-10-11T09:20:19.630Z","updated_at":"2025-03-23T08:32:03.121Z","avatar_url":"https://github.com/0exp.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AnyCache \u0026middot; [![Gem Version](https://badge.fury.io/rb/any_cache.svg)](https://badge.fury.io/rb/any_cache) [![Build Status](https://travis-ci.org/0exp/any_cache.svg?branch=master)](https://travis-ci.org/0exp/any_cache) [![Coverage Status](https://coveralls.io/repos/github/0exp/any_cache/badge.svg?branch=master)](https://coveralls.io/github/0exp/any_cache?branch=master)\n\nAnyCache - a powerful cache wrapper that provides a minimalistic generic interface for all well-known cache storages and includes a minimal set of necessary operations:\n`fetch`, `read`, `write`, `delete`, `fetch_multi`, `read_multi`, `write_multi`, `delete_matched`, `expire`, `persist`, `exist?`, `clear`, `cleanup`, `increment`, `decrement`.\n\nSupported clients:\n\n- `Redis` ([gem redis](https://github.com/redis/redis-rb)) ([redis storage](https://redis.io/))\n- `Redis::Store` ([gem redis-store](https://github.com/redis-store/redis-store)) ([redis storage](https://redis.io/))\n- `Dalli::Client` ([gem dalli](https://github.com/petergoldstein/dalli)) ([memcached storage](https://memcached.org/))\n- `ActiveSupport::Cache::RedisCacheStore` ([gem activesupport](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/redis_cache_store.rb)) ([redis cache storage](https://api.rubyonrails.org/classes/ActiveSupport/Cache/RedisCacheStore.html))\n- `ActiveSupport::Cache::DalliStore` ([gem dalli](https://github.com/petergoldstein/dalli)) ([dalli store](https://github.com/petergoldstein/dalli/blob/master/lib/active_support/cache/dalli_store.rb))\n- `ActiveSupport::Cache::MemCacheStore` ([gem activesupport](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/mem_cache_store.rb)) ([memcache storage](https://api.rubyonrails.org/classes/ActiveSupport/Cache/MemCacheStore.html))\n- `ActiveSupport::Cache::FileStore` ([gem activesupport](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/file_store.rb)) ([file storage](https://api.rubyonrails.org/classes/ActiveSupport/Cache/FileStore.html))\n- `ActiveSupport::Cache::MemoryStore` ([gem activesupport](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/memory_store.rb)) ([in memory storage](https://api.rubyonrails.org/classes/ActiveSupport/Cache/MemoryStore.html))\n\n- [Coming Soon] File-based configuration;\n- [Coming Soon] Simple in-memory hash-based cache client\n- [Coming Soon] Simple key-value storage based on PostgreSQL\n- [Coming Soon] Support for `ActiveSupport::Cache::NullStore`\n- [Coming Soon] Naive `NullStore` implementation;\n\n---\n\n## Installation\n\n```ruby\ngem 'any_cache'\n```\n\n```shell\nbundle install\n# --- or ---\ngem install any_cache\n```\n\n```ruby\nrequire 'any_cache'\n```\n\n---\n\n## Usage / Table of Contents\n\n- [Creation](#creation)\n    - [Manual creation](#manual-creation)\n    - [Config-based creation](#config-based-creation)\n        - [AnyCache with Redis](#anycache-with-redis)\n        - [AnyCache with Redis::Store](#anycache-with-redisstore)\n        - [AnyCache with Dalli::Client](#anycache-with-dalliclient)\n        - [AnyCache with ActiveSupport::Cache::RedisCacheStore](#anycache-with-activesupportcacherediscachestore)\n        - [AnyCache with ActiveSupport::Cache::DalliStore](#anycache-with-activesupportcachedallistore)\n        - [AnyCache with ActiveSupport::Cache::MemCacheStore](#anycache-with-activesupportcachememcachestore)\n        - [AnyCache with ActiveSupport::Cache::FileStore](#anycache-with-activesupportcachefilestore)\n        - [AnyCache with ActiveSupport::Cache::MemoryStore](#anycache-with-activesupportcachememorystore)\n    - [Many cache storages](#many-cache-storages)\n    - [Custom cache clients](#custom-cache-clients)\n- [Logging](#logging)\n- [Operations](#operations)\n    - [Fetch](#fetch) / [Fetch Multi](#fetch-multi)\n    - [Read](#read) / [Read Multi](#read-multi)\n    - [Write](#write) / [Write Multi](#write-multi)\n    - [Delete](#delete) / [Delete Matched](#delete-matched)\n    - [Increment](#increment) / [Decrement](#decrement)\n    - [Expire](#expire)\n    - [Persist](#persist)\n    - [Existence](#existence)\n    - [Clear](#clear)\n    - [Cleanup](#cleanup)\n- [Plugins](#plugins)\n- [Roadmap](#roadmap)\n\n---\n\n### Creation\n\nTo instantiate AnyCache instance you have to provide a client.\nClient - an independent driver that works with a corresponding cache storage (external dependency).\n\nSupported clients:\n\n- `Redis`\n- `Redis::Store`\n- `Dalli::Client`\n- `ActiveSupport::Cache::RedisCacheStore`\n- `ActiveSupport::Cache::DalliStore`\n- `ActiveSupport::Cache::MemCacheStore`\n- `ActiveSupport::Cache::FileStore`\n- `ActiveSupport::Cache::MemoryStore`\n\n`AnyCache` can be instantiated by two ways:\n\n- with explicit client object instantiated manually ([read](#manual-creation));\n- via configuration ([read](#config-based-creation));\n\n#### Manual creation\n\nCustom instantiation with explicit client objects:\n\n```ruby\n# 1) create client object\nclient = Redis.new(...)\n# -- or --\nclient = Redis::Store.new(...)\n# -- or --\nclient = Dalli::Client.new(...)\n# -- or --\nclient = ActiveSupport::Cache::RedisCacheStore.new(...)\n# -- or --\nclient = ActiveSupport::Cache::DalliStore.new(...)\n# -- or --\nclient = ActiveSupport::Cache::MemCacheStore.new(...)\n# -- or --\nclient = ActiveSupport::Cache::FileStore.new(...)\n# -- or --\nclient = ActiveSupport::Cache::MemoryStore.new(...)\n\n# 2) build AnyCache instance\ncache_store = AnyCache.build(client) # =\u003e \u003cAnyCache:0x00007f990527f268 ...\u003e\n```\n\n#### Config-based creation\n\nYou can configure `AnyCache` globally or create subclasses and configure each of them. After that\nstorage instantiation works via `.build` method without explicit attributes.\n\n- `AnyCache.configure` is used for configuration;\n- `config.driver` is used for determine which client should be used;\n- `config.__driver_name__.options` stores client-related options;\n\nSupported drivers:\n\n- `:redis` - [Redis](#anycache-with-redis);\n- `:redis_store` - [Redis::Client](#anycache-with-redisstore);\n- `:dalli` - [Dalli::Client](#anycache-with-dalliclient);\n- `:as_redis_cache_store` - [ActiveSupport::Cache::RedisCacheStore](#anycache-with-activesupportcacherediscachestore);\n- `:as_dalli_store` - [ActiveSupport::Cache::DalliStore](#anycache-with-activesupportcachedallistore);\n- `:as_mem_cache_store` - [ActiveSupport::Cache::MemCacheStore](#anycache-with-activesupportcachememcachestore);\n- `:as_file_store` - [ActiveSupport::Cache::FileStore](#anycache-with-activesupportcachefilestore);\n- `:as_memory_store` - [ActiveSupport::Cache::MemoryStore](#anycache-with-activesupportcachememorystore);\n\n##### `AnyCache` with `Redis`:\n\n```ruby\nrequire 'redis'\nrequire 'any_cache'\n\nAnyCache.configure do |conf|\n  conf.driver = :redis\n  conf.redis.options = { ... } # Redis-related options\nend\n\ncache_store = AnyCache.build\n```\n\n##### `AnyCache` with `Redis::Store`:\n\n```ruby\nrequire 'redis-store'\nrequire 'any_cache'\n\nAnyCache.configure do |conf|\n  conf.driver = :redis_store\n  conf.redis_store.options = { ... } # Redis::Store-related options\nend\n\ncache_store = AnyCache.build\n```\n\n##### `AnyCache` with `Dalli::Client`:\n\n```ruby\nrequire 'dalli'\nrequire 'any_cache'\n\nAnyCache.configure do |conf|\n  conf.driver = :dalli\n  conf.dalli.servers = ... # string or array of strings\n  conf.dalli.options = { ... } # Dalli::Client-related options\nend\n\ncache_store = AnyCache.build\n```\n\n##### `AnyCache` with `ActiveSupport::Cache::RedisCacheStore`:\n\n```ruby\nrequire 'redis'\nrequire 'active_support'\nrequire 'any_cache'\n\nAnyCache.configure do |conf|\n  conf.driver = :as_redis_cache_store\n  conf.as_redis_cache_store.options = { ... } # ActiveSupport::Cache::RedisCacheStore-related options\nend\n\ncache_store = AnyCache.build\n```\n\n##### `AnyCache` with `ActiveSupport::Cache::DalliStore`:\n\n```ruby\nrequire 'dalli'\nrequire 'active_support'\nrequire 'any_cache'\n\nAnyCache.enable_patch!(:dalli_store) # NOTE: actual for Dalli \u003c= 2.7.8\n\nAnyCache.configure do |conf|\n  conf.driver = :as_dalli_store\n  conf.as_dalli_store.servers = ... # string or array of strings\n  conf.as_dalli_store.options = { ... } # ActiveSupport::Cache::DalliStore-related options\nend\n\ncache_store = AnyCache.build\n```\n\n##### `AnyCache` with `ActiveSupport::Cache::MemCacheStore`:\n\n```ruby\nrequire 'active_support'\nrequire 'any_cache'\n\nAnyCache.configure do |conf|\n  conf.driver = :as_mem_cache_store\n  conf.as_mem_cache_store.servers = ... # string or array of strings\n  conf.as_mem_cache_store.options = { ... } # ActiveSupport::Cache::MemCacheStore-related options\nend\n\ncache_store = AnyCache.build\n```\n\n##### `AnyCache` with `ActiveSupport::Cache::FileStore`:\n\n```ruby\nrequire 'active_support'\nrequire 'any_cache'\n\nAnyCache.configure do |conf|\n  conf.driver = :as_file_store\n  conf.as_file_store.cache_path = '/path/to/cache'\n  conf.as_file_store.options = { ... } # ActiveSupport::Cache::FileStore-related options\nend\n\ncache_store = AnyCache.build\n```\n\n##### `AnyCache` with `ActiveSupport::Cache::MemoryStore`:\n\n```ruby\nrequire 'activesupport'\nrequire 'any_cache'\n\nAnyCache.configure do |conf|\n  conf.driver = :as_memory_store\n  conf.as_memory_store.options = { ... } # ActiveSupport::Cache::MemoryStore-related options\nend\n\ncache_store = AnyCache.build\n```\n\n#### Many cache storages\n\nYou can inherit `AnyCache` class and create and configure as many cache storages as you want:\n\n```ruby\nclass RedisCache \u003c AnyCache\n  configure do |conf|\n    conf.driver = :redis\n  end\nend\n\nclass DalliCache \u003c AnyCache\n  configure do |conf|\n    conf.driver = :dalli\n  end\nend\n\nredis_cache = RedisCache.build\ndalli_cache = DalliCache.build\n```\n\n#### Custom cache clients\n\nIf you want to use your own cache client implementation, you should provide an object that responds to:\n\n- `#fetch(key, [**options])` ([doc](#fetch))\n- `#fetch_multi(*keys, [**options])` ([doc](#fetch-multi))\n- `#read(key, [**options])` ([doc](#read))\n- `#read_multi(*keys, [**options])` ([doc](#read-multi))\n- `#write(key, value, [**options])` ([doc](#write))\n- `#write_multi(entries, [**options])` ([doc](#write-multi))\n- `#delete(key, [**options])` ([doc](#delete))\n- `#delete_matched(pattern, [**options])` ([doc](#delete-matched))\n- `#increment(key, amount, [**options])` ([doc](#increment))\n- `#decrement(key, amount, [**options])` ([doc](#decrement))\n- `#expire(key, [**options])` ([doc](#expire))\n- `#persist(key, [**options])` ([doc](#persist))\n- `#exist?(key, [**options])` ([doc](#existence))\n- `#clear([**options])` ([doc](#clear))\n- `#cleanup([**options])` ([doc](#cleanup))\n\n```ruby\nclass MyCacheClient\n  # ...\n\n  def read(key, **)\n    # ...\n  end\n\n  def write(key, value, **)\n    # ...\n  end\n\n  # ...\nend\n\nAnyCache.build(MyCacheClient.new)\n```\n\n---\n\n### Logging\n\nAnyCache logs all its operations. By default, `AnyCache` uses a simple `STDOUT` logger with `Logger::INFO` level.\nLogging is performed with level configured in logger object.\n\nLogger configuration:\n\n```ruby\n# --- use your own logger ---\nAnyCache.configure do |conf|\n  conf.logger = MyLoggerObject.new\nend\n\n# --- disable logging ---\nAnyCache.configure do |conf|\n  conf.logger = nil\nend\n\n# --- (used by default) ---\nAnyCache.configure do |conf|\n  conf.logger = AnyCache::Logging::Logger.new(STDOUT)\nend\n\n# --- (your cache client inherited from AnyCache) ---\nYourCacheClient.configure do |conf|\n  # same configs as above\nend\n```\n\nLog message format:\n\n```shell\n[AnyCache\u003cCACHER_NAME\u003e/Activity\u003cOPERATION_NAME\u003e]: performed \u003cOPERATION_NAME\u003e operation with\nparams: INSPECTED_ARGUMENTS and options: INSPECTED_OPTIONS\n```\n\n- progname\n  - `CACHER_NAME` - class name of your cache class;\n  - `OPERATION_NAME` - performed operation (`read`, `write`, `fetch` and etc);\n- message\n  - `INSPECTED_ARGUMENTS` - a set of operation arguments;\n  - `INSPECTED_OPTIONS` - a set of operation options;\n\n```ruby\nany_cache.write(\"data\", 123, expires_in: 60)\n# I, [2018-09-07T10:04:56.649960 #15761]  INFO -- [AnyCache\u003cAnyCache\u003e/Activity\u003cwrite\u003e]: performed \u003cwrite\u003e operation with attributes: [\"data\", 123] and options: {:expires_in=\u003e60}.\n\nany_cache.clear\n# I, [2018-09-07T10:05:26.999847 #15761]  INFO -- [AnyCache\u003cAnyCache\u003e/Activity\u003cclear\u003e]: performed \u003cclear\u003e operation with attributes: [] and options: {}.\n```\n\n## Operations\n\n`AnyCache` provides a following operation set:\n\n- [fetch](#fetch) / [fetch_multi](#fetch-multi)\n- [read](#read) / [read_multi](#read-multi)\n- [write](#write) / [write_multi](#write-multi)\n- [delete](#delete) / [delete_matched](#delete-matched)\n- [increment](#increment) / [decrement](#decrement)\n- [expire](#expire)\n- [persist](#persist)\n- [clear](#clear)\n- [exist?](#existence)\n\n---\n\n### Fetch\n\n- `AnyCache#fetch(key, [force:], [expires_in:], [\u0026fallback])`\n    - works in `ActiveSupport::Cache::Store#fetch`-manner;\n    - fetches data from the cache using the given key;\n    - if a `fallback` block has been passed and data with the given key does not exist - that block\n      will be called with the given key and the return value will be written to the cache;\n    - use `raw: true` if you want to fetch incrementable/decrementable entry;\n\n```ruby\n# --- entry exists ---\ncache_store.fetch(\"data\") # =\u003e \"some_data\"\ncache_store.fetch(\"data\") { \"new_data\" } # =\u003e \"some_data\"\n\n# --- entry does not exist ---\ncache_store.fetch(\"data\") # =\u003e nil\ncache_store.fetch(\"data\") { |key| \"new_data\" } # =\u003e \"new_data\"\ncache_store.fetch(\"data\") # =\u003e \"new_data\"\n\n# --- new entry with expiration time ---\ncache_store.fetch(\"data\") # =\u003e nil\ncache_store.fetch(\"data\", expires_in: 8) { |key| \"new_#{key}\" } # =\u003e \"new_data\"\ncache_store.fetch(\"data\") # =\u003e \"new_data\"\n# ...sleep 8 seconds...\ncache_store.fetch(\"data\") # =\u003e nil\n\n# --- force update/rewrite ---\ncache_store.fetch(\"data\") # =\u003e \"some_data\"\ncache_store.fetch(\"data\", expires_in: 8, force: true) { |key| \"new_#{key}\" } # =\u003e \"new_data\"\ncache_store.fetch(\"data\") # =\u003e \"new_data\"\n# ...sleep 8 seconds...\ncache_store.fetch(\"data\") # =\u003e nil\n```\n\n---\n\n### Fetch Multi\n\n- `AnyCache#fetch_multi(*keys, [force:], [expires_in:], [\u0026fallback])`\n    - get a set of entries in hash form from the cache storage using given keys;\n    - works in `#fetch` manner but with a series of entries;\n    - nonexistent entries will be fetched with `nil` values;\n    - use `raw: true` if you want to fetch incrementable/decrementable entries;\n\n```ruby\n# --- fetch entries ---\ncache_store.fetch_multi(\"data\", \"second_data\", \"last_data\")\n# =\u003e returns:\n{\n  \"data\" =\u003e \"data\", # existing entry\n  \"second_data\" =\u003e nil, # nonexistent entry\n  \"last_data\" =\u003e nil # nonexistent entry\n}\n\n# --- fetch etnries and define non-existent entries ---\ncache_store.fetch_multi(\"data\", \"second_data\", \"last_data\") { |key| \"new_#{key}\" }\n# =\u003e returns:\n{\n  \"data\" =\u003e \"data\", # entry with OLD value\n  \"second_data\" =\u003e \"new_second_data\", # entry with NEW DEFINED value\n  \"last_data\" =\u003e \"new_last_data\" # entry with NEW DEFINED value\n}\n\n# --- force rewrite all entries ---\ncache_store.fetch_multi(\"data\", \"second_data\", \"last_data\", force: true) { |key| \"force_#{key}\" }\n# =\u003e returns\n{\n  \"data\" =\u003e \"force_data\", # entry with REDEFINED value\n  \"second_data\" =\u003e \"force_second_data\", # entry with REDEFINED value\n  \"last_data\" =\u003e \"force_last_data\" # entry with REDEFINED value\n}\n```\n\n---\n\n### Read\n\n- `AnyCache#read(key)` - get an entry value from the cache storage\n  - pass `raw: true` if you want to read incrementable/decrementable entries;\n\n```ruby\n# --- entry exists ---\ncache_store.read(\"data\") # =\u003e \"some_data\"\n\n# --- entry doesnt exist ---\ncache_store.read(\"data\") # =\u003e nil\n\n# --- read incrementable/decrementable entry ---\ncache_store.read(\"data\", raw: true) # =\u003e \"2\" (for example)\n```\n\n---\n\n### Read Multi\n\n- `AnyCache#read_multi(*keys)`\n    - get entries from the cache storage in hash form;\n    - nonexistent entries will be fetched with `nil` values;\n    - pass `raw: true` if you want to read incrementable/decrementable entries;\n\n```ruby\ncache_store.read_multi(\"data\", \"another_data\", \"last_data\", \"super_data\")\n# =\u003e returns\n{\n  \"data\" =\u003e \"test\", # existing entry\n  \"another_data\" =\u003e nil, # nonexistent entry\n  \"last_data\" =\u003e \"some_data\", # exisitng enry\n  \"super_data\" =\u003e nil # existing entry\n}\n\n# --- read incrementable/decrementable entries ---\ncache_store.read_multi(\"data\", \"another_data\", raw: true)\n# =\u003e returns\n{\n  \"data\" =\u003e \"1\",\n  \"another_data\" =\u003e \"2\",\n}\n```\n\n---\n\n### Write\n\n- `AnyCache#write(key, value, [expires_in:])` - write a new entry to the cache storage;\n  - pass `raw: true` if you want to store incrementable/decrementable entries;\n\n```ruby\n# --- permanent entry ---\ncache_store.write(\"data\", 123)\n\n# --- temporal entry (expires in 60 seconds) ---\ncache_store.write(\"data\", 123, expires_in: 60)\n\n# --- incrementable/decrementable entry ---\ncache_store.write(\"data\", 123, raw: true)\n```\n\n---\n\n### Write Multi\n\n- `AnyCache#write_multi(**entries)` - write a set of permanent entries to the cache storage;\n  - pass `raw: true` if you want to store incrementable/decrementable entries;\n\n```ruby\ncache_store.write_multi(\"data\" =\u003e \"test\", \"another_data\" =\u003e 123)\n\n# --- incrementable/decrementable entries ---\ncache_store.write_multi(\"data\" =\u003e 1, \"another_data\" =\u003e 2, raw: true)\n```\n\n---\n\n### Delete\n\n- `AnyCache#delete(key)` - remove entry from the cache storage;\n\n```ruby\ncache_store.delete(\"data\")\n```\n\n---\n\n### Delete Matched\n\n- `AnyCache#delete_matched(pattern)`\n    - removes all entries with keys matching the pattern;\n    - currently unsupported: `:dalli`, `:as_mem_cache_store`, `:as_dalli_store`;\n\n```ruby\n# --- using a regepx ---\ncache_store.delete_matched(/\\A*test*\\z/i)\n\n# --- using a string ---\ncache_store.delete_matched(\"data\")\n```\n\n---\n\n### Increment\n\n- `AnyCache#increment(key, amount = 1, [expires_in:])` - increment entry's value by the given amount\n  and set the new expiration time if needed;\n  - can increment only nonexistent entries OR entries that were written with `raw: true` option;\n\n```ruby\n# --- increment existing entry ---\ncache_store.write(\"data\", 1, raw: true) # you must provide :raw =\u003e true for incrementable entries\n\n# --- increment by default value (1) ---\ncache_store.increment(\"data\") # =\u003e 2\n\n# --- increment by custom value ---\ncache_store.increment(\"data\", 12) # =\u003e 14\n\n# --- increment and expire after 31 seconds\ncache_store.incrmeent(\"data\", expires_in: 31) # =\u003e 15\n\n# --- increment nonexistent entry (create new entry) ---\ncache_store.increment(\"another_data\", 5, expires_in: 5) # =\u003e 5\n\n# --- read incrementable entry ---\ncache_store.read(\"data\", raw: true) # you must provide :raw =\u003e true for incrementable entries\n```\n\n---\n\n### Decrement\n\n- `AnyCache#decrement(key, amount = 1, [expires_in:])` - decrement entry's value by the given amount\n  and set the new expiration time if needed;\n  - can decrement only nonexistent entries OR entries that were written with `raw: true` option;\n\n```ruby\n# --- decrement existing entry ---\ncache_store.write(\"data\", 15, raw: true) # you must provide :raw =\u003e true for decrementable entries\n\n# --- decrement by default value (1) ---\ncache_store.decrement(\"data\") # =\u003e 14\n\n# --- decrement by custom value ---\ncache_store.decrement(\"data\", 10) # =\u003e 4\n\n# --- decrement and expire after 5 seconds\ncache_store.decrememnt(\"data\", expirs_in: 5) # =\u003e 3\n\n# --- decrement nonexistent entry (create new entry) ---\ncache_store.decrememnt(\"another_data\", 2, expires_in: 10) # =\u003e -2 (or 0 for Dalli::Client)\n\n# --- read decrementable entry ---\ncache_store.read(\"data\", raw: true) # you must provide :raw =\u003e true for decrementable entries\n```\n\n---\n\n### Expire\n\n- `AnyCache#expire(key, [expires_in:])` - expire entry immediately or set the new expiration time;\n\n```ruby\n# --- expire immediately ---\ncache_store.expire(\"data\")\n\n# --- set new expiration time (in seconds) --\ncache_store.expire(\"data\", expires_in: 36)\n```\n\n---\n\n### Persist\n\n- `AnyCache#persist(key)` - change entry's expiration time to permanent;\n\n```ruby\n# --- create temporal entry (30 seconds) ---\ncache_store.write(\"data\", { a: 1 }, expires_in: 30)\n\n# --- remove entry expiration (make it permanent) ---\ncache_store.persist(\"data\")\n```\n\n---\n\n### Existence\n\n- `AnyCache#exist?(key)` - determine if an entry exists;\n\n```ruby\n# --- entry exists ---\ncache_store.exist?(\"data\") # =\u003e true\n\n# --- entry does not exist ---\ncache_store.exist?(\"another-data\") # =\u003e false\n```\n\n---\n\n### Clear\n\n- `AnyCache#clear()` - clear cache database;\n\n```ruby\n# --- prepare cache data ---\ncache_store.write(\"data\", { a: 1, b: 2 })\ncache_store.write(\"another_data\", 123_456)\n\ncache_store.read(\"data\") # =\u003e { a: 1, b: 2 }\ncache_store.read(\"another_data\") # =\u003e 123_456\n\n# --- clear cache ---\ncache_store.clear\n\ncache_store.read(\"data\") # =\u003e nil\ncache_store.read(\"another_data\") # =\u003e nil\n```\n\n---\n\n### Cleanup\n\n- `AnyCache#cleanup()` - remove expired entries from cache database\n  (make sense only for `:as_file_store` and `:as_memory_store` cache clients);\n\n```ruby\n# --- prepare cache data ---\ncache_store.write(\"data\", \"123\", expires_in: 5)\ncache_store.write(\"another_data\", \"456\", expires_in: 10)\n\n# --- waiting for cache exiration (10 seconds) ---\ncache_store.cleanup # remove expired entries from database (release disk space for example)\n```\n\n---\n\n## Plugins\n\n`AnyCache` provides a set of plugins and an interface for controllable plugin registering and loading.\n\n```ruby\n# --- show names of registered plugins ---\nAnyCache.plugins # =\u003e array of strings\n\n# --- load specific plugin ---\nAnyCache.plugin(:plugin_name) # or AnyCache.plugin('plugin_name')\n```\n\n---\n\n## Build\n\n- see [bin/rspec](bin/rspec)\n\n```shell\nbin/rspec --test-redis # run specs with Redis\nbin/rspec --test-redis-store # run specs with Redis::Store\nbin/rspec --test-dalli # run specs with Dalli::Client\nbin/rspec --test-as-redis-cache-store # run specs with ActiveSupport::Cache::RedisCacheStore\nbin/rspec --test-as-dalli-store # run specs with ActiveSupport::Cache::DalliStore\nbin/rspec --test-as-mem-cache-store # run specs with ActiveSupport::Cache::MemCacheStore\nbin/rspec --test-as-file-store # run specs with ActiveSupport::Cache::FileStore\nbin/rspec --test-as-memory-store # run specs with ActiveSupport::Cache::MemoryStore\n```\n\n---\n\n## Roadmap\n\n- centralized Logging API (core API);\n- instrumentation layer (public API);\n- more robust delegation API (core API);\n- global and configurable default expiration time (public API);\n- `#delete_matched` for memcached-based cache storages (core/public API);\n- rails integration (public API);\n\n---\n\n## Contributing\n\n- Fork it (https://github.com/0exp/any_cache/fork)\n- Create your feature branch (`git checkout -b feature/my-new-feature`)\n- Commit your changes (`git commit -am 'Add some feature'`)\n- Push to the branch (`git push origin feature/my-new-feature`)\n- Create new Pull Request\n\n## License\n\nReleased under MIT License.\n\n## Authors\n\nCreated by [Rustam Ibragimov](https://github.com/0exp/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0exp%2Fany_cache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0exp%2Fany_cache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0exp%2Fany_cache/lists"}