• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

whitfin / cachex / 64ffdb79131a3eb9e15e483ea81eedd63160a005-PR-426

30 Oct 2025 04:39AM UTC coverage: 99.042% (-1.0%) from 100.0%
64ffdb79131a3eb9e15e483ea81eedd63160a005-PR-426

Pull #426

github

whitfin
Remove tagging from inspection and commands
Pull Request #426: Simplify and naturalize API signatures and return types

68 of 74 new or added lines in 25 files covered. (91.89%)

2 existing lines in 2 files now uncovered.

827 of 835 relevant lines covered (99.04%)

1054.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.75
/lib/cachex/actions/save.ex
1
defmodule Cachex.Actions.Save do
2
  @moduledoc false
3
  # Command module to allow serialization of a cache to disk.
4
  #
5
  # Rather than using DETS to back up the internal ETS table, this module will
6
  # serialize the entire table using a `Cachex.stream/3`.
7
  #
8
  # Backups can be imported again using the `Cachex.restore/3` command, and
9
  # should be ble to be transferred between processes and physical nodes.
10
  alias Cachex.Options
11
  alias Cachex.Query
12
  alias Cachex.Router.Local
13

14
  # import our macros
15
  import Cachex.Error
16
  import Cachex.Spec
17

18
  ##############
19
  # Public API #
20
  ##############
21

22
  @doc """
23
  Dumps a cache to disk at the given location.
24

25
  This call will return an error if anything goes wrong with writing the file;
26
  it is up to the caller to ensure the file is writeable using the default `File`
27
  interfaces.
28
  """
29
  def execute(cache(router: router(module: router)) = cache, path, options) do
5✔
30
    file = File.open!(path, [:write, :compressed])
5✔
31
    buffer = Options.get(options, :buffer, &is_positive_integer/1, 25)
4✔
32
    locality = Keyword.get(options, :local)
4✔
33

34
    case init_stream(locality, router, cache, buffer) do
4✔
35
      {:error, _reason} = error ->
NEW
36
        error
×
37

38
      stream ->
39
        stream
40
        |> Stream.chunk_every(buffer)
41
        |> Stream.map(&handle_batch/1)
42
        |> Enum.each(&IO.binwrite(file, &1))
4✔
43

44
        with :ok <- File.close(file) do
4✔
45
          true
46
        end
47
    end
48
  rescue
49
    File.Error -> error(:unreachable_file)
1✔
50
  end
51

52
  ###############
53
  # Private API #
54
  ###############
55

56
  # Use a local stream to lazily walk through records on a local cache.
57
  defp init_stream(local, router, cache, buffer) when local or router == Local do
58
    options =
1✔
59
      :local
60
      |> const()
61
      |> Enum.concat(const(:notify_false))
62
      |> Enum.concat(buffer: buffer)
63

64
    Cachex.stream(cache, Query.build(), options)
1✔
65
  end
66

67
  # Generate an export of all nodes in a distributed cluster via `Cachex.export/2`
68
  defp init_stream(_local, _router, cache, _buffer),
69
    do: Cachex.export(cache, const(:notify_false))
3✔
70

71
  # Handle a batch of records and generate a binary of each.
72
  defp handle_batch(buffer) do
73
    Enum.reduce(buffer, <<>>, fn tuple, acc ->
4✔
74
      binary = :erlang.term_to_binary(tuple)
7✔
75
      size = byte_size(binary)
7✔
76
      acc <> <<size::24-unsigned>> <> binary
7✔
77
    end)
78
  end
79
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc