feat(store): add per-shard ets genserver
This commit is contained in:
1 parent
4da7f20581
commit
381494514e
1 file changed
+46
@@ -0,0 +1,46 @@
|
||||
defmodule Excache.Store.Shard do
|
||||
@moduledoc false
|
||||
|
||||
use GenServer
|
||||
|
||||
alias Excache.Store.Ops
|
||||
|
||||
def start_link({index, shard_count}) do
|
||||
GenServer.start_link(__MODULE__, {index, shard_count}, name: Excache.Store.shard_name(index))
|
||||
end
|
||||
|
||||
@impl true
|
||||
def init({index, shard_count}) do
|
||||
table =
|
||||
:ets.new(:excache_shard, [
|
||||
:set,
|
||||
:protected,
|
||||
read_concurrency: true,
|
||||
write_concurrency: true
|
||||
])
|
||||
|
||||
load_snapshot(table, index, shard_count, Excache.Persistence.snapshot_path())
|
||||
{:ok, %{index: index, table: table}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call({:op, op}, _from, state) do
|
||||
now = System.system_time(:millisecond)
|
||||
{:reply, Ops.apply_op(state.table, now, op), state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call(:dump, _from, state) do
|
||||
{:reply, :ets.tab2list(state.table), state}
|
||||
end
|
||||
|
||||
defp load_snapshot(table, index, shard_count, snapshot_path) do
|
||||
now = System.system_time(:millisecond)
|
||||
|
||||
for {key, _kind, _value, ea} = entry <- Excache.Persistence.load_entries(snapshot_path),
|
||||
rem(:erlang.phash2(key), shard_count) == index,
|
||||
ea == nil or ea > now do
|
||||
:ets.insert(table, entry)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user