diff --git a/lib/aprsme/application.ex b/lib/aprsme/application.ex index ac0297c..8769b1c 100644 --- a/lib/aprsme/application.ex +++ b/lib/aprsme/application.ex @@ -235,24 +235,18 @@ defmodule Aprsme.Application do # end defp redis_children do - if System.get_env("REDIS_URL") do - require Logger + require Logger - Logger.info("Starting Redis-based caching and rate limiting") + Logger.info("Starting ETS-based caching and rate limiting") - [] - else - require Logger + # Create ETS tables for caching + :ets.new(:query_cache, [:set, :public, :named_table, read_concurrency: true]) + :ets.new(:device_cache, [:set, :public, :named_table, read_concurrency: true]) + :ets.new(:symbol_cache, [:set, :public, :named_table, read_concurrency: true]) - Logger.info("Starting ETS-based caching and rate limiting (no Redis URL)") - - [ - # Fallback to ETS-based implementations - Aprsme.RateLimiter, - %{id: :query_cache, start: {Cachex, :start_link, [:query_cache, [limit: 10_000]]}}, - %{id: :device_cache, start: {Cachex, :start_link, [:device_cache, [limit: 5_000]]}}, - %{id: :symbol_cache, start: {Cachex, :start_link, [:symbol_cache, [limit: 1_000]]}} - ] - end + [ + # ETS-based rate limiter + Aprsme.RateLimiter + ] end end diff --git a/lib/aprsme/cache.ex b/lib/aprsme/cache.ex index c1b1a06..60b473b 100644 --- a/lib/aprsme/cache.ex +++ b/lib/aprsme/cache.ex @@ -1,59 +1,85 @@ defmodule Aprsme.Cache do @moduledoc """ - Cache abstraction layer that works with both Cachex and RedisCache. - Provides a unified API regardless of the underlying implementation. + Cache abstraction layer using ETS (Erlang Term Storage). + Provides a unified API for in-memory caching. """ @doc """ Get a value from cache """ def get(cache_name, key) do - Cachex.get(cache_name, key) + case :ets.lookup(cache_name, key) do + [{^key, value}] -> {:ok, value} + [] -> {:ok, nil} + end + rescue + ArgumentError -> {:error, :no_cache} end @doc """ - Put a value in cache with optional TTL + Put a value in cache with optional TTL (TTL not implemented for ETS) """ - def put(cache_name, key, value, opts \\ []) do - Cachex.put(cache_name, key, value, opts) + def put(cache_name, key, value, _opts \\ []) do + try do + :ets.insert(cache_name, {key, value}) + {:ok, true} + rescue + ArgumentError -> {:error, :no_cache} + end end @doc """ Delete a key from cache """ def del(cache_name, key) do - Cachex.del(cache_name, key) + try do + :ets.delete(cache_name, key) + {:ok, true} + rescue + ArgumentError -> {:error, :no_cache} + end end @doc """ Clear all keys from cache """ def clear(cache_name) do - Cachex.clear(cache_name) + try do + :ets.delete_all_objects(cache_name) + {:ok, true} + rescue + ArgumentError -> {:error, :no_cache} + end end @doc """ - Get cache statistics + Get cache statistics (simplified for ETS) """ def stats(cache_name) do - Cachex.stats(cache_name) + try do + info = :ets.info(cache_name) + {:ok, %{size: Keyword.get(info, :size, 0)}} + rescue + ArgumentError -> {:error, :no_cache} + end end @doc """ Check if key exists """ def exists?(cache_name, key) do - case Cachex.exists?(cache_name, key) do - {:ok, exists?} -> exists? - {:error, _reason} -> false + try do + :ets.member(cache_name, key) + rescue + ArgumentError -> false end end @doc """ - Get TTL for a key + Get TTL for a key (not supported in ETS, always returns nil) """ - def ttl(cache_name, key) do - Cachex.ttl(cache_name, key) + def ttl(_cache_name, _key) do + {:ok, nil} end # Helper functions - no longer needed as we only use Cachex diff --git a/lib/aprsme_web/live/status_live/index.ex b/lib/aprsme_web/live/status_live/index.ex index ce5835e..74cf192 100644 --- a/lib/aprsme_web/live/status_live/index.ex +++ b/lib/aprsme_web/live/status_live/index.ex @@ -395,14 +395,14 @@ defmodule AprsmeWeb.StatusLive.Index do defp get_cached_aprs_status do # Try to get cached status for instant load - case Cachex.get(:query_cache, "aprs_status") do + case Aprsme.Cache.get(:query_cache, "aprs_status") do {:ok, status} when not is_nil(status) -> status _ -> # Fallback to direct query if cache miss status = get_aprs_status() - Cachex.put(:query_cache, "aprs_status", status, ttl: to_timeout(second: 5)) + Aprsme.Cache.put(:query_cache, "aprs_status", status) status end end