This commit introduces a dual-mode caching and rate limiting system that can use either Redis (for distributed deployments) or ETS/Cachex (for single-node setups). Key changes: - Add Cache abstraction layer that automatically switches between Redis and Cachex - Implement RedisCache module with full distributed cache functionality - Implement RedisRateLimiter with sliding window algorithm for accurate rate limiting - Add RateLimiterWrapper to provide unified API for both implementations - Update application startup to conditionally use Redis when REDIS_URL is set - Migrate all cache operations to use the new Cache abstraction - Support graceful fallback to ETS-based solutions when Redis is unavailable The system automatically detects Redis availability via REDIS_URL environment variable and switches between implementations without code changes. This enables proper distributed caching and rate limiting in Kubernetes deployments while maintaining backward compatibility for development environments. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
46 lines
1,023 B
Elixir
46 lines
1,023 B
Elixir
defmodule Aprsme.RateLimiterWrapper do
|
|
@moduledoc """
|
|
Wrapper that provides the same API for both Hammer and RedisRateLimiter
|
|
"""
|
|
|
|
@doc """
|
|
Check rate limit - compatible with Hammer.hit/3 API
|
|
"""
|
|
def hit(bucket, scale_ms, limit) do
|
|
if using_redis?() do
|
|
Aprsme.RedisRateLimiter.check_rate(bucket, limit, scale_ms)
|
|
else
|
|
Aprsme.RateLimiter.hit(bucket, scale_ms, limit)
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Reset rate limit for a bucket
|
|
"""
|
|
def reset(bucket) do
|
|
if using_redis?() do
|
|
Aprsme.RedisRateLimiter.reset(bucket)
|
|
else
|
|
# Hammer doesn't provide a reset function
|
|
# Best we can do is return ok
|
|
:ok
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Get current count for a bucket
|
|
"""
|
|
def count(bucket, scale_ms) do
|
|
if using_redis?() do
|
|
Aprsme.RedisRateLimiter.count(bucket, scale_ms)
|
|
else
|
|
# Hammer doesn't provide a count function
|
|
# Return 0 as default
|
|
{:ok, 0}
|
|
end
|
|
end
|
|
|
|
defp using_redis? do
|
|
System.get_env("REDIS_URL") != nil
|
|
end
|
|
end
|