我有很多网址。我需要与一些人分享这些网址。 我需要将这些网址转换为新的网址,以便:=>点击每个网址5次后,他们应该重定向到登录页面。
e.g。 www.abc.com/m
=> www.abc.com/m1234
(我们分享的这个)=>点击5次后=>登录页面。
注意:www.abc.com/m
需要登录。 www.abc.com/m1234
不需要登录5次尝试,它会打开www.abc.com/m
。
我需要用elixir / ruby来解决这个问题。 如果不包括DB,有什么方法可以做到吗?
这样做的最佳方法是什么?
答案 0 :(得分:1)
在标记elixir和ruby时,不完全确定您的堆栈是什么,但一种解决方案是使用Agent模块。另一种解决方案是使用ETS/DETS Table
这实际上是一个基于状态的GenServer包装器,对于类似的东西来说是完美的。
基本上,根据您的堆栈,您会向正在运行代理的elixir / phoenix应用程序发送消息。
例如:
#lib/appname.ex
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
worker(AppName.ClickCounter.start_link, [])
]
opts = [strategy: :one_for_one, name: Test.Supervisor]
Supervisor.start_link(children, opts)
end
以上在应用程序启动后启动代理,如果发生故障或崩溃,将重新启动代理。
然后在你的MyApp.ClickCounter
模块中:
defmodule MyApp.ClickCounter do
@doc """
Starts the Agent and registers it's process id under the name of the module name. Initializes it's state as an empty map.
"""
def start_link do
Agent.start_link(fn -> %{} end, name: __MODULE__)
end
@doc """
Takes in a string url and increments it's click count by one.
If there is no counter for the url already it will create one with a default value of 0.
"""
def increment_counter(url), do: update_state(url)
@doc """
Returns the current value of the counter for the given url
"""
def get_counter(url), do: Agent.get(__MODULE__, &(Map.fetch!(&1, url)))
defp update_state(value) do
Agent.update(__MODULE__, fn(state) ->
Map.update(state, value, 1, fn(count) ->
count + 1
end)
end)
end
end
然后启动iex -S mix
控制台并播放它。
iex(1)> MyApp.ClickCounter.increment_counter("http://google.com/123")
:ok
iex(2)> MyApp.ClickCounter.get_counter("http://google.com/123")
1
iex(3)> MyApp.ClickCounter.increment_counter("http://google.com/123")
:ok
iex(4)> MyApp.ClickCounter.increment_counter("http://google.com/123")
:ok
iex(5)> MyApp.ClickCounter.increment_counter("http://google.com/123")
:ok
iex(6)> MyApp.ClickCounter.get_counter("http://google.com/123")
4
从上面可以看出,您可以将任何想要的逻辑应用于更新,检索方法。由于它存储在一个过程中,因此速度非常快。
如果需要保持这种状态,你可以使用类似ETS / DETS的东西,它可以将表保存到磁盘,并在重启/崩溃时加载现有数据。
另一种持久化的方法可能是拥有一个数据库,然后拥有一个流程工作者(简单的方法是使用GenServer
并让它实现Process.send_after(x,x, 1000ms)
类的东西),它通过状态和再次将其保留在数据库中,以便您从崩溃中恢复。