Packages
electric
1.2.2
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.16
1.4.16-beta-1
1.4.15
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.14
1.1.13
1.1.12
1.1.11
1.1.10
1.1.9
1.1.8
1.1.7
1.1.6
retired
1.1.5
retired
1.1.4
retired
1.1.3
retired
1.1.2
1.1.1
1.1.0
1.0.24
1.0.23
1.0.22
1.0.21
1.0.20
1.0.19
1.0.18
1.0.17
1.0.15
1.0.13
1.0.12
1.0.11
1.0.10
1.0.9
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
1.0.0-beta.23
1.0.0-beta.22
1.0.0-beta.20
1.0.0-beta.19
1.0.0-beta.18
1.0.0-beta.17
1.0.0-beta.16
1.0.0-beta.15
1.0.0-beta.14
1.0.0-beta.13
1.0.0-beta.12
1.0.0-beta.11
1.0.0-beta.10
1.0.0-beta.9
1.0.0-beta.8
1.0.0-beta.7
1.0.0-beta.6
1.0.0-beta.5
1.0.0-beta.4
1.0.0-beta.3
1.0.0-beta.2
1.0.0-beta.1
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.1
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.5.2
0.4.4
Postgres sync engine. Sync little subsets of your Postgres data into local apps and services.
Current section
Files
Jump to
Current section
Files
lib/electric/persistent_kv/filesystem.ex
defmodule Electric.PersistentKV.Filesystem do
require Logger
defstruct root: "."
@schema NimbleOptions.new!(root: [type: :string, required: true])
def new!(opts) do
{:ok, config} = NimbleOptions.validate(opts, @schema)
struct(__MODULE__, config)
end
defimpl Electric.PersistentKV do
def get(fs, key) do
path = join(fs, key)
case File.read(path) do
{:ok, data} ->
try do
{:ok, :erlang.binary_to_term(data)}
rescue
ArgumentError ->
# This was before we added `term_to_binary` to the filesystem.
# We can treat data as a plain string
{:ok, data}
end
{:error, :enoent} ->
{:error, :not_found}
error ->
error
end
end
def set(fs, key, value) when is_binary(key) do
with file_path = mkdir(fs, key),
:ok <- atomic_write(file_path, value) do
Logger.debug("[SET] #{file_path}")
:ok
end
end
# rename is atomic if files are on same fs
# removes chance of reading partial write
defp atomic_write(final_path, data) do
tmp_file =
final_path
|> Path.dirname()
|> Path.join(
"." <> (:crypto.strong_rand_bytes(10) |> Base.encode32(case: :lower, padding: false))
)
with :ok <- File.write(tmp_file, :erlang.term_to_binary(data), [:binary]) do
File.rename(tmp_file, final_path)
end
end
defp mkdir(fs, key) do
path = join(fs, key)
dir = Path.dirname(path)
File.mkdir_p!(dir)
path
end
defp join(fs, key), do: Path.join(fs.root, key) |> Path.expand()
end
end