A key/value store where pairs can expire after a specified interval. Keys are always strings, and values can be any serializable Crystal type.
Add this to your application's shard.yml:
dependencies:
cache:
github: crystal-cache/cacheCaching means to store content generated during the request-response cycle and to reuse it when responding to similar requests.
The first time the result is returned from the query it is stored in the query cache (in memory) and the second time it's pulled from memory.
Memory cache can store any serializable Crystal objects.
Next example show how to get a single Github user and cache the result in memory.
require "http/client"
require "json"
require "cache"
cache = Cache::MemoryStore(String).new(expires_in: 30.minutes)
github_client = HTTP::Client.new(URI.parse("https://api.github.com"))
# Define how an object is mapped to JSON.
class User
include JSON::Serializable
property login : String
property id : Int32
end
username = "crystal-lang"
# First request.
# Getting data from Github and write it to cache.
user_json = cache.fetch("user_#{username}") do
response = github_client.get("/users/#{username}")
User.from_json(response.body).to_json
end
user = User.from_json(user_json)
user.id # => 6539796
# Second request.
# Getting data from cache.
user_json = cache.fetch("user_#{username}") do
response = github_client.get("/users/#{username}")
User.from_json(response.body).to_json
end
user = User.from_json(user_json)
user.id # => 6539796Note: The cache API has been updated in version 1.0.0. Keys are now always strings, and the store interface uses a single type parameter
Store(V)whereVis the value type. The previousStore(K, V)interface has been removed.
- Null store
- Memory
- Filesystem
There are multiple cache store implementations,
each having its own additional features. See the classes
under the /src/cache/stores directory, e.g.
All store implementations support:
fetch- Fetch data with fallback blockwrite- Write data to cacheread- Read data from cachedelete- Delete a specific keyexists?- Check if key existsclear- Clear all cache entries
Fetches data from the cache, using the given key (which must be a string). If there is data in the cache
with the given key, then that data is returned.
If there is no such data in the cache, then a block will be passed the key
and executed in the event of a cache miss.
Setting :expires_in will set an expiration time on the cache.
All caches support auto-expiring content after a specified number of seconds.
This value can be specified as an option to the constructor (in which case all entries will be affected),
or it can be supplied to the fetch or write method to effect just one entry.
store = Cache::MemoryStore(String).new(expires_in: 1.hour)
# Basic usage with block
value = store.fetch("key") do
"default_value"
end
# With custom expiration for this specific entry
value = store.fetch("key", expires_in: 10.minutes) do
"value_with_custom_expiry"
endWrites the value to the cache, with the key (which must be a string).
Optional expires_in will set an expiration time on the key.
Options are passed to the underlying cache implementation.
store = Cache::MemoryStore(String).new(12.hours)
# Basic write
store.write("foo", "bar")
# With custom expiration
store.write("temp_data", "value", expires_in: 5.minutes)Reads data from the cache, using the given key (which must be a string).
If there is data in the cache with the given key, then that data is returned.
Otherwise, nil is returned.
store = Cache::MemoryStore(String).new(12.hours)
store.write("foo", "bar")
store.read("foo") # => "bar"Deletes an entry in the cache using the given key (which must be a string). Returns true if an entry is deleted, false if the key didn't exist.
Options are passed to the underlying cache implementation.
store = Cache::MemoryStore(String).new(12.hours)
store.write("foo", "bar")
store.read("foo") # => "bar"
store.delete("foo") # => true
store.read("foo") # => nil
# Deleting non-existent key
store.delete("nonexistent") # => falseDeletes all items from the cache. This operation is irreversible and will remove all cached data.
Options are passed to the underlying cache implementation.
store = Cache::MemoryStore(String).new(12.hours)
store.write("foo", "bar")
store.write("baz", "qux")
store.keys.size # => 2
store.clear
store.keys.size # => 0
store.read("foo") # => nil
store.read("baz") # => nilChecks if a key exists in the cache. Returns true if the key exists and has not expired, false otherwise.
store = Cache::MemoryStore(String).new(12.hours)
store.write("foo", "bar")
store.exists?("foo") # => true
store.exists?("baz") # => false
store.delete("foo")
store.exists?("foo") # => falseA cache store implementation which stores everything into memory in the same process.
Can store any serializable Crystal object.
cache = Cache::MemoryStore(Hash(String | Int32)).new(expires_in: 1.minute)
cache.fetch("data_key") do
{"name" => "John", "age" => 18}
endCached data for MemoryStore(String) are compressed by default.
To turn off compression, pass compress: false to the initializer.
For other value types, the compress option is ignored.
cache = Cache::MemoryStore(String).new(expires_in: 1.minute, compress: false)
cache.fetch("today") do
Time.utc.day_of_week
endA cache store implementation which stores everything on the filesystem.
cache_path = "#{__DIR__}/cache"
cache = Cache::FileStore(String).new(expires_in: 12.hours, cache_path: cache_path)
cache.fetch("today") do
Time.utc.day_of_week
endCached data for FileStore(String) are not compressed by default.
To enable compression, pass compress: true to the initializer.
For other value types, the compress option is ignored.
cache = Cache::FileStore(String).new(expires_in: 12.hours, cache_path: cache_path, compress: true)
cache.fetch("today") do
Time.utc.day_of_week
endA cache store implementation which doesn't actually store anything. Useful in development and test environments where you don't want caching turned on but need to go through the caching interface.
cache = Cache::NullStore(String).new(expires_in: 1.minute)
cache.fetch("today") do
Time.utc.day_of_week
endFor activation, simply setup the log to :debug level:
Log.builder.bind "cache.*", :debug, Log::IOBackend.new- Fork it (https://github.com/crystal-cache/cache/fork)
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create a new Pull Request
- mamantoha Anton Maminov - creator, maintainer