任务是通过服务到服务身份验证机制查询Google服务之一,该机制假定每60分钟获取一次新鲜的访问令牌。因此,需要主动刷新或在失败的请求后刷新它。
最新似乎是一种防御性技术,不符合Elixir哲学。而且,无法确定请求是否由于访问令牌过期或提供的凭据(电子邮件和秘密密钥)通常无效而失败-它将是相同的文本和相同的401代码。
也许任何人都可以提供实施策略方面的建议?这将是供主机应用程序使用的库,并且假定在令牌刷新期间(可能是90ms?)将创建新的请求,通常,等待新令牌而不是使用即将使用的令牌对他们来说是个好习惯。过时的。
通常,在Elixir / Erlang中,您有大约4种存储和使用共享数据的方式:
GenServer或类似的服务器-您可以实现保留密钥并查询API的过程。您向它发送一条消息,它返回数据。您不必理会数据来自何处,使用了哪些键以及如何使用。请求是序列化的(不是并行完成的),这可能是您不想要的。
代理-仅保存数据(密钥)。您调用Agent.get / 3并获取密钥。每当您发现密钥已过期时,就调用Agent.update / 3将新密钥放入代理。或者您总是致电update / 3。
ETS表-不得已。如果没有充分的理由,请不要使用它。
任何外部来源-您都可以从磁盘,网络等中读取。甚至可以使用;)手段。
对于您的用例,第一个和第二个解决方案可能几乎相等。但由于并行化,我将使用第二个。您可以这样写:
defmodule TokenHolder do
def start_link(user,passwd) do
Agent.start_link(fn ->
tok_time = get_token user, passwd
{user,passwd,tok_time}
end, name: __MODULE__)
end
# refresh the token if older that one hour
@max_age 60*60*1000000
def token do
Agent.get_and_update(__MODULE__, fn state={user,passwd,{token,retrieved}} ->
now = :os.timestamp
if(:timer.now_diff(now, retrieved) < @max_age) do
# return old token and old state
{token,state}
else
# retrieve new token, return it and return changed state
tok_time = {token,_} = get_token user, passwd
{token,{user,passwd,tok_time}}
end
end)
end
defp get_token(user,passwd) do
token = ... # retrieve token somehow...
{token,:os.timestamp}
end
end
然后,您只需执行以下操作:
{:ok,_} = TokenHolder.start_link("user","secret")
token = TokenHolder.token
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句