electric icon indicating copy to clipboard operation
electric copied to clipboard

feat(sync-service): Send individual operations to ShapeLogCollector

Open robacourt opened this issue 2 months ago • 1 comments

Part of #3414, this PR sends individual operations from the ReplicationClient to ShapeLogCollector. This should reduce the working memory used by the ReplicationClient, but the ultimate aim is to send individual operations to storage and so not buffer at any point (unless subqueries are involved). This PR just moves the transaction consolidation one step, from ReplicationClient to ShapeLogCollector to keep the PR small. Other PRs will move the consolidation further, from ShapeLogCollector to Consumer, then finally from to Consumer to storage (except with subqueries are involved).

Currently the replication stream take two forms:

  1. Replication.Messages such as Messages.Begin, Messages.Commit, Messages.Insert etc.
  2. Changes.Transaction (or Changes.Relation)

And Collector converts one to the other.

This PR introduces an intermediate form, Operations, as Messages are coupled to the postgres replication protocol and are not optimised for use with Shapes (for example they do not include the relation name) and Transactions are whole transactions. So with this PR we have:

  1. Replication.Messages such as Messages.Begin, Messages.Commit, Messages.Insert etc.
  2. Operation (spec: Changes.operation()) such as Changes.Begin. Changes.Commit, Changes.NewRecord etc.
  3. Changes.Transaction (or Changes.Relation) which I'm calling database actions (spec: Changes.action())

Collector has been replaced by MessageConverter that converts 1 to 2 and TransactionBuilder that coverts 2 to 3.

robacourt avatar Nov 13 '25 16:11 robacourt

Codecov Report

:white_check_mark: All modified and coverable lines are covered by tests. :white_check_mark: Project coverage is 82.68%. Comparing base (c7adffa) to head (4e84bcb). :warning: Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3429      +/-   ##
==========================================
- Coverage   87.73%   82.68%   -5.06%     
==========================================
  Files           3       37      +34     
  Lines         163     2194    +2031     
  Branches       39      357     +318     
==========================================
+ Hits          143     1814    +1671     
- Misses         19      378     +359     
- Partials        1        2       +1     
Flag Coverage Δ
elixir 73.94% <ø> (?)
elixir-client 73.94% <ø> (?)
packages/experimental 88.95% <ø> (+1.22%) :arrow_up:
packages/react-hooks 86.48% <ø> (?)
packages/typescript-client 93.67% <ø> (?)
packages/y-electric 55.12% <ø> (?)
typescript 87.27% <ø> (-0.46%) :arrow_down:
unit-tests 82.68% <ø> (-5.06%) :arrow_down:

Flags with carried forward coverage won't be shown. Click here to find out more.

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

:rocket: New features to boost your workflow:
  • :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

codecov[bot] avatar Nov 13 '25 16:11 codecov[bot]

Open in StackBlitz

npm i https://pkg.pr.new/@electric-sql/react@3429
npm i https://pkg.pr.new/@electric-sql/client@3429
npm i https://pkg.pr.new/@electric-sql/y-electric@3429

commit: 4e84bcb

pkg-pr-new[bot] avatar Nov 17 '25 09:11 pkg-pr-new[bot]

benchmark this

robacourt avatar Nov 18 '25 09:11 robacourt

Benchmark results, triggered for 69799

  • write fanout completed

write fanout results

  • unrelated shapes one client latency completed

unrelated shapes one client latency results

  • many shapes one client latency completed

many shapes one client latency results

  • concurrent shape creation completed

concurrent shape creation results

  • diverse shape fanout completed

diverse shape fanout results

github-actions[bot] avatar Nov 18 '25 10:11 github-actions[bot]