Skip to content

feat(sdk): fail over to a surviving node when the current one dies - #3944

Open
numinnex wants to merge 19 commits into
masterfrom
multi_endpoint_failover
Open

feat(sdk): fail over to a surviving node when the current one dies#3944
numinnex wants to merge 19 commits into
masterfrom
multi_endpoint_failover

Conversation

@numinnex

Copy link
Copy Markdown
Contributor

No description provided.

@github-actions github-actions Bot added the S-waiting-on-review PR is waiting on a reviewer label Aug 21, 2026
@numinnex

Copy link
Copy Markdown
Contributor Author

Merge after #3934

@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.81151% with 200 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.20%. Comparing base (1e2d222) to head (46c33fd).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
core/sdk/src/tcp/tcp_client.rs 89.43% 56 Missing and 25 partials ⚠️
foreign/go/client/tcp/tcp_core.go 81.87% 22 Missing and 7 partials ⚠️
...ache/iggy/client/async/tcp/AsyncIggyTcpClient.java 77.27% 12 Missing and 8 partials ⚠️
...SDK/IggyClient/Implementations/TcpMessageStream.cs 80.80% 13 Missing and 6 partials ⚠️
core/sdk/src/leader_aware.rs 89.25% 13 Missing ⚠️
foreign/node/src/client/client.socket.ts 96.63% 11 Missing ⚠️
core/sdk/src/clients/client_builder.rs 0.00% 4 Missing ⚠️
...ache/iggy/client/async/tcp/AsyncTcpConnection.java 69.23% 4 Missing ⚠️
foreign/python/src/config.rs 55.55% 4 Missing ⚠️
core/common/src/types/args/mod.rs 25.00% 1 Missing and 2 partials ⚠️
... and 8 more
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3944      +/-   ##
============================================
+ Coverage     84.04%   84.20%   +0.15%     
- Complexity     1358     1398      +40     
============================================
  Files          1217     1219       +2     
  Lines        171874   173465    +1591     
  Branches     139630   140556     +926     
============================================
+ Hits         144459   146070    +1611     
+ Misses        23483    23410      -73     
- Partials       3932     3985      +53     
Components Coverage Δ
Rust Core 85.02% <89.27%> (+0.08%) ⬆️
Java SDK 67.23% <79.20%> (+0.55%) ⬆️
C# SDK 75.28% <82.72%> (+0.32%) ⬆️
Python SDK 89.97% <55.55%> (-0.14%) ⬇️
PHP SDK 85.65% <ø> (ø)
Node SDK 96.07% <97.41%> (+0.26%) ⬆️
Go SDK 69.09% <83.91%> (+0.80%) ⬆️
Files with missing lines Coverage Δ
.../src/traits/binary_impls/personal_access_tokens.rs 100.00% <ø> (ø)
core/common/src/traits/binary_impls/users.rs 100.00% <ø> (ø)
core/common/src/traits/binary_transport.rs 100.00% <100.00%> (ø)
...pes/configuration/auth_config/connection_string.rs 96.26% <100.00%> (+0.30%) ⬆️
...ypes/configuration/tcp_config/tcp_client_config.rs 100.00% <100.00%> (ø)
...ation/tcp_config/tcp_client_reconnection_config.rs 100.00% <ø> (ø)
...ration/tcp_config/tcp_connection_string_options.rs 88.00% <100.00%> (+1.63%) ⬆️
core/sdk/src/client_provider.rs 43.62% <100.00%> (+0.38%) ⬆️
...e/sdk/src/clients/binary_personal_access_tokens.rs 100.00% <ø> (ø)
core/sdk/src/clients/binary_users.rs 100.00% <ø> (ø)
... and 23 more

... and 43 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@hubcio hubcio 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.

cross-sdk:

  • configured seeds (failover_addresses) exist only in rust; go/java/c#/node keep a single seed, so a first connect on a dead configured node has nowhere to go. in scope or follow-up?
  • dial order: rust = current, roster, seeds; the four ports = current, configured seed, roster. every port dials a possibly dead configured node ahead of live survivors on every loss. pick one (rust's). same for reconnection disabled: rust bails on the first failed dial, go still sweeps everything.
  • StaleClient forget: rust/go/c# forget the remembered credentials, java never does, c# misses the outcome-unknown wrapper, go forgets only after the reconnection-disabled return. same contract in all five or in none.
  • empty description for a behaviour change across five sdks (remembered credentials, skipped reestablish_after, the 2s dial bound, replay semantics). write the contract down. the c# readme (InitialDelay, "without credentials a reconnect cannot restore the session") and the python readme (reestablish_after) are now wrong too.

outside the diff:

  • rust: IggyClientBuilder::with_tcp() has no with_failover_addresses passthrough, so seeds are only reachable via TcpClient::create(config). max_retries now counts full sweeps but the builder doc still says retries.
  • go: currentServerAddress is read without c.mtx in exchange (line 533) while dialCandidate writes it under the lock; time.Sleep(remaining) in the reestablish pause (line 926) ignores ctx. both pre-existing.
  • node: the maxRetries doc in client.type.ts says reconnection attempts, it now counts full passes; same for the DefaultReconnectOption comment. the readme has no failover mention.

Comment thread core/sdk/src/tcp/tcp_client.rs Outdated
Comment thread core/sdk/src/tcp/tcp_client.rs Outdated
Comment thread core/sdk/src/tcp/tcp_client.rs
Comment thread core/sdk/src/tcp/tcp_client.rs Outdated
Comment thread core/sdk/src/tcp/tcp_client.rs Outdated
Comment thread foreign/node/src/client/client.connection.ts Outdated
Comment thread foreign/node/src/client/client.connection.ts Outdated
Comment thread foreign/node/src/client/client.socket.ts Outdated
Comment thread foreign/node/src/client/client.connection.test.ts
Comment thread foreign/node/src/client/client.socket.test.ts Outdated
@github-actions github-actions Bot added S-waiting-on-author PR is waiting on author response and removed S-waiting-on-review PR is waiting on a reviewer labels Aug 25, 2026
@numinnex

Copy link
Copy Markdown
Contributor Author

/ready

@github-actions github-actions Bot added S-waiting-on-review PR is waiting on a reviewer and removed S-waiting-on-author PR is waiting on author response labels Aug 25, 2026

@hubcio hubcio 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.

second pass at 4433f9a. most threads are fixed; what's below and the inline comments are still open.

  • staleclient rule: replay the remembered login everywhere, like rust does now. an eviction is not caller intent. go, c# and java (with and without builder credentials) should match.
  • PR description is still empty. write the contract down: remembered credentials, the 2s dial bound, the reestablish_after rotation, what is replayed after a reconnect and what is not.
  • seeds still exist only in rust, and there only via TcpClient::create(config): no with_failover_addresses on IggyClientBuilder::with_tcp(), no connection string option, cli and python can't set them. in scope or follow-up?
  • dial order still differs: rust = current, roster, seeds; go/java/c#/node = current, configured seed, roster, and the ports now pin their order with tests. pick one.
  • reconnection disabled: rust, go and c# sweep every candidate once; java and node don't dial at all (maxRetries 0 / enabled = false skips the loop). same rule everywhere.
  • docs: c# README lines 104, 111-112, 204-206 still say a hand-run login can't be restored; rust max_retries docs (client_builder.rs:168, tcp_client_config_builder.rs:61) and the python config doc still say retries, one retry is a full sweep now.
  • go: currentServerAddress read without c.mtx in exchange (tcp_core.go:542) and clientAddress in tcp_session_management.go:79 - both reported by -race.
  • go: concurrent requests failing during a reconnect with credentials hang the whole client. skipAutoLoginOnce is client-global: a second failing request's disconnect() flips the state so two Connects run, one eats the flag and the login replay's own Connect auto-logins under its own registerMtx. 8 concurrent pings on a dropped socket with WithAutoLogin hung until the test timeout. pre-existing for WithAutoLogin, remembered logins reach it now. the second Connect also overwrites c.conn and the first conn is never closed.
  • java has no failover dial bound: netty CONNECT_TIMEOUT_MILLIS = connectionTimeout or 3s, always on, tcp only, so a long connectionTimeout stretches every rotation.

Comment thread core/sdk/src/tcp/tcp_client.rs Outdated
Comment thread core/sdk/src/tcp/tcp_client.rs Outdated
Comment thread core/sdk/src/tcp/tcp_client.rs Outdated
Comment thread core/sdk/src/leader_aware.rs Outdated
Comment thread core/sdk/src/leader_aware.rs Outdated
Comment thread foreign/node/src/client/client.socket.ts Outdated
Comment thread foreign/node/src/client/client.connection.ts
Comment thread foreign/node/src/client/client.connection.ts
Comment thread foreign/node/src/client/client.connection.ts
Comment thread foreign/node/src/client/client.connection.ts
@github-actions github-actions Bot added S-waiting-on-author PR is waiting on author response and removed S-waiting-on-review PR is waiting on a reviewer labels Aug 25, 2026
@numinnex

Copy link
Copy Markdown
Contributor Author

/ready

@github-actions github-actions Bot added S-waiting-on-review PR is waiting on a reviewer and removed S-waiting-on-author PR is waiting on author response labels Aug 25, 2026

@hubcio hubcio 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.

third pass at 0e6f965. the staleclient rule, the dial order and the one-sweep-when-disabled rule now match across the sdks, thanks. what is left:

  • go: the new single-flight Connect can deadlock a sign-in that holds registerMtx against a concurrent request's auto-login (inline). that one blocks.
  • node: a command re-issued after a leader move gets a fresh 30s budget (inline).
  • java: redial now replays the last sign-in instead of the configured credentials, the opposite of rust and go. pick one rule for all sdks and pin the eviction case with both credentials.
  • PR description is still empty. write the contract down: remembered credentials, the 2s dial bound, the reestablish_after rotation, what is replayed after a reconnect and what is not, and whether seeds outside the raw builder are in scope.
  • java AsyncTcpConnection.updateLoginPayload (850-856) still sets the payload with no closed check, so a send racing close() leaks the retained slice.
  • rust builder docs still say 'number of retries' (client_builder.rs:169/177/188, tcp_client_config_builder.rs:66/72/78) while the struct doc now says passes.
  • c# README 163-164 still says a lost session is repaired by auto login only.

Comment thread foreign/go/client/tcp/tcp_core.go
Comment thread foreign/go/client/tcp/tcp_core.go Outdated
Comment thread foreign/go/client/tcp/tcp_core.go
Comment thread foreign/go/client/tcp/tcp_core.go Outdated
Comment thread foreign/go/client/tcp/tcp_core.go Outdated
Comment thread foreign/csharp/Iggy_SDK_Tests/VsrTests/EndpointFailoverTests.cs Outdated
Comment thread core/common/src/types/configuration/tcp_config/tcp_client_reconnection_config.rs Outdated
Comment thread core/common/src/types/configuration/tcp_config/tcp_client_reconnection_config.rs Outdated
Comment thread core/sdk/src/tcp/tcp_client.rs Outdated
@github-actions github-actions Bot added S-waiting-on-author PR is waiting on author response and removed S-waiting-on-review PR is waiting on a reviewer labels Aug 26, 2026
@numinnex

Copy link
Copy Markdown
Contributor Author

/ready

@github-actions github-actions Bot added S-waiting-on-review PR is waiting on a reviewer and removed S-waiting-on-author PR is waiting on author response labels Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review PR is waiting on a reviewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants