electric-sql / electric-sql/electric

Elixir client `Message.from_message/2` eats change info.

Open
#2,831 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
10.4k
Forks
375
Avg merge
3d 1h
Merged PRs (30d)
18

Description

When consuming a shape in an Elixir application using the Electric.Client, the parsing of raw messages into `Electric.Client.Message.ChangeMessage` structs loses the information about which fields have changed.

To reproduce, make a surgical update, e.g.: just updating the name on a schema with additional fields:

```elixir
Threads.change_thread(thread, %{name: "some other name"})
```

This results in a raw message like this:

```elixir
%{
"headers" => %{
"last" => true,
"lsn" => "786675360",
"op_position" => 0,
"operation" => "update",
"relation" => ["public", "threads"],
"txids" => [39380]
},
"key" => "\"public\".\"threads\"/\"c946e731-ddd7-4331-8147-6a159fede21f\"",
"value" => %{
"id" => "c946e731-ddd7-4331-8147-6a159fede21f",
"name" => "some other name"
}
}
```

This is processed by `ChangeMessage.from_message` (using `Electric.Client.EctoAdapter.for_schema/2`) into:

```elixir
%Electric.Client.Message.ChangeMessage{
key: "\"public\".\"threads\"/\"c946e731-ddd7-4331-8147-6a159fede21f\"",
value: %MyApp.Threads.Thread{
__meta__: #Ecto.Schema.Metadata<:built, "threads">,
id: "c946e731-ddd7-4331-8147-6a159fede21f",
name: "some other name",
status: nil,
inserted_at: nil,
updated_at: nil
},
old_value: nil,
headers: %Electric.Client.Message.Headers{
operation: :update,
relation: ["public", "threads"],
handle: "8728556-1749895640933410"
},
request_timestamp: ~U[2025-06-14 10:07:20.967291Z]
}
```

Note the addition of `status: nil, inserted_at: nil, updated_at: nil`. It's impossible to know whether these values were set to `nil` by the change or were not set.

It is possible to workaround this by setting `?replica=full` to get the old_value and then figuring out the changes. However, this seems unnecessary given that the information is present in the raw message already.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.