Skip to content

Conversation

@adespawn
Copy link
Contributor

This PR adds a new load balancing policy, as well as attempts to add support for some of the old policies.

Right now, this is not tested, as all of the current integration tests rely on info.queried hosts, which are not available in the rust driver.

Update query options construction to be a method on the Client wrapper,
instead of a standalone function. This change will allow for adding
load balancing policies, which are configured at the client level,
in the DSx driver, and on the statement level in the Rust driver.
This adds a rust driver default load balancing policy.
This can be configured through JS at the session construction,
and will be used for all queries. Support for configuring it through
the driver interface will be added in the following commits.
@adespawn adespawn requested a review from Copilot November 21, 2025 11:47
@adespawn adespawn self-assigned this Nov 21, 2025
@adespawn adespawn added this to the GA milestone Nov 21, 2025
Copilot finished reviewing on behalf of adespawn November 21, 2025 11:52
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR introduces load balancing support by integrating the Rust driver's default load balancing policy into the JavaScript driver. It adds a new NewDefaultLoadBalancingPolicy class and LoadBalancingConfig configuration object, while deprecating the old DefaultLoadBalancingPolicy implementation. The PR also removes the deprecated WhiteListPolicy and updates the defaultLoadBalancingPolicy() function to no longer accept a localDc parameter.

Key changes:

  • Adds Rust-backed load balancing policy implementation with support for datacenter/rack awareness, token awareness, and datacenter failover
  • Refactors batch creation methods to be instance methods on SessionWrapper to enable per-session load balancing policy configuration
  • Updates existing policies (RoundRobinPolicy, DCAwareRoundRobinPolicy, TokenAwarePolicy) to provide Rust configuration via getRustConfiguration()

Reviewed Changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/session.rs Adds LoadBalancingConfig struct, session_load_balancing_policy field, and refactors statement/batch option application to be instance methods that apply the session's load balancing policy
src/utils/from_napi_obj.rs Updates macro to support trailing commas in field definitions
src/utils/to_napi_obj.rs Updates macro to support trailing commas in field definitions
src/requests/request.rs Adds trailing comma to QueryOptionsObj definition for consistency
src/metadata/host.rs Adds trailing comma to HostWrapper definition for consistency
lib/policies/load-balancing.js Adds NewDefaultLoadBalancingPolicy and LoadBalancingConfig classes, adds LoadBalancingRustImplemented base class, updates existing policies to support Rust configuration, removes deprecated WhiteListPolicy
lib/policies/index.js Updates defaultLoadBalancingPolicy() to return NewDefaultLoadBalancingPolicy and removes localDc parameter
lib/policies/index.d.ts Updates TypeScript definition for defaultLoadBalancingPolicy() to remove optional parameter
lib/client.js Changes batch creation from static functions to instance methods on rustClient
lib/client-options.js Adds load balancing configuration extraction and validation in setRustOptions()
test/unit/default-policies-tests.js Adds basic test for new default load balancing policy
test/unit-broken/default-load-balancing-policy-tests.js Removes tests for old implementation moved to broken tests directory
test/unit-not-supported/api-tests.js Removes WhiteListPolicy from API surface tests
test/typescript/policy-tests.ts Removes usage of WhiteListPolicy and localDc parameter
test/test-helper.js Restores client.hosts functionality check (previously commented out)
Comments suppressed due to low confidence (1)

lib/policies/load-balancing.js:16

  • [nitpick] Inconsistent empty constructor formatting. The codebase uses constructor() {} without a space between the braces. This should be constructor() {} to match the existing style in files like lib/execution-options.js:27, lib/policies/address-resolution.js:27, lib/policies/retry.js:11, etc.
    /**

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


#[rustfmt::skip] // fmt splits the struct definition into multiple lines
define_js_to_rust_convertible_object!(
LoadBalancingConfig {
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

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

[nitpick] Inconsistent indentation. The opening brace should be aligned with the macro name. The line should start with no leading space, like:

define_js_to_rust_convertible_object!(
LoadBalancingConfig {
Suggested change
LoadBalancingConfig {
LoadBalancingConfig {

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

+1

// We will catch this error when:
// - The policy does not implement getRustConfiguration (someone provided policy that does not inherit from LoadBalancingPolicy)
// - The policy implements getRustConfiguration but throws "Currently this policy is not supported by the driver"
// - Some other obscure error, like node deciding it has a bad day and just want't to crash
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

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

Typo in comment: "want't" should be "wants". Also, the comment is somewhat informal. Consider rewording to: "- Some other unexpected error occurs"

Suggested change
// - Some other obscure error, like node deciding it has a bad day and just want't to crash
// - Some other unexpected error occurs

Copilot uses AI. Check for mistakes.
This is a policy that is a wrapper for the Rust driver default load balancing policy,
The goal for this policy is to hold configuration options,
that will be passed to the Rust, during the session creation.
This policy was already deprecated in the DSx driver
As the old default load balancing policy is not supported,
ans starting form the next commit, we will use the load balancing policy,
this commit updates the default policy, to the supported one.
This commit attempts to to map the old policies to appropriate
rust default policy configuration. currently this is not tested,
as all of the current integration tests rely on info.queried hosts,
which is not available in the rust driver.
@wprzytula
Copy link
Contributor

Right now, this is not tested, as all of the current integration tests rely on info.queried hosts, which are not available in the rust driver.

I believe you can used HistoryListener capabilities of Rust Driver to emulate info.queriedHosts. Especially StructuredHistory should contain required information.


#[rustfmt::skip] // fmt splits the struct definition into multiple lines
define_js_to_rust_convertible_object!(
LoadBalancingConfig {
Copy link
Contributor

Choose a reason for hiding this comment

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

+1

Comment on lines 61 to 64
pub struct SessionWrapper {
pub(crate) inner: CachingSession,
pub(crate) session_load_balancing_policy: Option<Arc<dyn LoadBalancingPolicy>>,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🤔 Session-level LBP should be configured on the Session-level execution profile.

Comment on lines +313 to +324
if let Some(prefer_dc) = &config.prefer_datacenter {
if let Some(prefer_rack) = &config.prefer_rack {
builder = builder
.prefer_datacenter_and_rack(prefer_dc.to_owned(), prefer_rack.to_owned());
} else {
builder = builder.prefer_datacenter(prefer_dc.to_owned());
}
} else if config.prefer_rack.is_some() {
return Err(js_error(
"rack preference cannot be set without setting dc preference",
));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

♻️ Prefer a single match over pair of both config params instead of nested ifs.

Comment on lines +77 to +79
class NewDefaultLoadBalancingPolicy extends LoadBalancingPolicy {
constructor(config?: LoadBalancingConfig);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This will at some point no longer be new.
I'd call it simply DefaultLoadBalancingPolicy.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ugh, but there already is something called DefaultLoadBalancingPolicy...

Comment on lines +929 to +931
* It can be configured to be datacenter-aware, rack-aware and token-aware.
* Datacenter failover (sending query to a node from a remote datacenter)
* for queries with non local consistency mode is also supported.
Copy link
Contributor

Choose a reason for hiding this comment

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

AFAIR we changed the logic of DC failover to be possible also for queries with local consistency.
Please update the docs here. If you could be that kind and update Rust docs as well, it would be great 🙏

Copy link
Contributor

Choose a reason for hiding this comment

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

@Lorak-mmk changed Rust logic in 04a3751cfe635222e0d93c652e2af243c9a6fd3d, but docs must have remained obsolete.

Comment on lines +1037 to +1043
* When it is set, the policy will prefer to return alive remote replicas
* if datacenter failover is permitted and possible due to consistency
* constraints.
*
* @type {boolean?}
*/
permitDcFailover;
Copy link
Contributor

Choose a reason for hiding this comment

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

There are no more possible consistency constraints after the change in 04a3751cfe635222e0d93c652e2af243c9a6fd3d in Rust Driver.

Comment on lines -38 to 35
*/
exports.defaultLoadBalancingPolicy = function (localDc) {
return new loadBalancing.DefaultLoadBalancingPolicy(localDc);
exports.defaultLoadBalancingPolicy = function () {
return new loadBalancing.NewDefaultLoadBalancingPolicy();
};
Copy link
Contributor

Choose a reason for hiding this comment

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

💭 For maintaining as much compatibility as possible, shouldn't we accept localDc arg? Dunno.


/**
* @param {LoadBalancingConfig} config
* @param {LoadBalancingConfig} [config]
Copy link
Contributor

Choose a reason for hiding this comment

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

♻️ This should belong to an earlier commit, right?

Comment on lines +693 to +696
throw new Error(
"This load balancing policy does not appear to be supported by the driver. Root cause: " +
e.message,
);
Copy link
Contributor

Choose a reason for hiding this comment

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

🔧 Can we include the policy's class name in the message?

Comment on lines +58 to +65
/**
* @returns {LoadBalancingConfig}
* @package
*/
getRustConfiguration() {
// This error will be thrown by all policies, that do not override this method.
throw new Error("Currently this policy is not supported by the driver");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🔧

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/**
* @returns {LoadBalancingConfig}
* @package
*/
getRustConfiguration() {
// This error will be thrown by all policies, that do not override this method.
throw new Error("Currently this policy is not supported by the driver");
}
/**
* @returns {LoadBalancingConfig}
* @package
*/
getRustConfiguration() {
// This error will be thrown by all policies, that do not override this method.
throw new Error("Currently this load balancing policy is not supported by the driver");
}

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.

2 participants