diff --git a/src/simple_cache.erl b/src/simple_cache.erl index b9d3145..766034b 100644 --- a/src/simple_cache.erl +++ b/src/simple_cache.erl @@ -23,16 +23,14 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Types. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --define(ETS_TID, atom_to_list(?MODULE)). --define(NAME(N), list_to_atom(?ETS_TID ++ "_" ++ atom_to_list(N))). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Exports. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Public API. -export([init/1]). --export([get/4]). --export([flush/1, flush/2]). +-export([get/4, get/5]). +-export([flush/1, flush/2, clear/2, create_value/4]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Public API. @@ -40,8 +38,7 @@ %% @doc Initializes a cache. -spec init(string()) -> ok. init(CacheName) -> - RealName = ?NAME(CacheName), - RealName = ets:new(RealName, [ + CacheName = ets:new(CacheName, [ named_table, {read_concurrency, true}, public, {write_concurrency, true} ]), ok. @@ -49,32 +46,57 @@ init(CacheName) -> %% @doc Deletes the keys that match the given ets:matchspec() from the cache. -spec flush(string(), term()) -> true. flush(CacheName, Key) -> - RealName = ?NAME(CacheName), - ets:delete(RealName, Key). + ets:delete(CacheName, Key). + +%% @doc Deletes the keys that match the given pattern from the cache. +-spec clear(string(), term()) -> true. +clear(CacheName, Pattern) -> + ets:match_delete(CacheName, Pattern). %% @doc Deletes all keys in the given cache. -spec flush(string()) -> true. flush(CacheName) -> - RealName = ?NAME(CacheName), - true = ets:delete_all_objects(RealName). + true = ets:delete_all_objects(CacheName). %% @doc Tries to lookup Key in the cache, and execute the given FunResult %% on a miss. -spec get(string(), infinity|pos_integer(), term(), function()) -> term(). get(CacheName, LifeTime, Key, FunResult) -> - RealName = ?NAME(CacheName), - case ets:lookup(RealName, Key) of + get(CacheName, LifeTime, Key, FunResult, #{}). + +-spec get(string(), infinity|pos_integer(), term(), function(), map()) -> term(). +get(CacheName, LifeTime, Key, FunResult, Options) -> + CollectMetric = maps:get(collect_metric, Options, false), + case ets:lookup(CacheName, Key) of [] -> % Not found, create it. - create_value(RealName, LifeTime, Key, FunResult); - [{Key, R, _CreatedTime, infinity}] -> R; % Found, wont expire, return the value. + case CollectMetric of + true -> prometheus_summary:observe(simple_cache_hit_boolean, [CacheName], 0); + false -> ok + end, + create_value(CacheName, LifeTime, Key, FunResult); + [{Key, R, _CreatedTime, infinity}] -> + case CollectMetric of + true -> prometheus_summary:observe(simple_cache_hit_boolean, [CacheName], 1); + false -> ok + end, + R; % Found, wont expire, return the value. [{Key, R, CreatedTime, LifeTime}] -> TimeElapsed = now_usecs() - CreatedTime, if TimeElapsed > (LifeTime * 1000) -> % expired? create a new value - create_value(RealName, LifeTime, Key, FunResult); - true -> R % Not expired, return it. + case CollectMetric of + true -> prometheus_summary:observe(simple_cache_hit_boolean, [CacheName], 0); + false -> ok + end, + create_value(CacheName, LifeTime, Key, FunResult); + true -> + case CollectMetric of + true -> prometheus_summary:observe(simple_cache_hit_boolean, [CacheName], 1); + false -> ok + end, + R % Not expired, return it. end end. @@ -83,13 +105,13 @@ get(CacheName, LifeTime, Key, FunResult) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% @doc Creates a cache entry. -spec create_value(string(), pos_integer(), term(), function()) -> term(). -create_value(RealName, LifeTime, Key, FunResult) -> +create_value(CacheName, LifeTime, Key, FunResult) -> R = FunResult(), - ets:insert(RealName, {Key, R, now_usecs(), LifeTime}), + ets:insert(CacheName, {Key, R, now_usecs(), LifeTime}), R. %% @doc Returns total amount of microseconds since 1/1/1. -spec now_usecs() -> pos_integer(). now_usecs() -> {MegaSecs, Secs, MicroSecs} = os:timestamp(), - MegaSecs * 1000000000000 + Secs * 1000000 + MicroSecs. \ No newline at end of file + MegaSecs * 1000000000000 + Secs * 1000000 + MicroSecs.