diff --git a/lib/rox/batch.ex b/lib/rox/batch.ex index 82705a2..bd7cc8a 100644 --- a/lib/rox/batch.ex +++ b/lib/rox/batch.ex @@ -73,4 +73,18 @@ defmodule Rox.Batch do |> :lists.reverse |> Native.batch_write(db) end + + + @doc """ + Merges a list of `Batch.t` into a single `Batch.t`. + + """ + @spec merge([t]) :: t + def merge(batches) do + batches + |> Enum.reduce(Batch.new, fn %Batch{operations: ops}, %Batch{operations: merge_ops} = acc -> + %{acc | operations: Enum.concat(ops, merge_ops)} + end) + end + end diff --git a/test/rox/batch_test.exs b/test/rox/batch_test.exs new file mode 100644 index 0000000..c2377f5 --- /dev/null +++ b/test/rox/batch_test.exs @@ -0,0 +1,39 @@ +defmodule Rox.BatchTest do + use ExUnit.Case, async: true + + alias Rox.Batch + + describe "merge/1" do + test "stores operations in reverse order" do + batches = [ + %Batch{operations: [put: {"key_a", "value_a"}]}, + %Batch{operations: [put: {"key_b", "value_b"}]}, + %Batch{operations: [delete: "key_a"]}, + ] + + assert Batch.merge(batches) == %Batch{ + operations: [ + delete: "key_a", + put: {"key_b", "value_b"}, + put: {"key_a", "value_a"}, + ] + } + end + + test "works when a single batch contains multiple operations" do + batches = [ + %Batch{operations: [put: {"key_b", "value_b"}, put: {"key_a", "value_a"}]}, + %Batch{operations: [delete: "key_a"]}, + ] + + assert Batch.merge(batches) == %Batch{ + operations: [ + delete: "key_a", + put: {"key_b", "value_b"}, + put: {"key_a", "value_a"}, + ] + } + end + end + +end