diff --git a/lib/mix/tasks/phoenix_sync.install.ex b/lib/mix/tasks/phoenix_sync.install.ex index 990656d..77bd394 100644 --- a/lib/mix/tasks/phoenix_sync.install.ex +++ b/lib/mix/tasks/phoenix_sync.install.ex @@ -300,7 +300,7 @@ if Code.ensure_loaded?(Igniter) do defp required_electric_version do Phoenix.Sync.MixProject.project() |> Keyword.fetch!(:deps) - |> Enum.find(&match?({:electric, _, _}, &1)) + |> Enum.find(&(elem(&1, 0) == :electric)) |> elem(1) end diff --git a/lib/phoenix/sync/electric.ex b/lib/phoenix/sync/electric.ex index 40693c2..87a2b06 100644 --- a/lib/phoenix/sync/electric.ex +++ b/lib/phoenix/sync/electric.ex @@ -640,8 +640,9 @@ defmodule Phoenix.Sync.Electric do end end -if Code.ensure_loaded?(Electric.Shapes.Api) && - Code.ensure_loaded?(Phoenix.Sync.Electric.ApiAdapter) do +if Code.ensure_loaded?(Electric.Shapes.Api) do + Code.ensure_loaded(Phoenix.Sync.Electric.ApiAdapter) + defimpl Phoenix.Sync.Adapter.PlugApi, for: Electric.Shapes.Api do alias Electric.Shapes @@ -701,7 +702,7 @@ if Code.ensure_loaded?(Electric.Shapes.Api) && end end - def send_response(%ApiAdapter{}, conn, {request, response}) do + def send_response(_api, conn, {request, response}) do conn |> content_type() |> Plug.Conn.assign(:request, request) diff --git a/lib/phoenix/sync/plug/cors.ex b/lib/phoenix/sync/plug/cors.ex index cc126f2..c9e7762 100644 --- a/lib/phoenix/sync/plug/cors.ex +++ b/lib/phoenix/sync/plug/cors.ex @@ -16,7 +16,8 @@ defmodule Phoenix.Sync.Plug.CORS do "electric-offset", "electric-schema", "electric-up-to-date", - "electric-internal-known-error" + "electric-internal-known-error", + "retry-after" ] @expose_headers ["transfer-encoding" | @electric_headers] diff --git a/lib/phoenix/sync/sandbox.ex b/lib/phoenix/sync/sandbox.ex index d80c1e3..7756448 100644 --- a/lib/phoenix/sync/sandbox.ex +++ b/lib/phoenix/sync/sandbox.ex @@ -253,13 +253,14 @@ if Phoenix.Sync.sandbox_enabled?() do :ok = maybe_set_shared_mode(owner, stack_id, opts) - # give the inspector access to the sandboxed connection - Ecto.Adapters.SQL.Sandbox.allow(repo, owner, Sandbox.Inspector.name(stack_id)) - # mark the stack as ready Electric.StatusMonitor.mark_pg_lock_acquired(stack_id, owner) Electric.StatusMonitor.mark_replication_client_ready(stack_id, owner) - Electric.StatusMonitor.mark_connection_pool_ready(stack_id, owner) + Electric.StatusMonitor.mark_connection_pool_ready(stack_id, :admin, owner) + Electric.StatusMonitor.mark_connection_pool_ready(stack_id, :snapshot, owner) + Electric.StatusMonitor.mark_integrety_checks_passed(stack_id, owner) + Electric.StatusMonitor.mark_shape_log_collector_ready(stack_id, owner) + Electric.StatusMonitor.mark_supervisor_processes_ready(stack_id, owner) api_config = Sandbox.Stack.config(stack_id, repo) api = Electric.Application.api(api_config) @@ -292,7 +293,8 @@ if Phoenix.Sync.sandbox_enabled?() do defp generate_stack_id(opts) do tags = Keyword.get(opts, :tags, %{}) # with parameterised tests the same file:line can be running simultaneously - uid = System.unique_integer() |> to_string() + uid = System.unique_integer([:positive, :monotonic]) |> to_string() + now = System.monotonic_time(:microsecond) suffix = case Map.fetch(tags, :line) do @@ -306,7 +308,7 @@ if Phoenix.Sync.sandbox_enabled?() do :error -> "" end - "#{inspect(__MODULE__.Stack)}#{uid}#{prefix}#{suffix}" + "#{inspect(__MODULE__.Stack)}#{now}-#{uid}#{prefix}#{suffix}" end defp maybe_set_shared_mode(owner, stack_id, opts) do diff --git a/lib/phoenix/sync/sandbox/cleanup.ex b/lib/phoenix/sync/sandbox/cleanup.ex new file mode 100644 index 0000000..62465c8 --- /dev/null +++ b/lib/phoenix/sync/sandbox/cleanup.ex @@ -0,0 +1,24 @@ +defmodule Phoenix.Sync.Sandbox.Cleanup do + # We use PureFileStorage in the sandbox to remove compatibility issues + # this ensures that the storage dir is removed when the stack is torn + # down + @moduledoc false + + use GenServer + + def start_link({stack_id, storage_dir}) do + GenServer.start_link(__MODULE__, {stack_id, storage_dir}) + end + + @impl GenServer + def init({stack_id, storage_dir}) do + Process.flag(:trap_exit, true) + {:ok, Path.join(storage_dir, stack_id)} + end + + @impl GenServer + def terminate(_reason, storage_dir) do + File.rm_rf!(storage_dir) + :ok + end +end diff --git a/lib/phoenix/sync/sandbox/expiry_manager.ex b/lib/phoenix/sync/sandbox/expiry_manager.ex new file mode 100644 index 0000000..277d146 --- /dev/null +++ b/lib/phoenix/sync/sandbox/expiry_manager.ex @@ -0,0 +1,11 @@ +defmodule Phoenix.Sync.Sandbox.ExpiryManager do + use GenServer + + def start_link(args) do + GenServer.start_link(__MODULE__, args, name: Electric.ShapeCache.ExpiryManager.name(args)) + end + + def init(_) do + {:ok, []} + end +end diff --git a/lib/phoenix/sync/sandbox/inspector.ex b/lib/phoenix/sync/sandbox/inspector.ex index 9e33a66..36fbab5 100644 --- a/lib/phoenix/sync/sandbox/inspector.ex +++ b/lib/phoenix/sync/sandbox/inspector.ex @@ -34,6 +34,13 @@ if Phoenix.Sync.sandbox_enabled?() do @impl Electric.Postgres.Inspector def list_relations_with_stale_cache(_), do: {:ok, []} + @impl Electric.Postgres.Inspector + def load_supported_features(stack_id) do + with {:ok, pid} <- validate_stack_alive(stack_id) do + GenServer.call(pid, :load_supported_features) + end + end + def start_link(args) do GenServer.start_link(__MODULE__, args, name: name(args[:stack_id])) end @@ -56,8 +63,20 @@ if Phoenix.Sync.sandbox_enabled?() do def init(args) do {:ok, stack_id} = Keyword.fetch(args, :stack_id) {:ok, repo} = Keyword.fetch(args, :repo) - - {:ok, %{repo: repo, stack_id: stack_id, relations: %{}, columns: %{}, oids: %{}}} + {:ok, owner} = Keyword.fetch(args, :owner) + + # give the inspector access to the sandboxed connection + Ecto.Adapters.SQL.Sandbox.allow(repo, owner, self()) + + {:ok, + %{ + repo: repo, + stack_id: stack_id, + relations: %{}, + columns: %{}, + oids: %{}, + supported_features: %{} + }} end @impl GenServer @@ -88,6 +107,15 @@ if Phoenix.Sync.sandbox_enabled?() do {:reply, result, state} end + def handle_call(:load_supported_features, _from, state) do + {result, state} = + fetch_lazy(state, :supported_features, nil, fn -> + Electric.Postgres.Inspector.DirectInspector.load_supported_features(pool(state)) + end) + + {:reply, result, state} + end + defp pool(state) do %{pid: pool} = Ecto.Adapter.lookup_meta(state.repo.get_dynamic_repo()) pool diff --git a/lib/phoenix/sync/sandbox/producer.ex b/lib/phoenix/sync/sandbox/producer.ex index a7f3231..50fc2e5 100644 --- a/lib/phoenix/sync/sandbox/producer.ex +++ b/lib/phoenix/sync/sandbox/producer.ex @@ -3,7 +3,8 @@ if Phoenix.Sync.sandbox_enabled?() do @moduledoc false alias Electric.Replication.Changes.{ - Transaction, + TransactionFragment, + Commit, NewRecord, UpdatedRecord, DeletedRecord, @@ -50,6 +51,7 @@ if Phoenix.Sync.sandbox_enabled?() do def init(stack_id) do state = %{txid: 10000, stack_id: stack_id} + {:ok, state} end @@ -62,7 +64,7 @@ if Phoenix.Sync.sandbox_enabled?() do :ok = txid |> transaction(msgs) - |> ShapeLogCollector.store_transaction(ShapeLogCollector.name(stack_id)) + |> ShapeLogCollector.handle_event(stack_id) {:noreply, %{state | txid: next_txid}} end @@ -73,20 +75,22 @@ if Phoenix.Sync.sandbox_enabled?() do :ok = state.txid |> transaction(changes) - |> ShapeLogCollector.store_transaction(ShapeLogCollector.name(state.stack_id)) + |> ShapeLogCollector.handle_event(state.stack_id) {:noreply, %{state | txid: state.txid + 100}} end defp transaction(txid, changes) do - %Transaction{ + %{log_offset: last_log_offset} = Enum.at(changes, -1) + + %TransactionFragment{ xid: txid, lsn: Electric.Postgres.Lsn.from_integer(txid), - last_log_offset: Enum.at(changes, -1) |> Map.fetch!(:log_offset), + last_log_offset: last_log_offset, + has_begin?: true, + commit: %Commit{}, changes: changes, - num_changes: length(changes), - commit_timestamp: DateTime.utc_now(), - affected_relations: Enum.into(changes, MapSet.new(), & &1.relation) + affected_relations: MapSet.new(changes, & &1.relation) } end diff --git a/lib/phoenix/sync/sandbox/publication_manager.ex b/lib/phoenix/sync/sandbox/publication_manager.ex index 97ed390..6fb729c 100644 --- a/lib/phoenix/sync/sandbox/publication_manager.ex +++ b/lib/phoenix/sync/sandbox/publication_manager.ex @@ -4,57 +4,31 @@ if Phoenix.Sync.sandbox_enabled?() do use GenServer - @behaviour Electric.Replication.PublicationManager - - def start_link(_) do - :ignore - end - - def init(_arg) do - :ignore - end - - def name(stack_id) when is_binary(stack_id) do - Phoenix.Sync.Sandbox.name({__MODULE__, stack_id}) - end - - def name(opts) when is_list(opts) do - opts - |> Keyword.fetch!(:stack_id) - |> name() + def start_link(args) do + GenServer.start_link(__MODULE__, args, name: name(args)) end - def recover_shape(_shape_handle, _shape, _opts) do - :ok + def name(stack_ref) do + Electric.Replication.PublicationManager.name(stack_ref) end - def recover_shape(_shape, _opts) do - :ok + def init(opts) do + {:ok, opts} end - def add_shape(_shape_handle, _shape, opts) do - snapshotter = self() - {:ok, owner} = Keyword.fetch(opts, :owner) - {:ok, repo} = Keyword.fetch(opts, :repo) + # intercept the snapshotter process's add_shape call to add it to the allow + # list for the sandbox repo + def handle_call({:add_shape, _shape_handle, _pub_filter}, {snapshotter, _ref}, state) do + {:ok, owner} = Keyword.fetch(state, :owner) + {:ok, repo} = Keyword.fetch(state, :repo) Ecto.Adapters.SQL.Sandbox.allow(repo, owner, snapshotter) - :ok - end - - def add_shape(_shape, _opts) do - :ok - end - - def remove_shape(_shape_handle, _shape, _opts) do - :ok - end - def remove_shape(_shape, _opts) do - :ok + {:reply, :ok, state} end - def refresh_publication(_opts) do - :ok + def handle_call(_msg, _from, state) do + {:reply, :ok, state} end end end diff --git a/lib/phoenix/sync/sandbox/stack.ex b/lib/phoenix/sync/sandbox/stack.ex index e5be0f6..44f4bbf 100644 --- a/lib/phoenix/sync/sandbox/stack.ex +++ b/lib/phoenix/sync/sandbox/stack.ex @@ -6,6 +6,8 @@ if Phoenix.Sync.sandbox_enabled?() do alias Phoenix.Sync.Sandbox + @json Phoenix.Sync.json_library() + def child_spec(opts) do {:ok, stack_id} = Keyword.fetch(opts, :stack_id) {:ok, repo} = Keyword.fetch(opts, :repo) @@ -27,49 +29,92 @@ if Phoenix.Sync.sandbox_enabled?() do Supervisor.start_link(__MODULE__, {stack_id, repo, owner}, name: name(stack_id)) end - alias Electric.Shapes.Querying alias Electric.ShapeCache.Storage + alias Electric.Shapes.Querying def snapshot_query( - parent, + task_parent, + consumer, shape_handle, shape, - db_pool, - storage, - stack_id, - chunk_bytes_threshold + %{storage: storage, stack_id: stack_id}, + sandbox_pool ) do Postgrex.transaction( - db_pool, + sandbox_pool, fn conn -> - GenServer.cast(parent, {:pg_snapshot_known, shape_handle, {1000, 1100, []}}) + xmin = 1000 + xmax = 1100 + + send(task_parent, {:ready_to_stream, self(), System.monotonic_time(:millisecond)}) + + GenServer.cast(consumer, {:pg_snapshot_known, shape_handle, {xmin, xmax, []}}) # Enforce display settings *before* querying initial data to maintain consistent # formatting between snapshot and live log entries. Enum.each(Electric.Postgres.display_settings(), &Postgrex.query!(conn, &1, [])) + chunk_bytes_threshold = Electric.StackConfig.lookup(stack_id, :chunk_bytes_threshold) + + # xmin/xmax/xip_list are uint64, so we need to convert them to strings for JS not to mangle them + finishing_control_message = + @json.encode!(%{ + headers: %{ + control: "snapshot-end", + xmin: to_string(xmin), + xmax: to_string(xmax), + xip_list: [] + } + }) + stream = - Querying.stream_initial_data(conn, stack_id, shape, chunk_bytes_threshold) + Querying.stream_initial_data( + conn, + stack_id, + shape_handle, + shape, + chunk_bytes_threshold + ) |> Stream.transform( fn -> false end, fn item, acc -> - if not acc, do: GenServer.cast(parent, {:snapshot_started, shape_handle}) + if not acc do + send(task_parent, :data_received) + GenServer.cast(consumer, {:snapshot_started, shape_handle}) + end + {[item], true} end, fn acc -> - if not acc, do: GenServer.cast(parent, {:snapshot_started, shape_handle}) + if not acc do + # The stream has been read to the end but we haven't seen a single item in + # it. Notify `consumer` anyway since an empty file will have been created by + # the storage implementation for the API layer to read the snapshot data + # from. + send(task_parent, :data_received) + GenServer.cast(consumer, {:snapshot_started, shape_handle}) + end + + {[], acc} + end, + fn acc -> + # noop after fun just to be able to specify the last fun which is only + # available in `Stream.transoform/5`. acc end ) + |> Stream.concat([finishing_control_message]) - # could pass the shape and then make_new_snapshot! can pass it to row_to_snapshot_item - # that way it has the relation, but it is still missing the pk_cols Storage.make_new_snapshot!(stream, storage) end, timeout: :infinity ) end + defp storage_dir(stack_id) do + Path.join([System.tmp_dir!(), "#{inspect(__MODULE__)}_#{stack_id}"]) + end + def config(stack_id, repo, owner \\ nil) do publication_manager_spec = {Sandbox.PublicationManager, stack_id: stack_id, owner: owner, repo: repo} @@ -79,28 +124,23 @@ if Phoenix.Sync.sandbox_enabled?() do %{pid: pool} = Ecto.Adapter.lookup_meta(repo.get_dynamic_repo()) - registry = :"#{__MODULE__}.Registry-#{stack_id}" + registry = Electric.StackSupervisor.registry_name(stack_id) + + storage_dir = storage_dir(stack_id) storage = { - Electric.ShapeCache.InMemoryStorage, - %{stack_id: stack_id, table_base_name: :"#{stack_id}"} + Electric.ShapeCache.PureFileStorage, + [stack_id: stack_id, storage_dir: storage_dir] } [ - purge_all_shapes?: false, stack_id: stack_id, storage: storage, - shape_status: - {Electric.ShapeCache.ShapeStatus, - Electric.ShapeCache.ShapeStatus.opts( - shape_meta_table: Electric.ShapeCache.ShapeStatus.shape_meta_table(stack_id), - storage: storage - )}, + storage_dir: storage_dir, inspector: inspector, publication_manager: publication_manager_spec, chunk_bytes_threshold: 10_485_760, db_pool: pool, - create_snapshot_fn: &snapshot_query/7, log_producer: Electric.Replication.ShapeLogCollector.name(stack_id), consumer_supervisor: Electric.Shapes.DynamicConsumerSupervisor.name(stack_id), registry: registry, @@ -110,47 +150,65 @@ if Phoenix.Sync.sandbox_enabled?() do def init({stack_id, repo, owner}) do config = config(stack_id, repo, owner) - shape_cache_spec = {Electric.ShapeCache, config} + shape_cache_spec = {Electric.ShapeCache, stack_id: stack_id} persistent_kv = Electric.PersistentKV.Memory.new!() - shape_status_owner_spec = - {Electric.ShapeCache.ShapeStatusOwner, - [stack_id: stack_id, shape_status: config[:shape_status]]} + storage = Storage.shared_opts(config[:storage]) - consumer_supervisor_spec = {Electric.Shapes.DynamicConsumerSupervisor, [stack_id: stack_id]} + create_snapshot_fn = fn task_parent, consumer, shape_handle, shape, ctx -> + snapshot_query(task_parent, consumer, shape_handle, shape, ctx, config[:db_pool]) + end children = [ + {Sandbox.Cleanup, {stack_id, config[:storage_dir]}}, + {Electric.ProcessRegistry, partitions: 1, stack_id: stack_id}, {Registry, keys: :duplicate, name: config[:registry]}, - {Electric.ProcessRegistry, stack_id: stack_id}, - {Electric.StatusMonitor, stack_id}, - {Electric.Shapes.Monitor, + {Electric.StackConfig, + stack_id: stack_id, + seed_config: [ + inspector: config[:inspector], + create_snapshot_fn: create_snapshot_fn + ]}, + {Electric.AsyncDeleter, stack_id: stack_id, - storage: config[:storage], - shape_status: config[:shape_status], - publication_manager: config[:publication_manager]}, - # TODO: start an electric stack, decoupled from the db connection - # with in memory storage, a mock publication_manager and inspector + storage_dir: config[:storage_dir], + cleanup_interval_ms: :timer.seconds(60)}, + Storage.stack_child_spec(storage), + {Electric.ShapeCache.ShapeStatusOwner, stack_id: stack_id}, + {Electric.StatusMonitor, stack_id: stack_id}, + {Electric.ShapeCache.ShapeStatus.ShapeDb.Supervisor, + Keyword.take(config, [:stack_id, :storage_dir])}, + {Sandbox.Inspector, stack_id: stack_id, repo: repo, owner: owner}, + {DynamicSupervisor, + name: Phoenix.Sync.Sandbox.Fetch.name(stack_id), strategy: :one_for_one}, Supervisor.child_spec( { - Electric.Replication.Supervisor, + Electric.Shapes.Supervisor, stack_id: stack_id, - shape_status_owner: shape_status_owner_spec, + consumer_supervisor: {Electric.Shapes.DynamicConsumerSupervisor, stack_id: stack_id}, + shape_cleaner: + {Electric.ShapeCache.ShapeCleaner.CleanupTaskSupervisor, stack_id: stack_id}, shape_cache: shape_cache_spec, publication_manager: config[:publication_manager], - consumer_supervisor: consumer_supervisor_spec, log_collector: { - Electric.Replication.ShapeLogCollector, + Electric.Replication.ShapeLogCollector.Supervisor, stack_id: stack_id, inspector: config[:inspector], persistent_kv: persistent_kv }, schema_reconciler: {Phoenix.Sync.Sandbox.SchemaReconciler, stack_id}, - stack_events_registry: config[:registry] + expiry_manager: {Phoenix.Sync.Sandbox.ExpiryManager, stack_id: stack_id} }, restart: :temporary ), - {Sandbox.Inspector, stack_id: stack_id, repo: repo}, {Sandbox.Producer, stack_id: stack_id}, - {DynamicSupervisor, - name: Phoenix.Sync.Sandbox.Fetch.name(stack_id), strategy: :one_for_one} + {Agent, + fn -> + :ok = Electric.ShapeCache.ShapeStatusOwner.initialize(stack_id) + + Electric.LsnTracker.set_last_processed_lsn( + stack_id, + Electric.Postgres.Lsn.from_integer(0) + ) + end} ] Supervisor.init(children, strategy: :one_for_one) diff --git a/mix.exs b/mix.exs index 8060362..c951d77 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,8 @@ defmodule Phoenix.Sync.MixProject do # Remember to update the README when you change the version @version "0.6.1" - @electric_version ">= 1.1.9 and <= 1.1.10" + # @electric_version ">= 1.1.9 and <= 1.1.10" + @electric_version "~> 1.2.4" def project do [ @@ -45,8 +46,15 @@ defmodule Phoenix.Sync.MixProject do {:plug, "~> 1.0"}, {:jason, "~> 1.0"}, {:ecto_sql, "~> 3.10", optional: true}, - {:electric, @electric_version, optional: true}, - {:electric_client, "~> 0.7.2"}, + # {:electric, @electric_version, optional: true}, + # {:electric, path: "../electric-main/packages/sync-service", override: true, optional: true}, + {:electric, + github: "electric-sql/electric", + sparse: "packages/sync-service", + ref: "029e92ba8e1329aeb3d479549886c6b21975f09a", + override: true, + optional: true}, + {:electric_client, "~> 0.8.0-beta-1"}, {:igniter, "~> 0.6", optional: true} ] ++ deps_for_env(Mix.env()) ++ json_deps() end diff --git a/mix.lock b/mix.lock index 3be4935..14d4dee 100644 --- a/mix.lock +++ b/mix.lock @@ -1,7 +1,7 @@ %{ - "acceptor_pool": {:hex, :acceptor_pool, "1.0.0", "43c20d2acae35f0c2bcd64f9d2bde267e459f0f3fd23dab26485bf518c281b21", [:rebar3], [], "hexpm", "0cbcd83fdc8b9ad2eee2067ef8b91a14858a5883cb7cd800e6fcd5803e158788"}, + "acceptor_pool": {:hex, :acceptor_pool, "1.0.1", "d88c2e8a0be9216cf513fbcd3e5a4beb36bee3ff4168e85d6152c6f899359cdb", [:rebar3], [], "hexpm", "f172f3d74513e8edd445c257d596fc84dbdd56d2c6fa287434269648ae5a421e"}, "backoff": {:hex, :backoff, "1.1.6", "83b72ed2108ba1ee8f7d1c22e0b4a00cfe3593a67dbc792799e8cce9f42f796b", [:rebar3], [], "hexpm", "cf0cfff8995fb20562f822e5cc47d8ccf664c5ecdc26a684cbe85c225f9d7c39"}, - "bandit": {:hex, :bandit, "1.8.0", "c2e93d7e3c5c794272fa4623124f827c6f24b643acc822be64c826f9447d92fb", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "8458ff4eed20ff2a2ea69d4854883a077c33ea42b51f6811b044ceee0fa15422"}, + "bandit": {:hex, :bandit, "1.10.1", "6b1f8609d947ae2a74da5bba8aee938c94348634e54e5625eef622ca0bbbb062", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "4b4c35f273030e44268ace53bf3d5991dfc385c77374244e2f960876547671aa"}, "castore": {:hex, :castore, "1.0.14", "4582dd7d630b48cf5e1ca8d3d42494db51e406b7ba704e81fbd401866366896a", [:mix], [], "hexpm", "7bc1b65249d31701393edaaac18ec8398d8974d52c647b7904d01b964137b9f4"}, "cc_precompiler": {:hex, :cc_precompiler, "0.1.10", "47c9c08d8869cf09b41da36538f62bc1abd3e19e41701c2cea2675b53c704258", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f6e046254e53cd6b41c6bacd70ae728011aa82b2742a80d6e2214855c6e06b22"}, "chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"}, @@ -10,16 +10,17 @@ "db_connection": {:hex, :db_connection, "2.8.1", "9abdc1e68c34c6163f6fb96a96532272d13ad7ca45262156ae8b7ec6d9dc4bec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a61a3d489b239d76f326e03b98794fb8e45168396c925ef25feb405ed09da8fd"}, "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, "dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"}, - "dotenvy": {:hex, :dotenvy, "1.1.0", "316aee89c11a4ec8be3d74a69d17d17ea2e21e633e0cac9f155cf420e237ccb4", [:mix], [], "hexpm", "0519bda67fdfa1c22279c2654b2f292485f0caae7360fe29205f74f28a93df18"}, + "dotenvy": {:hex, :dotenvy, "1.1.1", "00e318f3c51de9fafc4b48598447e386f19204dc18ca69886905bb8f8b08b667", [:mix], [], "hexpm", "c8269471b5701e9e56dc86509c1199ded2b33dce088c3471afcfef7839766d8e"}, "earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"}, - "ecto": {:hex, :ecto, "3.13.3", "6a983f0917f8bdc7a89e96f2bf013f220503a0da5d8623224ba987515b3f0d80", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1927db768f53a88843ff25b6ba7946599a8ca8a055f69ad8058a1432a399af94"}, + "ecto": {:hex, :ecto, "3.13.5", "9d4a69700183f33bf97208294768e561f5c7f1ecf417e0fa1006e4a91713a834", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "df9efebf70cf94142739ba357499661ef5dbb559ef902b68ea1f3c1fabce36de"}, "ecto_sql": {:hex, :ecto_sql, "3.13.2", "a07d2461d84107b3d037097c822ffdd36ed69d1cf7c0f70e12a3d1decf04e2e1", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "539274ab0ecf1a0078a6a72ef3465629e4d6018a3028095dc90f60a19c371717"}, - "electric": {:hex, :electric, "1.1.10", "db6a4b714d711b754aff68b456bd4065c83494277cce2143dff9a9b39273c463", [:mix], [{:backoff, "~> 1.1", [hex: :backoff, repo: "hexpm", optional: false]}, {:bandit, "~> 1.6", [hex: :bandit, repo: "hexpm", optional: false]}, {:dotenvy, "~> 1.1", [hex: :dotenvy, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:electric_cubdb, "~> 2.0", [hex: :electric_cubdb, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:opentelemetry, "~> 1.5", [hex: :opentelemetry, repo: "hexpm", optional: true]}, {:opentelemetry_exporter, "~> 1.8", [hex: :opentelemetry_exporter, repo: "hexpm", optional: true]}, {:opentelemetry_semantic_conventions, "~> 1.27", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: false]}, {:opentelemetry_telemetry, "~> 1.1", [hex: :opentelemetry_telemetry, repo: "hexpm", optional: false]}, {:otel_metric_exporter, "~> 0.3.11", [hex: :otel_metric_exporter, repo: "hexpm", optional: true]}, {:pg_query_ex, "0.9.0", [hex: :pg_query_ex, repo: "hexpm", optional: false]}, {:plug, "~> 1.17", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.20", [hex: :postgrex, repo: "hexpm", optional: false]}, {:remote_ip, "~> 1.2", [hex: :remote_ip, repo: "hexpm", optional: false]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:retry, "~> 0.19", [hex: :retry, repo: "hexpm", optional: false]}, {:sentry, "~> 11.0", [hex: :sentry, repo: "hexpm", optional: true]}, {:stream_split, "~> 0.1", [hex: :stream_split, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.1", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: true]}, {:telemetry_metrics_statsd, "~> 0.7", [hex: :telemetry_metrics_statsd, repo: "hexpm", optional: true]}, {:telemetry_poller, "~> 1.2", [hex: :telemetry_poller, repo: "hexpm", optional: false]}, {:tls_certificate_check, "~> 1.27", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}, {:tz, "~> 0.28", [hex: :tz, repo: "hexpm", optional: false]}], "hexpm", "e62ba80b4104405490a72d09844fcf040d5da779340e212ac52804ffc1f7b46d"}, - "electric_client": {:hex, :electric_client, "0.7.2", "06f221fa7379d41ab4fb771c9cf78f26654d7c265f61faffa8c31e6b73073224", [:mix], [{:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:electric, "~> 1.1.1", [hex: :electric, repo: "hexpm", optional: true]}, {:gen_stage, "~> 1.2", [hex: :gen_stage, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}], "hexpm", "4036796cc21767917f1c1c72541b0865a5585b9b4a59ccdb15b99af9c457c97e"}, + "electric": {:git, "https://github.com/electric-sql/electric.git", "1e51dd3857479e4c55eff22cc14dc1e0ac65dd78", [sparse: "packages/sync-service", ref: "1e51dd3857479e4c55eff22cc14dc1e0ac65dd78"]}, + "electric_client": {:hex, :electric_client, "0.8.0-beta-1", "d5fb545d429ff0985ab5151aa27d1848f0944d9222daf40a202093552ad54cc7", [:mix], [{:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:electric, "~> 1.1.11 or ~> 1.2.4", [hex: :electric, repo: "hexpm", optional: true]}, {:gen_stage, "~> 1.2", [hex: :gen_stage, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}], "hexpm", "32c4d7b8127b1248d1dfb6f94eaab05cf5a3b778f47241718ad0dd91c5289b49"}, "electric_cubdb": {:hex, :electric_cubdb, "2.0.2", "36f86e3c52dc26f4e077a49fbef813b1a38d3897421cece851f149190b34c16c", [:mix], [], "hexpm", "0c0e24b31fb76ad1b33c5de2ab35c41a4ff9da153f5c1f9b15e2de78575acaf2"}, "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, "ex_doc": {:hex, :ex_doc, "0.37.3", "f7816881a443cd77872b7d6118e8a55f547f49903aef8747dbcb345a75b462f9", [:mix], [{:earmark_parser, "~> 1.4.42", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "e6aebca7156e7c29b5da4daa17f6361205b2ae5f26e5c7d8ca0d3f7e18972233"}, + "exqlite": {:hex, :exqlite, "0.34.0", "ebca3570eb4c4eb4345d76c8e44ce31a62de7b24a54fd118164480f2954bd540", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "bcdc58879a0db5e08cd5f6fbe07a0692ceffaaaa617eab46b506137edf0a2742"}, "finch": {:hex, :finch, "0.20.0", "5330aefb6b010f424dcbbc4615d914e9e3deae40095e73ab0c1bb0968933cadf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2658131a74d051aabfcba936093c903b8e89da9a1b63e430bee62045fa9b2ee2"}, "fine": {:hex, :fine, "0.1.2", "85cf7dd190c7c6c54c2840754ae977c9acc0417316255b674fad9f2678e4ecc7", [:mix], [], "hexpm", "9113531982c2b60dbea6c7233917ddf16806947cd7104b5d03011bf436ca3072"}, "floki": {:hex, :floki, "0.38.0", "62b642386fa3f2f90713f6e231da0fa3256e41ef1089f83b6ceac7a3fd3abf33", [:mix], [], "hexpm", "a5943ee91e93fb2d635b612caf5508e36d37548e84928463ef9dd986f0d1abd9"}, @@ -29,7 +30,7 @@ "grpcbox": {:hex, :grpcbox, "0.17.1", "6e040ab3ef16fe699ffb513b0ef8e2e896da7b18931a1ef817143037c454bcce", [:rebar3], [{:acceptor_pool, "~> 1.0.0", [hex: :acceptor_pool, repo: "hexpm", optional: false]}, {:chatterbox, "~> 0.15.1", [hex: :ts_chatterbox, repo: "hexpm", optional: false]}, {:ctx, "~> 0.6.0", [hex: :ctx, repo: "hexpm", optional: false]}, {:gproc, "~> 0.9.1", [hex: :gproc, repo: "hexpm", optional: false]}], "hexpm", "4a3b5d7111daabc569dc9cbd9b202a3237d81c80bf97212fbc676832cb0ceb17"}, "hpack": {:hex, :hpack_erl, "0.3.0", "2461899cc4ab6a0ef8e970c1661c5fc6a52d3c25580bc6dd204f84ce94669926", [:rebar3], [], "hexpm", "d6137d7079169d8c485c6962dfe261af5b9ef60fbc557344511c1e65e3d95fb0"}, "hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"}, - "igniter": {:hex, :igniter, "0.6.30", "83a466369ebb8fe009e0823c7bf04314dc545122c2d48f896172fc79df33e99d", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "76a14d5b7f850bb03b5243088c3649d54a2e52e34a2aa1104dee23cf50a8bae0"}, + "igniter": {:hex, :igniter, "0.7.0", "6848714fa5afa14258c82924a57af9364745316241a409435cf39cbe11e3ae80", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "1e7254780dbf4b44c9eccd6d86d47aa961efc298d7f520c24acb0258c8e90ba9"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "lazy_html": {:hex, :lazy_html, "0.1.3", "8b9c8c135e95f7bc483de6195c4e1c0b2c913a5e2c57353ef4e82703b7ac8bd1", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.9.0", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1.0", [hex: :fine, repo: "hexpm", optional: false]}], "hexpm", "5f96f29587dcfed8a22281e8c44c6607e958ba821d90b9dfc003d1ef610f7d07"}, "makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"}, @@ -40,32 +41,32 @@ "mint": {:hex, :mint, "1.7.1", "113fdb2b2f3b59e47c7955971854641c61f378549d73e829e1768de90fc1abf1", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b"}, "mox": {:hex, :mox, "1.2.0", "a2cd96b4b80a3883e3100a221e8adc1b98e4c3a332a8fc434c39526babafd5b3", [:mix], [{:nimble_ownership, "~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}], "hexpm", "c7b92b3cc69ee24a7eeeaf944cd7be22013c52fcb580c1f33f50845ec821089a"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, - "nimble_ownership": {:hex, :nimble_ownership, "1.0.1", "f69fae0cdd451b1614364013544e66e4f5d25f36a2056a9698b793305c5aa3a6", [:mix], [], "hexpm", "3825e461025464f519f3f3e4a1f9b68c47dc151369611629ad08b636b73bb22d"}, + "nimble_ownership": {:hex, :nimble_ownership, "1.0.2", "fa8a6f2d8c592ad4d79b2ca617473c6aefd5869abfa02563a77682038bf916cf", [:mix], [], "hexpm", "098af64e1f6f8609c6672127cfe9e9590a5d3fcdd82bc17a377b8692fd81a879"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, - "opentelemetry": {:hex, :opentelemetry, "1.5.0", "7dda6551edfc3050ea4b0b40c0d2570423d6372b97e9c60793263ef62c53c3c2", [:rebar3], [{:opentelemetry_api, "~> 1.4", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}], "hexpm", "cdf4f51d17b592fc592b9a75f86a6f808c23044ba7cf7b9534debbcc5c23b0ee"}, - "opentelemetry_api": {:hex, :opentelemetry_api, "1.4.1", "e071429a37441a0fe9097eeea0ff921ebadce8eba8e1ce297b05a43c7a0d121f", [:mix, :rebar3], [], "hexpm", "39bdb6ad740bc13b16215cb9f233d66796bbae897f3bf6eb77abb712e87c3c26"}, - "opentelemetry_exporter": {:hex, :opentelemetry_exporter, "1.8.0", "5d546123230771ef4174e37bedfd77e3374913304cd6ea3ca82a2add49cd5d56", [:rebar3], [{:grpcbox, ">= 0.0.0", [hex: :grpcbox, repo: "hexpm", optional: false]}, {:opentelemetry, "~> 1.5.0", [hex: :opentelemetry, repo: "hexpm", optional: false]}, {:opentelemetry_api, "~> 1.4.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:tls_certificate_check, "~> 1.18", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "a1f9f271f8d3b02b81462a6bfef7075fd8457fdb06adff5d2537df5e2264d9af"}, + "opentelemetry": {:hex, :opentelemetry, "1.7.0", "20d0f12d3d1c398d3670fd44fd1a7c495dd748ab3e5b692a7906662e2fb1a38a", [:rebar3], [{:opentelemetry_api, "~> 1.5.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}], "hexpm", "a9173b058c4549bf824cbc2f1d2fa2adc5cdedc22aa3f0f826951187bbd53131"}, + "opentelemetry_api": {:hex, :opentelemetry_api, "1.5.0", "1a676f3e3340cab81c763e939a42e11a70c22863f645aa06aafefc689b5550cf", [:mix, :rebar3], [], "hexpm", "f53ec8a1337ae4a487d43ac89da4bd3a3c99ddf576655d071deed8b56a2d5dda"}, + "opentelemetry_exporter": {:hex, :opentelemetry_exporter, "1.10.0", "972e142392dbfa679ec959914664adefea38399e4f56ceba5c473e1cabdbad79", [:rebar3], [{:grpcbox, ">= 0.0.0", [hex: :grpcbox, repo: "hexpm", optional: false]}, {:opentelemetry, "~> 1.7.0", [hex: :opentelemetry, repo: "hexpm", optional: false]}, {:opentelemetry_api, "~> 1.5.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:tls_certificate_check, "~> 1.18", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "33a116ed7304cb91783f779dec02478f887c87988077bfd72840f760b8d4b952"}, "opentelemetry_semantic_conventions": {:hex, :opentelemetry_semantic_conventions, "1.27.0", "acd0194a94a1e57d63da982ee9f4a9f88834ae0b31b0bd850815fe9be4bbb45f", [:mix, :rebar3], [], "hexpm", "9681ccaa24fd3d810b4461581717661fd85ff7019b082c2dff89c7d5b1fc2864"}, "opentelemetry_telemetry": {:hex, :opentelemetry_telemetry, "1.1.2", "410ab4d76b0921f42dbccbe5a7c831b8125282850be649ee1f70050d3961118a", [:mix, :rebar3], [{:opentelemetry_api, "~> 1.3", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "641ab469deb181957ac6d59bce6e1321d5fe2a56df444fc9c19afcad623ab253"}, - "otel_metric_exporter": {:hex, :otel_metric_exporter, "0.2.5", "8b9e9253c85202ac47f4c1c16c4496e093b12d4afe11292c7e58a03e943e24c0", [:mix], [{:finch, "~> 0.19", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:protobuf, "~> 0.13.0", [hex: :protobuf, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "66f697a4aff251ba50a58564eb11efeed61aacbae12f151ba9a80bd87c92323e"}, + "otel_metric_exporter": {:hex, :otel_metric_exporter, "0.4.3", "c8e47eae9f222e100b590eb95246e49ea4a376bf3595067ee089ddfc7169405a", [:mix], [{:finch, "~> 0.19", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:protobuf, "~> 0.15", [hex: :protobuf, repo: "hexpm", optional: false]}, {:retry, "~> 0.19", [hex: :retry, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "6cdb0a9bcd6f4bee3e70b7b8664af8b6d23156e978ccedde47782f56b6636531"}, "owl": {:hex, :owl, "0.13.0", "26010e066d5992774268f3163506972ddac0a7e77bfe57fa42a250f24d6b876e", [:mix], [{:ucwidth, "~> 0.2", [hex: :ucwidth, repo: "hexpm", optional: true]}], "hexpm", "59bf9d11ce37a4db98f57cb68fbfd61593bf419ec4ed302852b6683d3d2f7475"}, "pg_query_ex": {:hex, :pg_query_ex, "0.9.0", "8e34bd2d0e0eb9e8d621c4697032fad4bfba46826950d3b46904a80ab589b43a", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:protox, "~> 2.0", [hex: :protox, repo: "hexpm", optional: false]}], "hexpm", "a3fada1704fa9e2bc11ff846ad545ef9a1d34f46d86206063c37128960f4f5f5"}, - "phoenix": {:hex, :phoenix, "1.8.1", "865473a60a979551a4879db79fbfb4503e41cd809e77c85af79716578b6a456d", [:mix], [{:bandit, "~> 1.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "84d77d2b2e77c3c7e7527099bd01ef5c8560cd149c036d6b3a40745f11cd2fb2"}, + "phoenix": {:hex, :phoenix, "1.8.3", "49ac5e485083cb1495a905e47eb554277bdd9c65ccb4fc5100306b350151aa95", [:mix], [{:bandit, "~> 1.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "36169f95cc2e155b78be93d9590acc3f462f1e5438db06e6248613f27c80caec"}, "phoenix_html": {:hex, :phoenix_html, "4.3.0", "d3577a5df4b6954cd7890c84d955c470b5310bb49647f0a114a6eeecc850f7ad", [:mix], [], "hexpm", "3eaa290a78bab0f075f791a46a981bbe769d94bc776869f4f3063a14f30497ad"}, - "phoenix_live_view": {:hex, :phoenix_live_view, "1.1.14", "cae84abc4cd00dde4bb200b8516db556704c585c267aff9cd4955ff83cceb86c", [:mix], [{:igniter, ">= 0.6.16 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:lazy_html, "~> 0.1.0", [hex: :lazy_html, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b827980e2bc00fddd8674e3b567519a4e855b5de04bf8607140414f1101e2627"}, - "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "1.1.19", "c95e9acbc374fb796ee3e24bfecc8213123c74d9f9e45667ca40bb0a4d242953", [:mix], [{:igniter, ">= 0.6.16 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:lazy_html, "~> 0.1.0", [hex: :lazy_html, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d5ad357d6b21562a5b431f0ad09dfe76db9ce5648c6949f1aac334c8c4455d32"}, + "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.2.0", "ff3a5616e1bed6804de7773b92cbccfc0b0f473faf1f63d7daf1206c7aeaaa6f", [:mix], [], "hexpm", "adc313a5bf7136039f63cfd9668fde73bba0765e0614cba80c06ac9460ff3e96"}, "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, - "plug": {:hex, :plug, "1.18.1", "5067f26f7745b7e31bc3368bc1a2b818b9779faa959b49c934c17730efc911cf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "57a57db70df2b422b564437d2d33cf8d33cd16339c1edb190cd11b1a3a546cc2"}, + "plug": {:hex, :plug, "1.19.1", "09bac17ae7a001a68ae393658aa23c7e38782be5c5c00c80be82901262c394c0", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "560a0017a8f6d5d30146916862aaf9300b7280063651dd7e532b8be168511e62"}, "plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"}, "postgrex": {:hex, :postgrex, "0.21.1", "2c5cc830ec11e7a0067dd4d623c049b3ef807e9507a424985b8dcf921224cd88", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "27d8d21c103c3cc68851b533ff99eef353e6a0ff98dc444ea751de43eb48bdac"}, "protobuf": {:hex, :protobuf, "0.13.0", "7a9d9aeb039f68a81717eb2efd6928fdf44f03d2c0dfdcedc7b560f5f5aae93d", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "21092a223e3c6c144c1a291ab082a7ead32821ba77073b72c68515aa51fef570"}, "protox": {:hex, :protox, "2.0.4", "2a86ae3699696c5d92e15804968ce6a6827a8d9516d0bbabcf16584dec710ae1", [:mix], [], "hexpm", "8ac5a03bb84da4c75d76dc29cd46008081c2068ad0f6f0da4c051093d6e24c01"}, "remote_ip": {:hex, :remote_ip, "1.2.0", "fb078e12a44414f4cef5a75963c33008fe169b806572ccd17257c208a7bc760f", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2ff91de19c48149ce19ed230a81d377186e4412552a597d6a5137373e5877cb7"}, - "req": {:hex, :req, "0.5.15", "662020efb6ea60b9f0e0fac9be88cd7558b53fe51155a2d9899de594f9906ba9", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "a6513a35fad65467893ced9785457e91693352c70b58bbc045b47e5eb2ef0c53"}, + "req": {:hex, :req, "0.5.17", "0096ddd5b0ed6f576a03dde4b158a0c727215b15d2795e59e0916c6971066ede", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0b8bc6ffdfebbc07968e59d3ff96d52f2202d0536f10fef4dc11dc02a2a43e39"}, "retry": {:hex, :retry, "0.19.0", "aeb326d87f62295d950f41e1255fe6f43280a1b390d36e280b7c9b00601ccbc2", [:mix], [], "hexpm", "85ef376aa60007e7bff565c366310966ec1bd38078765a0e7f20ec8a220d02ca"}, "rewrite": {:hex, :rewrite, "1.2.0", "80220eb14010e175b67c939397e1a8cdaa2c32db6e2e0a9d5e23e45c0414ce21", [:mix], [{:glob_ex, "~> 0.1", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}, {:text_diff, "~> 0.1", [hex: :text_diff, repo: "hexpm", optional: false]}], "hexpm", "a1cd702bbb9d51613ab21091f04a386d750fc6f4516b81900df082d78b2d8c50"}, - "sentry": {:hex, :sentry, "10.8.1", "aa45309785e1521416225adb16e0b4d8b957578804527f3c7babb6fefbc5e456", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0 or ~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "495b3cdadad90ba72eef973aa3dec39b3b8b2a362fe87e2f4ef32133ac3b4097"}, + "sentry": {:hex, :sentry, "11.0.4", "60371c96cefd247e0fc98840bba2648f64f19aa0b8db8e938f5a98421f55b619", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:igniter, "~> 0.5", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0 or ~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:opentelemetry, ">= 0.0.0", [hex: :opentelemetry, repo: "hexpm", optional: true]}, {:opentelemetry_api, ">= 0.0.0", [hex: :opentelemetry_api, repo: "hexpm", optional: true]}, {:opentelemetry_exporter, ">= 0.0.0", [hex: :opentelemetry_exporter, repo: "hexpm", optional: true]}, {:opentelemetry_semantic_conventions, ">= 0.0.0", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "feaafc284dc204c82aadaddc884227aeaa3480decb274d30e184b9d41a700c66"}, "sourceror": {:hex, :sourceror, "1.10.0", "38397dedbbc286966ec48c7af13e228b171332be1ad731974438c77791945ce9", [:mix], [], "hexpm", "29dbdfc92e04569c9d8e6efdc422fc1d815f4bd0055dc7c51b8800fb75c4b3f1"}, "spitfire": {:hex, :spitfire, "0.2.1", "29e154873f05444669c7453d3d931820822cbca5170e88f0f8faa1de74a79b47", [:mix], [], "hexpm", "6eeed75054a38341b2e1814d41bb0a250564092358de2669fdb57ff88141d91b"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, @@ -73,13 +74,13 @@ "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"}, "telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.2.1", "c9755987d7b959b557084e6990990cb96a50d6482c683fb9622a63837f3cd3d8", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "5e2c599da4983c4f88a33e9571f1458bf98b0cf6ba930f1dc3a6e8cf45d5afb6"}, - "telemetry_metrics_statsd": {:hex, :telemetry_metrics_statsd, "0.7.1", "3502235bb5b35ce50d608bf0f34369ef76eb92a4dbc8708c7e8780ca0da2d53e", [:mix], [{:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "06338d9dc3b4a202f11a6e706fd3feba4c46100d0aca23688dea0b8f801c361f"}, + "telemetry_metrics_statsd": {:hex, :telemetry_metrics_statsd, "0.7.2", "a70cfaf821cb2f3ac2e767988461179add44762d1db752e74dfa0c93449b2857", [:mix], [{:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "933bb8b176b95d5088404b7137d94926b8dea9a74ef2c95d616f2740f1571c13"}, "telemetry_poller": {:hex, :telemetry_poller, "1.3.0", "d5c46420126b5ac2d72bc6580fb4f537d35e851cc0f8dbd571acf6d6e10f5ec7", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "51f18bed7128544a50f75897db9974436ea9bfba560420b646af27a9a9b35211"}, "text_diff": {:hex, :text_diff, "0.1.0", "1caf3175e11a53a9a139bc9339bd607c47b9e376b073d4571c031913317fecaa", [:mix], [], "hexpm", "d1ffaaecab338e49357b6daa82e435f877e0649041ace7755583a0ea3362dbd7"}, - "thousand_island": {:hex, :thousand_island, "1.4.1", "8df065e627407e281f7935da5ad0f3842d10eb721afa92e760b720d71e2e37aa", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "204a8640e5d2818589b87286ae66160978628d7edf6095181cbe0440765fb6c1"}, - "tls_certificate_check": {:hex, :tls_certificate_check, "1.29.0", "4473005eb0bbdad215d7083a230e2e076f538d9ea472c8009fd22006a4cfc5f6", [:rebar3], [{:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "5b0d0e5cb0f928bc4f210df667304ed91c5bff2a391ce6bdedfbfe70a8f096c5"}, + "thousand_island": {:hex, :thousand_island, "1.4.3", "2158209580f633be38d43ec4e3ce0a01079592b9657afff9080d5d8ca149a3af", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6e4ce09b0fd761a58594d02814d40f77daff460c48a7354a15ab353bb998ea0b"}, + "tls_certificate_check": {:hex, :tls_certificate_check, "1.31.0", "9a910b54d8cb96cc810cabf4c0129f21360f82022b20180849f1442a25ccbb04", [:rebar3], [{:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "9d2b41b128d5507bd8ad93e1a998e06d0ab2f9a772af343f4c00bf76c6be1532"}, "tz": {:hex, :tz, "0.28.1", "717f5ffddfd1e475e2a233e221dc0b4b76c35c4b3650b060c8e3ba29dd6632e9", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:mint, "~> 1.6", [hex: :mint, repo: "hexpm", optional: true]}], "hexpm", "bfdca1aa1902643c6c43b77c1fb0cb3d744fd2f09a8a98405468afdee0848c8a"}, "uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [:mix], [], "hexpm", "c790593b4c3b601f5dc2378baae7efaf5b3d73c4c6456ba85759905be792f2ac"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, - "websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"}, + "websock_adapter": {:hex, :websock_adapter, "0.5.9", "43dc3ba6d89ef5dec5b1d0a39698436a1e856d000d84bf31a3149862b01a287f", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "5534d5c9adad3c18a0f58a9371220d75a803bf0b9a3d87e6fe072faaeed76a08"}, } diff --git a/test/phoenix/sync/application_test.exs b/test/phoenix/sync/application_test.exs index f55d701..8c441af 100644 --- a/test/phoenix/sync/application_test.exs +++ b/test/phoenix/sync/application_test.exs @@ -340,10 +340,7 @@ defmodule Phoenix.Sync.ApplicationTest do api = App.plug_opts(config) - assert %Electric.Shapes.Api{ - storage: {Electric.ShapeCache.PureFileStorage, %{base_path: ^storage_dir <> _}}, - persistent_kv: %Electric.PersistentKV.Filesystem{root: ^storage_dir} - } = api + assert %Electric.Shapes.Api{stack_id: "electric-embedded"} = api end test "remote http mode" do diff --git a/test/phoenix/sync/controller_test.exs b/test/phoenix/sync/controller_test.exs index e4ae068..26a59f4 100644 --- a/test/phoenix/sync/controller_test.exs +++ b/test/phoenix/sync/controller_test.exs @@ -128,7 +128,8 @@ defmodule Phoenix.Sync.ControllerTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -151,7 +152,8 @@ defmodule Phoenix.Sync.ControllerTest do assert Plug.Conn.get_resp_header(resp, "electric-offset") == ["0_0"] assert [ - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -164,7 +166,8 @@ defmodule Phoenix.Sync.ControllerTest do assert Plug.Conn.get_resp_header(resp, "electric-offset") == ["0_0"] assert [ - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) resp = @@ -176,7 +179,8 @@ defmodule Phoenix.Sync.ControllerTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -191,7 +195,8 @@ defmodule Phoenix.Sync.ControllerTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -206,7 +211,8 @@ defmodule Phoenix.Sync.ControllerTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -220,7 +226,8 @@ defmodule Phoenix.Sync.ControllerTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -245,7 +252,8 @@ defmodule Phoenix.Sync.ControllerTest do %{ "headers" => %{"operation" => "insert"}, "value" => %{"title" => "three", "merged" => "mapping-insert-3-three"} - } + }, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -270,7 +278,8 @@ defmodule Phoenix.Sync.ControllerTest do %{ "headers" => %{"operation" => "insert"}, "value" => %{"title" => "three", "merged" => "mapping-insert-3-three"} - } + }, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -295,7 +304,8 @@ defmodule Phoenix.Sync.ControllerTest do %{ "headers" => %{"operation" => "insert"}, "value" => %{"title" => "two", "merged" => "mapping-insert-2-two"} - } + }, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -339,7 +349,8 @@ defmodule Phoenix.Sync.ControllerTest do "inserted_at" => "2025-01-02T12:34:14", "updated_at" => "2025-01-02T12:34:14" } - } + }, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end end @@ -384,7 +395,8 @@ defmodule Phoenix.Sync.ControllerTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end diff --git a/test/phoenix/sync/electric_test.exs b/test/phoenix/sync/electric_test.exs index 0683f33..ba92ad3 100644 --- a/test/phoenix/sync/electric_test.exs +++ b/test/phoenix/sync/electric_test.exs @@ -124,7 +124,8 @@ defmodule Phoenix.Sync.ElectricTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"value" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"value" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"value" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"value" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -180,7 +181,8 @@ defmodule Phoenix.Sync.ElectricTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"value" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"value" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"value" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"value" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end diff --git a/test/phoenix/sync/router_test.exs b/test/phoenix/sync/router_test.exs index c86a964..14260e0 100644 --- a/test/phoenix/sync/router_test.exs +++ b/test/phoenix/sync/router_test.exs @@ -173,7 +173,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -197,7 +198,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -222,7 +224,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -293,7 +296,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "world war"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "make tea"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "make tea"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -321,7 +325,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"food" => "peas"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"food" => "beans"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"food" => "sweetcorn"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"food" => "sweetcorn"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -349,7 +354,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) resp = @@ -362,7 +368,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) resp = @@ -375,7 +382,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) resp = @@ -388,7 +396,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -415,7 +424,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) resp = @@ -427,7 +437,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -516,7 +527,8 @@ defmodule Phoenix.Sync.RouterTest do %{ "headers" => %{"operation" => "insert"}, "value" => %{"merged" => "query-mfa-insert-2-two", "title" => "two"} - } + }, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -579,7 +591,8 @@ defmodule Phoenix.Sync.RouterTest do "inserted_at" => "2025-01-02T12:34:14", "updated_at" => "2025-01-02T12:34:14" } - } + }, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end end @@ -697,7 +710,8 @@ defmodule Phoenix.Sync.RouterTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end end @@ -723,7 +737,8 @@ defmodule Phoenix.Sync.RouterTest do %{ "headers" => %{"operation" => "insert"}, "value" => %{"merged" => "module-mfa-insert-3-three", "title" => "three"} - } + }, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -748,7 +763,8 @@ defmodule Phoenix.Sync.RouterTest do %{ "headers" => %{"operation" => "insert"}, "value" => %{"merged" => "capture-insert-3-three", "title" => "three"} - } + }, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -812,7 +828,8 @@ defmodule Phoenix.Sync.RouterTest do "inserted_at" => "2025-01-02T12:34:14", "updated_at" => "2025-01-02T12:34:14" } - } + }, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end diff --git a/test/phoenix/sync/sandbox_test.exs b/test/phoenix/sync/sandbox_test.exs index 5755c30..53225c7 100644 --- a/test/phoenix/sync/sandbox_test.exs +++ b/test/phoenix/sync/sandbox_test.exs @@ -180,7 +180,8 @@ defmodule Phoenix.Sync.SandboxTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -204,7 +205,7 @@ defmodule Phoenix.Sync.SandboxTest do Phoenix.ConnTest.build_conn() |> Phoenix.ConnTest.get("/sync/todos", %{offset: offset, handle: handle}) - assert [%{"headers" => %{"control" => "up-to-date", "global_last_seen_lsn" => "0"}}] = + assert [%{"headers" => %{"control" => "up-to-date", "global_last_seen_lsn" => "10200"}}] = Jason.decode!(resp.resp_body) [offset] = Plug.Conn.get_resp_header(resp, "electric-offset") @@ -237,7 +238,8 @@ defmodule Phoenix.Sync.SandboxTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = snapshot send(task1.pid, :request) @@ -267,7 +269,8 @@ defmodule Phoenix.Sync.SandboxTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = Jason.decode!(resp.resp_body) end @@ -292,7 +295,7 @@ defmodule Phoenix.Sync.SandboxTest do Phoenix.ConnTest.build_conn() |> Phoenix.ConnTest.get(path, %{offset: offset, handle: handle}) - assert [%{"headers" => %{"control" => "up-to-date", "global_last_seen_lsn" => "0"}}] = + assert [%{"headers" => %{"control" => "up-to-date", "global_last_seen_lsn" => "10200"}}] = Jason.decode!(resp.resp_body) [offset] = Plug.Conn.get_resp_header(resp, "electric-offset") @@ -325,7 +328,8 @@ defmodule Phoenix.Sync.SandboxTest do assert [ %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "one"}}, %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "two"}}, - %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}} + %{"headers" => %{"operation" => "insert"}, "value" => %{"title" => "three"}}, + %{"headers" => %{"control" => "snapshot-end"}} ] = snapshot send(task1.pid, :request) diff --git a/test/phoenix/sync/shape_test.exs b/test/phoenix/sync/shape_test.exs index bed283a..59bf67e 100644 --- a/test/phoenix/sync/shape_test.exs +++ b/test/phoenix/sync/shape_test.exs @@ -174,7 +174,7 @@ defmodule Support.ShapeTest do ] = Shape.to_list(pid) end - test "must refetch messages clear the state", ctx do + test "must-refetch messages clear the state", ctx do {:ok, pid} = start_shape(Support.Todo, client: ctx.client) ref = Shape.subscribe(pid, only: [:up_to_date, :must_refetch], tag: :my_sync) @@ -228,7 +228,7 @@ defmodule Support.ShapeTest do ref = Shape.subscribe(pid, only: [:up_to_date, :must_refetch], tag: :my_sync) - assert_receive {:my_sync, ^ref, :up_to_date}, 1000 + assert_receive {:my_sync, ^ref, :up_to_date}, 2000 assert [] = Shape.to_list(pid) end diff --git a/test/support/electric_helpers.ex b/test/support/electric_helpers.ex index 85ebf4c..df3c17f 100644 --- a/test/support/electric_helpers.ex +++ b/test/support/electric_helpers.ex @@ -68,10 +68,8 @@ defmodule Support.ElectricHelpers do } storage = - Electric.ShapeCache.Storage.shared_opts( - {Electric.ShapeCache.InMemoryStorage, - stack_id: stack_id, table_base_name: :"in_memory_storage_#{stack_id}"} - ) + {Electric.ShapeCache.InMemoryStorage, + stack_id: stack_id, table_base_name: :"in_memory_storage_#{stack_id}"} publication_name = "electric_test_pub_#{:erlang.phash2(stack_id)}"