Skip to content

Commit

Permalink
fix: Correct OpenAPI spec for 409 (#2406)
Browse files Browse the repository at this point in the history
Closes #2361

Also makes the `location` header in 409 responses carry over the full
shape query as the original shape.
  • Loading branch information
msfstef authored Mar 5, 2025
1 parent b59c821 commit b33fd2c
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/few-cougars-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@core/sync-service": patch
---

Carry over full original shape query in 409 redirects.
5 changes: 5 additions & 0 deletions .changeset/silver-mirrors-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@electric-sql/docs": patch
---

Fix OpenAPI spec 409 response schema
11 changes: 6 additions & 5 deletions packages/sync-service/lib/electric/shapes/api/response.ex
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,12 @@ defmodule Electric.Shapes.Api.Response do
end

defp put_location_header(conn, %__MODULE__{status: 409} = response) do
params = [
table: Electric.Utils.relation_to_sql(response.shape_definition.root_table),
handle: response.handle,
offset: "-1"
]
params =
conn.query_params
|> Map.put("handle", response.handle)
|> Map.put("offset", to_string(@before_all_offset))
|> Map.delete("live")
|> Map.delete("cursor")

query = URI.encode_query(params)

Expand Down
4 changes: 2 additions & 2 deletions packages/sync-service/test/electric/plug/router_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -990,15 +990,15 @@ defmodule Electric.Plug.RouterTest do
} do
# Make the next request but forget to include the where clause
conn =
conn("GET", "/v1/shape?table=items", %{offset: "0_0", handle: "nonexistent"})
conn("GET", "/v1/shape?table=items&unrelated=foo", %{offset: "0_0", handle: "nonexistent"})
|> Router.call(opts)

assert %{status: 409} = conn
assert conn.resp_body == Jason.encode!([%{headers: %{control: "must-refetch"}}])
new_shape_handle = get_resp_header(conn, "electric-handle")

assert get_resp_header(conn, "location") ==
"/v1/shape?table=public.items&handle=#{new_shape_handle}&offset=-1"
"/v1/shape?handle=#{new_shape_handle}&offset=-1&table=items&unrelated=foo"
end

test "GET receives 409 when shape handle is not found but there is another shape matching the definition",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ defmodule Electric.Plug.ServeShapePlugTest do
assert get_resp_header(conn, "electric-handle") == [@test_shape_handle]

assert get_resp_header(conn, "location") == [
"/?table=public.users&handle=#{@test_shape_handle}&offset=-1"
"/?handle=#{@test_shape_handle}&offset=-1&table=public.users"
]
end

Expand Down Expand Up @@ -664,7 +664,7 @@ defmodule Electric.Plug.ServeShapePlugTest do
assert get_resp_header(conn, "electric-handle") == [new_shape_handle]

assert get_resp_header(conn, "location") == [
"/?table=public.users&handle=#{new_shape_handle}&offset=-1"
"/?handle=#{new_shape_handle}&offset=-1&table=public.users"
]
end

Expand Down
29 changes: 22 additions & 7 deletions website/electric-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -387,14 +387,29 @@ paths:
content:
application/json:
schema:
type: object
properties:
headers:
type: object
description: Cache control headers
type: array
description: Array of message objects
items:
type: object
description: Message object
properties:
headers:
type: object
description: |-
Metadata describing the control message.
The `control` message returned will be a `must-refetch` message,
which a client should detect and throw away any local data and
re-sync from scratch using the new shape handle available in the
`electric-handle` header of the response.
properties:
control:
type: "string"
enum:
- must-refetch
example:
headers:
control: "must-refetch"
- headers:
control: must-refetch
"429":
description:
Too many requests. The server is busy with other requests, potentially
Expand Down

0 comments on commit b33fd2c

Please sign in to comment.