diff --git a/.changeset/upgrade-elixir-rc.md b/.changeset/upgrade-elixir-rc.md new file mode 100644 index 0000000000..f781bfe001 --- /dev/null +++ b/.changeset/upgrade-elixir-rc.md @@ -0,0 +1,5 @@ +--- +'@core/sync-service': patch +--- + +Upgrade Elixir to 1.20.0-rc.3 and fix compatibility warnings (unused requires, bitstring pin operators, built-in type conflict, dead code). Also bump postgrex to 0.22.0. diff --git a/.tool-versions b/.tool-versions index c75f812127..4a14e7b1ef 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,5 +1,5 @@ caddy 2.10.0 -elixir 1.19.5 +elixir 1.20.0-rc.3-otp-28 erlang 28.4 nodejs 24.11.1 pnpm 10.12.1 diff --git a/packages/electric-telemetry/lib/electric/telemetry/stack_telemetry.ex b/packages/electric-telemetry/lib/electric/telemetry/stack_telemetry.ex index 6413382a94..df5b2a2c7a 100644 --- a/packages/electric-telemetry/lib/electric/telemetry/stack_telemetry.ex +++ b/packages/electric-telemetry/lib/electric/telemetry/stack_telemetry.ex @@ -12,8 +12,6 @@ defmodule ElectricTelemetry.StackTelemetry do alias ElectricTelemetry.Reporters - require Logger - @behaviour ElectricTelemetry.Poller def start_link(opts) do diff --git a/packages/elixir-client/lib/electric/client/ecto_adapter/postgres.ex b/packages/elixir-client/lib/electric/client/ecto_adapter/postgres.ex index 300489557c..e2db87513f 100644 --- a/packages/elixir-client/lib/electric/client/ecto_adapter/postgres.ex +++ b/packages/elixir-client/lib/electric/client/ecto_adapter/postgres.ex @@ -399,7 +399,7 @@ if Code.ensure_loaded?(Ecto) do defp bitstring_literal(value) do size = bit_size(value) - <> = value + <> = value [?b, ?', val |> Integer.to_string(2) |> String.pad_leading(size, ["0"]), ?'] end diff --git a/packages/sync-service/Dockerfile b/packages/sync-service/Dockerfile index 3df7f90457..3adc6432e2 100644 --- a/packages/sync-service/Dockerfile +++ b/packages/sync-service/Dockerfile @@ -1,4 +1,4 @@ -ARG ELIXIR_VERSION=1.19.5 +ARG ELIXIR_VERSION=1.20.0-rc.3 ARG OTP_VERSION=28.4 ARG DEBIAN_VERSION=bookworm-20260223-slim diff --git a/packages/sync-service/lib/electric/connection/manager/pool.ex b/packages/sync-service/lib/electric/connection/manager/pool.ex index 3b313c0838..578c29e386 100644 --- a/packages/sync-service/lib/electric/connection/manager/pool.ex +++ b/packages/sync-service/lib/electric/connection/manager/pool.ex @@ -229,7 +229,6 @@ defmodule Electric.Connection.Manager.Pool do state = case reason do :killed -> state - :shutdown -> state {:shutdown, exit_reason} -> %{state | last_connection_error: exit_reason} reason -> %{state | last_connection_error: reason} end diff --git a/packages/sync-service/lib/electric/replication/changes.ex b/packages/sync-service/lib/electric/replication/changes.ex index cd026a9e2f..1bf19a946e 100644 --- a/packages/sync-service/lib/electric/replication/changes.ex +++ b/packages/sync-service/lib/electric/replication/changes.ex @@ -17,7 +17,7 @@ defmodule Electric.Replication.Changes do @type db_identifier() :: String.t() @type xid() :: Xid.anyxid() @type relation_name() :: {schema :: db_identifier(), table :: db_identifier()} - @type record() :: %{(column_name :: db_identifier()) => column_data :: binary()} + @type row() :: %{(column_name :: db_identifier()) => column_data :: binary()} @type relation_id() :: non_neg_integer @typedoc """ @@ -186,7 +186,7 @@ defmodule Electric.Replication.Changes do @type t() :: %__MODULE__{ relation: Changes.relation_name(), - record: Changes.record(), + record: Changes.row(), log_offset: LogOffset.t(), key: String.t() | nil, last?: boolean(), @@ -210,8 +210,8 @@ defmodule Electric.Replication.Changes do @type t() :: %__MODULE__{ relation: Changes.relation_name(), - old_record: Changes.record() | nil, - record: Changes.record(), + old_record: Changes.row() | nil, + record: Changes.row(), log_offset: LogOffset.t(), key: String.t() | nil, old_key: String.t() | nil, @@ -258,7 +258,7 @@ defmodule Electric.Replication.Changes do @type t() :: %__MODULE__{ relation: Changes.relation_name(), - old_record: Changes.record(), + old_record: Changes.row(), log_offset: LogOffset.t(), key: String.t() | nil, move_tags: [Changes.tag()], diff --git a/packages/sync-service/lib/electric/replication/shape_log_collector.ex b/packages/sync-service/lib/electric/replication/shape_log_collector.ex index e7f423fba5..93ac892df3 100644 --- a/packages/sync-service/lib/electric/replication/shape_log_collector.ex +++ b/packages/sync-service/lib/electric/replication/shape_log_collector.ex @@ -35,7 +35,6 @@ defmodule Electric.Replication.ShapeLogCollector do import Electric.Utils, only: [map_while_ok: 2, map_if_ok: 2] - require Electric.Postgres.Lsn require Electric.Replication.LogOffset require Logger require TransactionFragment diff --git a/packages/sync-service/lib/electric/shape_cache/pure_file_storage.ex b/packages/sync-service/lib/electric/shape_cache/pure_file_storage.ex index 1b0a475782..56481df5c7 100644 --- a/packages/sync-service/lib/electric/shape_cache/pure_file_storage.ex +++ b/packages/sync-service/lib/electric/shape_cache/pure_file_storage.ex @@ -909,8 +909,8 @@ defmodule Electric.ShapeCache.PureFileStorage do with {:meta, <>} <- {:meta, IO.binread(file, 15)}, _tags = read_tags(file, tag_count), - <> <- IO.binread(file, key_size), - <> <- IO.binread(file, json_size) do + <> <- IO.binread(file, key_size), + <> <- IO.binread(file, json_size) do {[{offset, key_size, key, op_type, 0, json_size, json}], {file, LogOffset.increment(offset)}} else @@ -937,7 +937,7 @@ defmodule Electric.ShapeCache.PureFileStorage do defp read_tags(file, tag_count) do for _ <- 1..tag_count//1 do <> = IO.binread(file, 2) - <> = IO.binread(file, tag_size) + <> = IO.binread(file, tag_size) tag end end @@ -962,8 +962,8 @@ defmodule Electric.ShapeCache.PureFileStorage do with {:meta, <>} <- {:meta, IO.binread(file, 15)}, tags = read_tags(file, tag_count), - <> <- IO.binread(file, key_size), - <> <- IO.binread(file, json_size) do + <> <- IO.binread(file, key_size), + <> <- IO.binread(file, json_size) do # Check if this row should be skipped if all_parents_moved_out?(tags, tags_to_skip) or Electric.Shapes.Consumer.MoveIns.should_skip_query_row?( diff --git a/packages/sync-service/lib/electric/shape_cache/shape_status.ex b/packages/sync-service/lib/electric/shape_cache/shape_status.ex index 51e087fa60..5ec652bf9e 100644 --- a/packages/sync-service/lib/electric/shape_cache/shape_status.ex +++ b/packages/sync-service/lib/electric/shape_cache/shape_status.ex @@ -20,7 +20,6 @@ defmodule Electric.ShapeCache.ShapeStatus do import Electric, only: [is_stack_id: 1, is_shape_handle: 1] - require Electric.Shapes.Shape require Logger @type stack_id() :: Electric.stack_id() diff --git a/packages/sync-service/lib/electric/shape_cache/shape_status/shape_db/migrator.ex b/packages/sync-service/lib/electric/shape_cache/shape_status/shape_db/migrator.ex index aef60795fc..8a32c8774c 100644 --- a/packages/sync-service/lib/electric/shape_cache/shape_status/shape_db/migrator.ex +++ b/packages/sync-service/lib/electric/shape_cache/shape_status/shape_db/migrator.ex @@ -3,8 +3,6 @@ defmodule Electric.ShapeCache.ShapeStatus.ShapeDb.Migrator do alias Electric.ShapeCache.ShapeStatus.ShapeDb - require Logger - @optimization_period :timer.minutes(60) def start_link(args) do diff --git a/packages/sync-service/lib/electric/shape_cache/shape_status_owner.ex b/packages/sync-service/lib/electric/shape_cache/shape_status_owner.ex index bc9a3f9501..730405f836 100644 --- a/packages/sync-service/lib/electric/shape_cache/shape_status_owner.ex +++ b/packages/sync-service/lib/electric/shape_cache/shape_status_owner.ex @@ -12,8 +12,6 @@ defmodule Electric.ShapeCache.ShapeStatusOwner do alias Electric.ShapeCache.ShapeStatus - require Logger - @schema NimbleOptions.new!(stack_id: [type: :string, required: true]) def name(stack_id) do diff --git a/packages/sync-service/lib/electric/shapes/consumer/move_ins.ex b/packages/sync-service/lib/electric/shapes/consumer/move_ins.ex index c0c554cb70..a235bf7ffe 100644 --- a/packages/sync-service/lib/electric/shapes/consumer/move_ins.ex +++ b/packages/sync-service/lib/electric/shapes/consumer/move_ins.ex @@ -4,8 +4,6 @@ defmodule Electric.Shapes.Consumer.MoveIns do alias Electric.Postgres.Xid alias Electric.Postgres.SnapshotQuery - require Xid - defstruct waiting_move_ins: %{}, filtering_move_ins: [], touch_tracker: %{}, diff --git a/packages/sync-service/lib/electric/shapes/consumer/state.ex b/packages/sync-service/lib/electric/shapes/consumer/state.ex index 3b51de7855..ff1a31aa79 100644 --- a/packages/sync-service/lib/electric/shapes/consumer/state.ex +++ b/packages/sync-service/lib/electric/shapes/consumer/state.ex @@ -11,7 +11,6 @@ defmodule Electric.Shapes.Consumer.State do alias Electric.ShapeCache.Storage require Logger - require LogOffset @write_unit_txn :txn @write_unit_txn_fragment :txn_fragment diff --git a/packages/sync-service/lib/electric/telemetry.ex b/packages/sync-service/lib/electric/telemetry.ex index 13023a4753..3cfb299873 100644 --- a/packages/sync-service/lib/electric/telemetry.ex +++ b/packages/sync-service/lib/electric/telemetry.ex @@ -23,7 +23,7 @@ defmodule Electric.Telemetry do modules = List.wrap(dependencies) |> Enum.map(&Macro.expand(&1, env)) telemetry_code_available? = Enum.all?(modules, &Code.ensure_loaded?/1) - if Electric.telemetry_enabled?() && telemetry_code_available? do + if apply(Electric, :telemetry_enabled?, []) and telemetry_code_available? do if @log_level do Logger.log( @log_level, diff --git a/packages/sync-service/mix.exs b/packages/sync-service/mix.exs index bbc2441871..97b53f1761 100644 --- a/packages/sync-service/mix.exs +++ b/packages/sync-service/mix.exs @@ -100,7 +100,10 @@ defmodule Electric.MixProject do {:opentelemetry_semantic_conventions, "~> 1.27"}, {:pg_query_ex, "0.9.0"}, {:plug, "~> 1.17"}, - {:postgrex, "~> 0.20"}, + # TODO: Switch back to Hex once postgrex releases a version with the + # Elixir 1.20 unused-clause fix (https://github.com/elixir-ecto/postgrex/issues/760) + {:postgrex, + github: "elixir-ecto/postgrex", ref: "e4f79427e99bb0dc86376a769fc966b98edb7dfc"}, {:retry, "~> 0.19"}, {:remote_ip, "~> 1.2"}, {:req, "~> 0.5"}, diff --git a/packages/sync-service/mix.lock b/packages/sync-service/mix.lock index a69bbed739..d04178db32 100644 --- a/packages/sync-service/mix.lock +++ b/packages/sync-service/mix.lock @@ -6,7 +6,7 @@ "chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "ctx": {:hex, :ctx, "0.6.0", "8ff88b70e6400c4df90142e7f130625b82086077a45364a78d208ed3ed53c7fe", [:rebar3], [], "hexpm", "a14ed2d1b67723dbebbe423b28d7615eb0bdcba6ff28f2d1f1b0a7e1d4aa5fc2"}, - "db_connection": {:hex, :db_connection, "2.8.1", "9abdc1e68c34c6163f6fb96a96532272d13ad7ca45262156ae8b7ec6d9dc4bec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a61a3d489b239d76f326e03b98794fb8e45168396c925ef25feb405ed09da8fd"}, + "db_connection": {:hex, :db_connection, "2.9.0", "a6a97c5c958a2d7091a58a9be40caf41ab496b0701d21e1d1abff3fa27a7f371", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "17d502eacaf61829db98facf6f20808ed33da6ccf495354a41e64fe42f9c509c"}, "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, "dialyxir": {:hex, :dialyxir, "1.4.6", "7cca478334bf8307e968664343cbdb432ee95b4b68a9cba95bdabb0ad5bdfd9a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "8cf5615c5cd4c2da6c501faae642839c8405b49f8aa057ad4ae401cb808ef64d"}, "dotenvy": {:hex, :dotenvy, "1.1.0", "316aee89c11a4ec8be3d74a69d17d17ea2e21e633e0cac9f155cf420e237ccb4", [:mix], [], "hexpm", "0519bda67fdfa1c22279c2654b2f292485f0caae7360fe29205f74f28a93df18"}, @@ -43,7 +43,7 @@ "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"}, "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_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"}, + "postgrex": {:git, "https://github.com/elixir-ecto/postgrex.git", "e4f79427e99bb0dc86376a769fc966b98edb7dfc", [ref: "e4f79427e99bb0dc86376a769fc966b98edb7dfc"]}, "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"}, @@ -54,7 +54,7 @@ "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "stream_data": {:hex, :stream_data, "1.2.0", "58dd3f9e88afe27dc38bef26fce0c84a9e7a96772b2925c7b32cd2435697a52b", [:mix], [], "hexpm", "eb5c546ee3466920314643edf68943a5b14b32d1da9fe01698dc92b73f89a9ed"}, "stream_split": {:hex, :stream_split, "0.1.7", "2d3fd1fd21697da7f91926768d65f79409086052c9ec7ae593987388f52425f8", [:mix], [], "hexpm", "1dc072ff507a64404a0ad7af90df97096183fee8eeac7b300320cea7c4679147"}, - "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, + "telemetry": {:hex, :telemetry, "1.4.1", "ab6de178e2b29b58e8256b92b382ea3f590a47152ca3651ea857a6cae05ac423", [:rebar3], [], "hexpm", "2172e05a27531d3d31dd9782841065c50dd5c3c7699d95266b2edd54c2dafa1c"}, "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.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"},