Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions lib/groot.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,16 @@ defmodule Groot do
@doc """
Sets the value for a register.
"""
@spec set(term(), term()) :: :ok
def set(key, value) do
Storage.set(key, value)
@spec set(term(), term(), term() | nil) :: :ok
def set(key, value, expires_in \\ nil) do
Storage.set(key, value, expires_in)
end
end

@doc """
Deletes a register
"""
@spec delete(term()) :: :ok
def delete(key) do
Storage.delete(key)
end
end
47 changes: 44 additions & 3 deletions lib/groot/storage.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,19 @@ defmodule Groot.Storage do
end

# The main api for setting a keys value
def set(key, value) do
GenServer.call(__MODULE__, {:set, key, value})
def set(key, value, expires_in \\ nil) do
GenServer.call(__MODULE__, {:set, key, value, expires_in})
end

# The main api for deleting a key
def delete(key) do
case :ets.lookup(__MODULE__, key) do
[] ->
:ok

[{^key, _value}] ->
GenServer.call(__MODULE__, {:delete, key})
end
end

# Deletes all keys in the currently connected cluster. This is only
Expand All @@ -44,13 +55,26 @@ defmodule Groot.Storage do
{:ok, %{table: tab, registers: registers}}
end

def handle_call({:set, key, value}, _from, data) do
def handle_call({:set, key, value, expires_in}, _from, data) do
registers = Map.update(data.registers, key, Register.new(key, value), fn reg ->
Register.update(reg, value)
end)
:ets.insert(data.table, {key, registers[key].value})
GenServer.abcast(__MODULE__, {:update_register, registers[key]})

case expires_in do
nil -> :ok
_ -> Process.send_after(self(), {:delete, key}, expires_in)
end

{:reply, :ok, %{data | registers: registers}}
end

def handle_call({:delete, key}, _from, data) do
registers = Map.delete(data.registers, key)
:ets.delete(data.table, key)
GenServer.abcast(__MODULE__, {:propagate_delete, key})

{:reply, :ok, %{data | registers: registers}}
end

Expand Down Expand Up @@ -79,6 +103,12 @@ defmodule Groot.Storage do
{:noreply, %{data | registers: new_registers}}
end

def handle_cast({:propagate_delete, key}, data) do
registers = Map.delete(data.registers, key)
:ets.delete(data.table, key)
{:noreply, %{data | registers: registers}}
end

def handle_info(msg, data) do
case msg do
{:nodeup, node} ->
Expand All @@ -90,6 +120,10 @@ defmodule Groot.Storage do
schedule_sync_timeout()
{:noreply, data}

{:delete, key} ->
registers = delete_record(key, data)
{:noreply, %{data | registers: registers}}

_msg ->
{:noreply, data}
end
Expand All @@ -111,4 +145,11 @@ defmodule Groot.Storage do
|> Enum.map(fn key -> {key, Register.latest(r1[key], r2[key])} end)
|> Enum.into(%{})
end

defp delete_record(key, data) do
registers = Map.delete(data.registers, key)
:ets.delete(data.table, key)
GenServer.abcast(__MODULE__, {:propagate_delete, key})
registers
end
end