Skip to content

Instantly share code, notes, and snippets.

@eteubert
Last active May 9, 2023 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eteubert/e4ddc45052afc138f85a59d886623345 to your computer and use it in GitHub Desktop.
Save eteubert/e4ddc45052afc138f85a59d886623345 to your computer and use it in GitHub Desktop.
nl_buffer.ex
alias Sandbox.Buffer
{:ok, pid} = Buffer.start_link([])
Buffer.push(pid, %{created_at: 5})
Buffer.push(pid, %{created_at: 7})
Buffer.push(pid, %{created_at: 1})
Buffer.inspect(pid)
Buffer.pop(pid) # nil
Process.sleep(3100)
Buffer.pop(pid) # created_at: 1
Buffer.pop(pid) # created_at: 5
Buffer.pop(pid) # created_at: 7
Buffer.pop(pid) # nil
defmodule Sandbox.Buffer do
use GenServer
# Client
def start_link(default) when is_list(default) do
GenServer.start_link(__MODULE__, default)
end
def push(pid, element) do
GenServer.cast(pid, {:push, element})
end
def pop(pid) do
GenServer.call(pid, :pop)
end
# Server
@impl true
def init(state) do
{:ok, state}
end
@impl true
def handle_cast({:push, element}, state) do
# TODO: pass mapping function when creating buffer
new_element = Map.put(element, :buffered_at, DateTime.utc_now())
new_state = Enum.sort_by([new_element | state], fn item -> item.created_at end)
{:noreply, new_state}
end
@impl true
def handle_call(:pop, _from, []) do
{:reply, nil, []}
end
def handle_call(:pop, _from, [head | tail]) do
# TODO: pass condition function when creating buffer
condition = fn item -> buffer_age(item) >= :timer.seconds(3) end
if condition.(head) do
{:reply, head, tail}
else
{:reply, nil, [head | tail]}
end
end
def buffer_age(item) do
DateTime.diff(DateTime.utc_now(), item.buffered_at) * 1000
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment