-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR introduces compaction for the FileStorage. Compaction follows some rules: 1. Relative order preservation of insert/update/delete operations over same row: a consumer cannot see an update before the insert 2. insert/delete operations are never compacted 3. updates to the same row are compacted into one 4. clients can continue reading from same offsets as before the compaction and shouldn't see inserts/deletes they've already seen - they may see updates they've already seen as part of another latter update 5. Live tail is not affected by compaction in order to preserve idempotent inserts of already-seen transactions from Postgres Compaction doesn't currently affect "live tail" storage - we're still using CubDB for that, but compacted data is moved out of CubDB. On-disk format for the log is ```elixir <<tx_offset::64, op_offset::64, key_size::32, key::binary-size(key_size), op_type::8, json_size::64, json::binary-size(json_size)>> ``` With a supporing chunk index ```elixir <<start_tx_offset::64, start_op_offset::64, start_file_pos::64, end_tx_offset::64, end_op_offset::64, start_file_pos::64>> ``` that allows aligning reads for all clients and acts as a sparse index at the same time - the client comes with the offset, we find the chunk to serve them, and then serve only part of that chunk they've not seen, same as we're doing right now
- Loading branch information
1 parent
79a7dce
commit edfb9f3
Showing
27 changed files
with
1,809 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@core/sync-service": patch | ||
--- | ||
|
||
feat: add compaction flag to Electric that allows `UPDATE` events within a shape to be compacted to save space and bandwidth |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
packages/sync-service/lib/electric/shape_cache/compaction_runner.ex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
defmodule Electric.ShapeCache.CompactionRunner do | ||
use GenServer | ||
|
||
require Logger | ||
|
||
alias Electric.ShapeCache.Storage | ||
|
||
@schema NimbleOptions.new!( | ||
stack_id: [type: :string, required: true], | ||
shape_handle: [type: :string, required: true], | ||
storage: [type: :mod_arg, required: true], | ||
compaction_period: [type: :non_neg_integer, default: :timer.minutes(10)] | ||
) | ||
|
||
def start_link(opts) do | ||
with {:ok, opts} <- NimbleOptions.validate(opts, @schema) do | ||
GenServer.start_link(__MODULE__, opts, name: name(opts)) | ||
end | ||
end | ||
|
||
def name(opts) do | ||
Electric.ProcessRegistry.name(opts[:stack_id], __MODULE__, opts[:shape_handle]) | ||
end | ||
|
||
@impl GenServer | ||
def init(opts) do | ||
clean_after_period(opts) | ||
Process.set_label({:compaction_runner, opts[:stack_id], opts[:shape_handle]}) | ||
Logger.metadata(stack_id: opts[:stack_id], shape_handle: opts[:shape_handle]) | ||
{:ok, opts} | ||
end | ||
|
||
@impl GenServer | ||
def handle_info(:clean, opts) do | ||
Logger.info("Triggering compaction for shape #{opts[:shape_handle]}") | ||
clean_after_period(opts) | ||
Storage.compact(opts[:storage]) | ||
Logger.info("Compaction complete for shape #{opts[:shape_handle]}") | ||
|
||
{:noreply, opts} | ||
end | ||
|
||
defp clean_after_period(opts) do | ||
# add a large random jitter to avoid all compactions happening at the same time | ||
half_period = div(opts[:compaction_period], 2) | ||
next_msg = opts[:compaction_period] + Enum.random(-half_period..half_period) | ||
Process.send_after(self(), :clean, next_msg) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.