The cache module provides flexible caching with multiple backend support.
In-process memory cache.
Azu.configure do |config|
config.cache = Azu::Cache::MemoryStore.new
endOptions:
max_size : Int32- Maximum entries (default: 10000)default_ttl : Time::Span- Default expiration (default: 1.hour)
Redis-backed distributed cache.
Azu.configure do |config|
config.cache = Azu::Cache::RedisStore.new(
url: ENV["REDIS_URL"]
)
endOptions:
url : String- Redis connection URLpool_size : Int32- Connection pool sizenamespace : String?- Key prefixdefault_ttl : Time::Span- Default expiration
Store a value.
Azu.cache.set("key", "value")
Azu.cache.set("key", "value", expires_in: 1.hour)Parameters:
key : String- Cache keyvalue : String- Value to storeexpires_in : Time::Span?- Optional TTL
Retrieve a value.
value = Azu.cache.get("key") # => String?Parameters:
key : String- Cache key
Returns: String? - Cached value or nil
Get or compute a value.
value = Azu.cache.fetch("key", expires_in: 1.hour) do
expensive_computation
endParameters:
key : String- Cache keyexpires_in : Time::Span?- Optional TTL&block- Block to compute value if missing
Returns: String - Cached or computed value
Remove a value.
Azu.cache.delete("key")Parameters:
key : String- Cache key
Check if key exists.
if Azu.cache.exists?("key")
# Key is cached
endParameters:
key : String- Cache key
Returns: Bool
Remove all cached values.
Azu.cache.clearIncrement a numeric value.
Azu.cache.increment("counter") # => 1
Azu.cache.increment("counter") # => 2
Azu.cache.increment("counter", by: 5) # => 7Parameters:
key : String- Cache keyby : Int32- Increment amount (default: 1)
Returns: Int32 - New value
Decrement a numeric value.
Azu.cache.decrement("counter")
Azu.cache.decrement("counter", by: 5)Parameters:
key : String- Cache keyby : Int32- Decrement amount (default: 1)
Returns: Int32 - New value
Set expiration on existing key.
Azu.cache.expire("key", 30.minutes)Parameters:
key : String- Cache keyttl : Time::Span- Time to live
Delete keys matching a pattern.
Azu.cache.delete_matched("user:*")Parameters:
pattern : String- Glob pattern
Get remaining time to live.
remaining = Azu.cache.ttl("key") # => Time::Span?Parameters:
key : String- Cache key
Returns: Time::Span? - Remaining TTL or nil
def get_user(id : Int64) : User?
cache_key = "user:#{id}"
cached = Azu.cache.get(cache_key)
return User.from_json(cached) if cached
user = User.find?(id)
if user
Azu.cache.set(cache_key, user.to_json, expires_in: 15.minutes)
end
user
endclass User
after_save :update_cache
after_destroy :remove_from_cache
private def update_cache
Azu.cache.set("user:#{id}", to_json, expires_in: 1.hour)
end
private def remove_from_cache
Azu.cache.delete("user:#{id}")
end
enddef fetch_with_lock(key : String, expires_in : Time::Span, &)
# Try cache first
cached = Azu.cache.get(key)
return cached if cached
# Try to acquire lock
lock_key = "lock:#{key}"
if Azu.cache.set(lock_key, "1", expires_in: 10.seconds, nx: true)
begin
value = yield
Azu.cache.set(key, value, expires_in: expires_in)
value
ensure
Azu.cache.delete(lock_key)
end
else
# Wait and retry
sleep 100.milliseconds
Azu.cache.get(key) || yield
end
endAzu.configure do |config|
if ENV["AZU_ENV"] == "production"
config.cache = Azu::Cache::RedisStore.new(
url: ENV["REDIS_URL"],
pool_size: 10,
namespace: "myapp:production",
default_ttl: 1.hour
)
else
config.cache = Azu::Cache::MemoryStore.new(
max_size: 1000,
default_ttl: 15.minutes
)
end
end