defmodule WeChat.Storage.Cache do
@moduledoc "缓存存储器"
@type cache_id :: WeChat.appid()
@type cache_sub_key :: term
@type cache_key :: {cache_id, cache_sub_key}
@type cache_value :: term
@compile {:inline, put_cache: 2, get_cache: 1, del_cache: 1}
alias WeChat.Work
def init_table() do
:ets.new(:wechat, [:named_table, :set, :public, read_concurrency: true])
end
@spec set_client(WeChat.client()) :: true
def set_client(client) do
appid = client.appid()
code_name = client.code_name()
app_list = Enum.uniq([appid, code_name])
Enum.map(app_list, &{{&1, :client}, client}) |> put_caches()
if match?(:work, client.app_type()) do
Enum.flat_map(client.agents(), &agent_cache_list(app_list, client, &1))
|> put_caches()
end
end
@spec set_work_agent(WeChat.client(), Work.Agent.t()) :: true
def set_work_agent(client, agent) do
appid = client.appid()
code_name = client.code_name()
Enum.uniq([appid, code_name])
|> agent_cache_list(client, agent)
|> List.flatten()
|> put_caches()
end
defp agent_cache_list(app_list, client, agent) do
agent_id = agent.id
name = agent.name
agent_list = Enum.uniq([agent_id, to_string(agent_id), name, to_string(name)])
value = {client, agent}
for app_flag <- app_list, agent_flag <- agent_list do
{{app_flag, agent_flag}, value}
end
end
@spec search_client(WeChat.appid() | WeChat.code_name()) :: nil | WeChat.client()
def search_client(app_flag), do: get_cache(app_flag, :client)
@spec search_client_agent(WeChat.appid() | WeChat.code_name(), Work.agent()) ::
nil | {WeChat.client(), Work.Agent.t()}
def search_client_agent(app_flag, agent_flag), do: get_cache(app_flag, agent_flag)
@spec put_cache(cache_id(), cache_sub_key(), cache_value()) :: true
def put_cache(id, sub_key, value) do
put_cache({id, sub_key}, value)
end
@spec put_cache(cache_key(), cache_value()) :: true
def put_cache(key, value) do
:ets.insert(:wechat, {key, value})
end
@spec put_caches([{cache_key(), cache_value()}]) :: true
def put_caches(list) when is_list(list) do
:ets.insert(:wechat, list)
end
@spec get_cache(cache_id(), cache_sub_key()) :: nil | cache_value()
def get_cache(id, sub_key) do
get_cache({id, sub_key})
end
@spec get_cache(cache_key()) :: nil | cache_value()
def get_cache(key) do
case :ets.lookup(:wechat, key) do
[{_, value}] -> value
_ -> nil
end
end
@spec del_cache(cache_id(), cache_sub_key()) :: true
def del_cache(id, sub_key) do
del_cache({id, sub_key})
end
@spec del_cache(cache_key()) :: true
def del_cache(key) do
:ets.delete(:wechat, key)
end
end