Skip to content

fix(sync-service): Move connection opts discovery into external process - #3118

Merged
magnetised merged 7 commits into
magnetised/separate-db-poolsfrom
magnetised/synchronous-connection-fix
Sep 10, 2025
Merged

magnetised merged 7 commits into
magnetised/separate-db-poolsfrom
magnetised/synchronous-connection-fix

Conversation

@magnetised

Copy link
Copy Markdown
Contributor

Fixes #3099

@codecov

codecov Bot commented Sep 9, 2025 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 12.74510% with 89 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.19%. Comparing base (34bfcc7) to head (798f7db).
⚠️ Report is 1 commits behind head on magnetised/separate-db-pools.

Files with missing lines Patch % Lines
...electric/connection/manager/connection_resolver.ex 2.04% 48 Missing ⚠️
...es/sync-service/lib/electric/connection/manager.ex 0.00% 38 Missing ⚠️
...nc-service/lib/electric/connection/manager/pool.ex 78.57% 3 Missing ⚠️
Additional details and impacted files
@@                       Coverage Diff                        @@
##           magnetised/separate-db-pools    #3118      +/-   ##
================================================================
- Coverage                         77.31%   77.19%   -0.12%     
================================================================
  Files                               169      170       +1     
  Lines                              9059     9074      +15     
  Branches                            287      284       -3     
================================================================
+ Hits                               7004     7005       +1     
- Misses                             2053     2067      +14     
  Partials                              2        2              
Flag Coverage Δ
elixir 76.01% <12.74%> (-0.14%) ⬇️
elixir-client 73.87% <ø> (-0.54%) ⬇️
packages/experimental 87.73% <ø> (ø)
packages/react-hooks 86.48% <ø> (ø)
packages/typescript-client 93.18% <ø> (ø)
packages/y-electric 55.12% <ø> (ø)
postgres-140000 75.89% <12.74%> (-0.32%) ⬇️
postgres-150000 76.16% <12.74%> (-0.01%) ⬇️
postgres-170000 76.10% <12.74%> (-0.12%) ⬇️
sync-service 76.23% <12.74%> (-0.10%) ⬇️
typescript 85.27% <ø> (ø)
unit-tests 77.19% <12.74%> (-0.12%) ⬇️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

@magnetised
magnetised force-pushed the magnetised/synchronous-connection-fix branch from 6af8834 to b9da18a Compare September 9, 2025 13:26
@balegas

balegas commented Sep 9, 2025

Copy link
Copy Markdown
Contributor

Shall we expedite testing this in staging Cloud. @msfstef we can check what users have pooled connection enabled and test with supabase to understand if this would work with the users that have pooled connections

@msfstef msfstef left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice!

My main worry is why are we not starting the connection resolver as a process in the supervisor before the connection manager, so we don't have to start link and kill it every time?

We could even hibernate it if we're worried about its usage, but I'm not that worried about it personally, I would prefer it in a supervisor rather than start link and unlink and killing it etc

Comment thread packages/sync-service/lib/electric/connection/manager/connection_resolver.ex Outdated
Comment thread packages/sync-service/lib/electric/connection/manager/connection_resolver.ex Outdated
Comment thread packages/sync-service/lib/electric/connection/manager/connection_resolver.ex Outdated

@alco alco left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. There's some confusion about shared_connection_options in the new code, I don't think we need them anymore.

It'd be nice to have an actual test for exercising IPv6 fallback working in a real connection. Why can't we have that tested here, since we're already running real Postgres for tests? Is the DNS request for AAAA on localhost going to resolve to a valid IPv6 address?

if in_connection_opts == Keyword.fetch!(in_replication_opts, :connection_opts) do
populate_connection_opts(in_connection_opts)
end
shared_connection_opts = Keyword.fetch!(in_replication_opts, :connection_opts)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This completely changes the logic below. shared_connection_opts can no longer be nil so there's no point in running is_nil(shared_connection_opts) checks below.

And I don't see a reason to keep shared_connection_opts if there's now a separate validate() call for every type of connection opts. So even if connection_opts == replication_opts[:connection_opts], we'll still run separate checks for each because of different type arguments passed into validate().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, again i didn't delve too deeply into the shared_connection_opts -- just did a superficial pass to remove the obviously unnecessary calls

# connection errors
Process.flag(:trap_exit, true)

Process.set_label({:connection_discovery, opts[:stack_id]})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be :connection_resolver.

@balegas

balegas commented Sep 9, 2025

Copy link
Copy Markdown
Contributor

My main worry is why are we not starting the connection resolver as a process in the supervisor before the connection manager, so we don't have to start link and kill it every time?

A comment from 10000 feet high: please make sure the exists don't get to Sentry.

@magnetised

Copy link
Copy Markdown
Contributor Author

Looks good. There's some confusion about shared_connection_options in the new code, I don't think we need them anymore.

Yeah, in the interests of speed (on the clock with this one) I r tried not to go down too many rabbit holes.

It'd be nice to have an actual test for exercising IPv6 fallback working in a real connection. Why can't we have that tested here, since we're already running real Postgres for tests? Is the DNS request for AAAA on localhost going to resolve to a valid IPv6 address?

localhost resolves to [::1] for me and connects so I don't think this is entirely straightforward -- I have the mocked out test which exercises the path.

@magnetised
magnetised requested review from alco and msfstef September 9, 2025 15:19
@magnetised

Copy link
Copy Markdown
Contributor Author

@msfstef have restructured as a permanent sibling process of the connection manager as you suggest

@alco let's push some of the cleanup around shared opts to another pr -- don't want to get into the weeds here

there is a reliable failure of one of the integration tests looking at behaviour when there are insufficient connections available. must be something to do with the splitting the connections between the two pools interfering with the restart mechanism somehow. am investigating...

@msfstef

msfstef commented Sep 9, 2025

Copy link
Copy Markdown
Contributor

there is a reliable failure of one of the integration tests looking at behaviour when there are insufficient connections available. must be something to do with the splitting the connections between the two pools interfering with the restart mechanism somehow. am investigating...

Yeah that seems to be failing on the pool PR (and the failure translates to this one) - the test manually fixes the number of available connections on postgres so that the pool fails to start expecting:

Database connection in connection_pool mode failed: sorry, too many clients already

I assume you need to match to a different log now that you have named the pools

@magnetised
magnetised force-pushed the magnetised/separate-db-pools branch from 6f17e00 to 480d9c4 Compare September 9, 2025 15:53
@magnetised
magnetised force-pushed the magnetised/synchronous-connection-fix branch from 0928c35 to d847551 Compare September 9, 2025 16:05

@msfstef msfstef left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice!

I think even with the minimal latency overhead the clarity of having a separate validation step is invaluable. I think it'll help us break up the conn man in further steps

Probably needs rebasing to fix the example TS tests failing

@magnetised
magnetised force-pushed the magnetised/separate-db-pools branch from 480d9c4 to 34bfcc7 Compare September 9, 2025 16:43
@magnetised
magnetised force-pushed the magnetised/synchronous-connection-fix branch from d847551 to 67b3935 Compare September 9, 2025 16:43

@msfstef msfstef left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

I think we could still share conn opts if possible but with a simpler method but happy to keep them nice and cleanly separate at the cost of minimal latency.

Integration test failing (and it'd be good to add a regression unit test that ensures pooled conn url is used) but other than that good on my side!

Comment thread packages/sync-service/lib/electric/connection/manager.ex
connection_opts: connection_opts,
replication_opts: replication_opts
}
%{state | connection_opts: connection_opts, replication_opts: replication_opts}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that all unit tests missed the fact that we were not using a pooled connection string it would be good if we can have some sort of manager_test that checks that the pooled connection is actually used if provided

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Let me write it up as a follow-up issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is a really good point

@magnetised
magnetised merged commit f074710 into magnetised/separate-db-pools Sep 10, 2025
39 checks passed
@magnetised
magnetised deleted the magnetised/synchronous-connection-fix branch September 10, 2025 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants