Skip to content

Commit

Permalink
elixir-client: add params map to client config (#2177)
Browse files Browse the repository at this point in the history
remove explicit database_id setting from client

Fixes #2175
  • Loading branch information
magnetised authored Dec 19, 2024
1 parent 1c28aee commit 9f0b96a
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 42 deletions.
5 changes: 5 additions & 0 deletions .changeset/young-olives-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@core/elixir-client": patch
---

Add generic params to client config that are appended to every request, remove database_id top-level config as it can be done via the params.
3 changes: 2 additions & 1 deletion examples/phoenix-liveview/config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,5 @@ config :phoenix_live_view,
enable_expensive_runtime_checks: true

config :electric_phoenix, Electric.Client,
base_url: System.get_env("ELECTRIC_URL", "http://localhost:3000/")
base_url: System.get_env("ELECTRIC_URL", "http://localhost:3000/"),
params: System.get_env("ELECTRIC_CLIENT_PARAMS", "{}") |> :json.decode()
4 changes: 3 additions & 1 deletion examples/phoenix-liveview/config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,7 @@ if config_env() == :prod do
# Check `Plug.SSL` for all available options in `force_ssl`.

config :electric_phoenix, Electric.Client,
base_url: System.get_env("ELECTRIC_URL") || raise("ELECTRIC_URL environment variable not set")
base_url:
System.get_env("ELECTRIC_URL") || raise("ELECTRIC_URL environment variable not set"),
params: System.get_env("ELECTRIC_CLIENT_PARAMS", "{}") |> :json.decode()
end
3 changes: 2 additions & 1 deletion examples/phoenix-liveview/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ defmodule Electric.PhoenixExample.MixProject do
{:jason, "~> 1.2"},
{:dns_cluster, "~> 0.1.1"},
{:bandit, "~> 1.5"},
{:electric_phoenix, "~> 0.2.0"}
{:electric_phoenix, "~> 0.2.0"},
{:electric_client, ">= 0.2.6-pre-1", override: true}
]
end

Expand Down
20 changes: 10 additions & 10 deletions examples/phoenix-liveview/mix.lock

Large diffs are not rendered by default.

18 changes: 12 additions & 6 deletions packages/elixir-client/lib/electric/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ defmodule Electric.Client do

defstruct [
:endpoint,
:database_id,
:fetch,
:authenticator,
:pool
:pool,
:params
]

@api_endpoint_path "/v1/shape"
Expand All @@ -169,10 +169,11 @@ defmodule Electric.Client do
doc:
"The full URL of the shape API endpoint. E.g. for local development this would be `http://localhost:3000/v1/shape`. Use this if you need a non-standard API path."
],
database_id: [
type: {:or, [nil, :string]},
params: [
type: {:map, {:or, [:atom, :string]}, :any},
default: %{},
doc:
"Which database to use, optional unless Electric is used with multiple databases."
"Additional query parameters to include in every request to the Electric backend."
],
fetch: [type: :mod_arg, default: {Client.Fetch.HTTP, []}, doc: false],
authenticator: [
Expand Down Expand Up @@ -376,7 +377,12 @@ defmodule Electric.Client do
@doc false
@spec request(t(), Fetch.Request.attrs()) :: Fetch.Request.t()
def request(%Client{} = client, opts) do
struct(%Fetch.Request{endpoint: client.endpoint, database_id: client.database_id}, opts)
params = Map.merge(client.params, Keyword.get(opts, :params, %{}))

struct(
%Fetch.Request{endpoint: client.endpoint},
Keyword.put(opts, :params, params)
)
end

@doc """
Expand Down
3 changes: 0 additions & 3 deletions packages/elixir-client/lib/electric/client/fetch/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ defmodule Electric.Client.Fetch.Request do
defstruct [
:stream_id,
:endpoint,
:database_id,
:shape_handle,
:live,
:shape,
Expand Down Expand Up @@ -105,7 +104,6 @@ defmodule Electric.Client.Fetch.Request do
replica: replica,
live: live?,
shape_handle: shape_handle,
database_id: database_id,
offset: %Offset{} = offset,
next_cursor: cursor,
params: params
Expand All @@ -118,7 +116,6 @@ defmodule Electric.Client.Fetch.Request do
|> Util.map_put_if("handle", shape_handle, is_binary(shape_handle))
|> Util.map_put_if("live", "true", live?)
|> Util.map_put_if("cursor", to_string(cursor), !is_nil(cursor))
|> Util.map_put_if("database_id", database_id, !is_nil(database_id))
end

@doc false
Expand Down
37 changes: 24 additions & 13 deletions packages/elixir-client/test/electric/client/fetch/request_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -89,38 +89,48 @@ defmodule Electric.Client.Fetch.RequestTest do
assert %{"my_param" => "here"} = params
end

test "includes column list in parameters" do
columns = ["id", "value", "description"]
test "includes client params in the url" do
client_params = %{my_goal: "unknowable", my_reasons: "inscrutable"}
request_params = %{"my_param" => "here"}

expected_query_params =
client_params
|> Map.merge(request_params)
|> Map.new(fn {k, v} ->
{to_string(k), v}
end)

%Client{params: ^client_params} = client = client!(params: client_params)

request =
Client.request(client!(),
Client.request(client,
offset: Client.Offset.new(1234, 1),
shape_handle: "my-shape",
live: true,
next_cursor: 123_948,
shape: Client.shape!("my_table", columns: columns)
shape: Client.shape!("my_table"),
params: request_params
)

url = Request.url(request)

{:ok, uri} = URI.new(url)

params = URI.decode_query(uri.query)

column_list = Enum.join(columns, ",")
assert %{"columns" => ^column_list} = params
for {k, v} <- expected_query_params do
assert params[k] == v
end
end

test "includes client database_id in params" do
database_id = "168d01dc-9e19-4887-99d9-7f5eba1ca434"
test "includes column list in parameters" do
columns = ["id", "value", "description"]

request =
Client.request(client!(database_id: database_id),
Client.request(client!(),
offset: Client.Offset.new(1234, 1),
shape_handle: "my-shape",
live: true,
next_cursor: 123_948,
shape: Client.shape!("my_table")
shape: Client.shape!("my_table", columns: columns)
)

url = Request.url(request)
Expand All @@ -129,7 +139,8 @@ defmodule Electric.Client.Fetch.RequestTest do

params = URI.decode_query(uri.query)

assert %{"database_id" => ^database_id} = params
column_list = Enum.join(columns, ",")
assert %{"columns" => ^column_list} = params
end
end
end
54 changes: 47 additions & 7 deletions packages/elixir-client/test/electric/client_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,54 @@ defmodule Electric.ClientTest do
assert {:error, _} = Client.new([])
end

test "database_id is correctly assigned" do
{:ok, %Client{database_id: "1234"}} =
Client.new(base_url: "http://localhost:3000", database_id: "1234")
end
test "params are appended to all requests" do
params = %{my_goal: "unknowable", my_reasons: "inscrutable"}

expected_query_params =
Map.new(params, fn {k, v} ->
{to_string(k), v}
end)

bypass = Bypass.open()

{:ok, %Client{params: ^params} = client} =
Client.new(base_url: "http://localhost:#{bypass.port}", params: params)

stream = Client.stream(client, "things", oneshot: true)

parent = self()

test "database_id is optional" do
{:ok, %Client{database_id: nil}} =
Client.new(base_url: "http://localhost:3000", database_id: nil)
Bypass.expect(
bypass,
fn %{
query_params: query_params
} = conn ->
for {k, v} <- expected_query_params do
assert query_params[k] == v
end

send(parent, {:request, query_params})

bypass_resp(conn, "[]",
shape_handle: "my-shape",
last_offset: "1234_0",
schema: Jason.encode!(%{"id" => %{type: "text"}, "value" => %{type: "text"}})
)
end
)

Task.start_link(fn ->
stream |> Stream.take(1) |> Enum.to_list()
end)

receive do
{:request, _query} ->
:ok
after
500 ->
# the asserts in the bypass handler just trigger a retry loop
flunk("did not receive the expected query parameters")
end
end
end

Expand Down

0 comments on commit 9f0b96a

Please sign in to comment.