-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathdisk.ex
97 lines (80 loc) · 2.51 KB
/
disk.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
defmodule Elasticlunr.Storage.Disk do
@moduledoc """
This storage provider writes data to the local disk of the running application.
```elixir
config :elasticlunr,
storage: Elasticlunr.Storage.Disk
config :elasticlunr, Elasticlunr.Storage.Disk,
directory: "/path/to/project/storage"
```
"""
use Elasticlunr.Storage
alias Elasticlunr.{DB, Deserializer, Index, Serializer}
require Logger
@data_file_ext "data"
@index_file_ext "index"
@extensions [@data_file_ext, @index_file_ext]
@impl true
def write(%Index{db: db, name: name} = index) do
directory = config(:directory, ".")
data = Serializer.serialize(index)
with %{data: data_file, index: index_file} <- filenames(directory, name),
:ok <- DB.to(db, file: data_file) do
write_serialized_index_to_file(index_file, data)
end
end
@impl true
def read(name) do
directory = config(:directory, ".")
%{data: data_file, index: index_file} = filenames(directory, name)
index =
File.stream!(index_file, ~w[compressed]a)
|> Deserializer.deserialize()
with %Index{db: db} <- index,
{:ok, db} <- DB.from(db, file: data_file) do
Index.update_documents_size(%{index | db: db})
else
false ->
Logger.info("[elasticlunr] unable to data for index #{index.name}")
index
end
end
@impl true
def load_all do
files()
|> Stream.filter(&String.ends_with?(&1, @index_file_ext))
|> Stream.map(fn file ->
name = without_ext(file, @index_file_ext)
read(name)
end)
end
@impl true
def delete(name) do
directory = config(:directory, ".")
%{data: data_file, index: index_file} = filenames(directory, name)
with :ok <- File.rm(index_file) do
File.rm(data_file)
end
end
@spec files() :: list(binary())
def files do
directory = config(:directory, ".")
extensions = Enum.map_join(@extensions, ",", & &1)
match = Path.join(directory, "*.{#{extensions}}")
Path.wildcard(match)
|> Enum.map(&Path.expand/1)
end
@spec write_serialized_index_to_file(binary(), Enum.t()) :: :ok
def write_serialized_index_to_file(path, data) do
data
|> Stream.into(File.stream!(path, ~w[compressed]a), &"#{&1}\n")
|> Stream.run()
end
defp filenames(directory, name) do
%{
index: Path.join(directory, "#{name}.#{@index_file_ext}"),
data: Path.join(directory, "#{name}.#{@data_file_ext}") |> String.to_charlist()
}
end
defp without_ext(file, ext), do: Path.basename(file, ".#{ext}")
end