feat: metadata, frontmatter, write atomicity should now be in
This commit is contained in:
85
lib/bds/persistence.ex
Normal file
85
lib/bds/persistence.ex
Normal file
@@ -0,0 +1,85 @@
|
||||
defmodule BDS.Persistence do
|
||||
@moduledoc false
|
||||
|
||||
def now_ms, do: System.system_time(:millisecond)
|
||||
|
||||
def normalize_unix_timestamp(nil), do: nil
|
||||
|
||||
def normalize_unix_timestamp(value) when is_integer(value) do
|
||||
if abs(value) < 100_000_000_000 do
|
||||
value * 1000
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
def normalize_unix_timestamp(value) when is_binary(value) do
|
||||
value
|
||||
|> String.trim()
|
||||
|> case do
|
||||
"" -> nil
|
||||
trimmed ->
|
||||
case Integer.parse(trimmed) do
|
||||
{integer, ""} -> normalize_unix_timestamp(integer)
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def normalize_unix_timestamp(_value), do: nil
|
||||
|
||||
def from_unix_ms!(value) when is_integer(value) do
|
||||
value
|
||||
|> normalize_unix_timestamp()
|
||||
|> DateTime.from_unix!(:millisecond)
|
||||
end
|
||||
|
||||
def timestamp_to_iso8601(nil), do: nil
|
||||
|
||||
def timestamp_to_iso8601(value) when is_integer(value) do
|
||||
value
|
||||
|> from_unix_ms!()
|
||||
|> DateTime.to_iso8601()
|
||||
end
|
||||
|
||||
def parse_timestamp(nil), do: nil
|
||||
def parse_timestamp(value) when is_integer(value), do: normalize_unix_timestamp(value)
|
||||
|
||||
def parse_timestamp(value) when is_binary(value) do
|
||||
trimmed = String.trim(value)
|
||||
|
||||
cond do
|
||||
trimmed == "" ->
|
||||
nil
|
||||
|
||||
Regex.match?(~r/^-?\d+$/, trimmed) ->
|
||||
normalize_unix_timestamp(trimmed)
|
||||
|
||||
true ->
|
||||
case DateTime.from_iso8601(trimmed) do
|
||||
{:ok, datetime, _offset} -> DateTime.to_unix(datetime, :millisecond)
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def parse_timestamp(_value), do: nil
|
||||
|
||||
def atomic_write(path, contents) when is_binary(path) and is_binary(contents) do
|
||||
:ok = File.mkdir_p(Path.dirname(path))
|
||||
temp_path = path <> ".tmp"
|
||||
|
||||
with :ok <- File.write(temp_path, contents),
|
||||
:ok <- File.rename(temp_path, path) do
|
||||
:ok
|
||||
else
|
||||
{:error, _reason} = error ->
|
||||
_ = File.rm(temp_path)
|
||||
error
|
||||
|
||||
error ->
|
||||
_ = File.rm(temp_path)
|
||||
error
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user