Created
March 6, 2021 16:47
-
-
Save joenoon/921f1b364fe1c9debb421bbd9e147410 to your computer and use it in GitHub Desktop.
Simple ecto Binary KV store in the db, MIT License, Joe Noon, Copyright 2020
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Noonhq.Repo.BinaryKv do | |
@moduledoc """ | |
Simple ecto Binary KV store in the db | |
MIT License, Joe Noon, Copyright 2020 | |
""" | |
require Logger | |
use Ecto.Schema | |
import Ecto.Query | |
alias Noonhq.Repo | |
@primary_key {:k, :string, autogenerate: false} | |
schema "binary_kv" do | |
field :v, :binary | |
field :exp, :utc_datetime_usec | |
timestamps type: :utc_datetime_usec | |
end | |
# PUBLIC API | |
def get(k) do | |
from(x in __MODULE__, | |
where: is_nil(x.exp) or x.exp > fragment("now()"), | |
where: x.k == ^k | |
) | |
|> Repo.one() | |
|> return_if_valid() | |
end | |
def del(k) do | |
from(x in __MODULE__, | |
where: x.k == ^k | |
) | |
|> Repo.delete_all() | |
end | |
def exp(k, exp) do | |
from(x in __MODULE__, | |
where: x.k == ^k, | |
update: [ | |
set: [exp: ^exp] | |
] | |
) | |
|> Repo.update_all([]) | |
end | |
def put(k, v, exp \\ nil) do | |
%__MODULE__{ | |
k: k, | |
v: to_value(v), | |
exp: exp | |
} | |
|> Repo.insert!( | |
on_conflict: {:replace_all_except, [:k]}, | |
conflict_target: [:k] | |
) | |
end | |
defmacro fetch(k, [exp: exp], do: do_fun) do | |
quote do | |
case Noonhq.Repo.Kv.get(unquote(k)) do | |
nil -> | |
v = unquote(do_fun) | |
Noonhq.Repo.Kv.put(unquote(k), v, unquote(exp)) | |
v | |
v -> | |
v | |
end | |
end | |
end | |
# PRIV | |
defp return_if_valid(%{exp: nil, v: v}), do: from_value(v) | |
defp return_if_valid(%{exp: exp, v: v}) do | |
case DateTime.compare(DateTime.utc_now(), exp) do | |
:lt -> from_value(v) | |
_ -> nil | |
end | |
end | |
defp return_if_valid(_), do: nil | |
defp to_value(nil), do: nil | |
defp to_value(v), do: :erlang.term_to_binary(v) | |
defp from_value(nil), do: nil | |
defp from_value(v) when is_binary(v), do: :erlang.binary_to_term(v) | |
end | |
defmodule Noonhq.Repo.Migrations.CreateBinaryKv do | |
use Ecto.Migration | |
def change do | |
create table(:binary_kv, primary_key: false) do | |
add :k, :text, primary_key: true | |
add :v, :binary | |
add :exp, :timestamptz | |
timestamps(type: :timestamptz) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment