idl: add a representation of client_state for forwarding

In the following patches, when we start allowing to forward CQL
requests to other nodes, we'll need to use the same client state
for executing the request on the destination node as we had on the
source. client_state contains many fields and we need to create
a new instance of it when we start handling the forwarded request,
so to prepare for the forwarding RPC, we add a serializable format
of the client_state as an IDL struct. The new class is missing some
fields that are not used while executing requests, and some whose
value is determined by the fact that the client state is used for
a forwarded request.
These include:
- driver name, driver version, client options - not used for executing
requests. Instead, we use these as data sources for the virtual
"clients" system table.
- auth_state - must be READY - we reached a bounce message, so we were
able to try executing the request locally
- _control_connection - used for altering a cql_server::connection, which
we don't have on the target node
- _default_timeout_config - used when updating service levels, also only
per-connection
- workload_type - used for deciding whether to allow shedding at the
start of processing the request, and for getting per-connection service
level params (for an API)
This commit is contained in:
Wojciech Mitros
2026-03-04 23:37:43 +01:00
parent b4a7fefe20
commit 170b82ddca
5 changed files with 99 additions and 1 deletions

View File

@@ -1493,7 +1493,8 @@ idls = ['idl/gossip_digest.idl.hh',
'idl/gossip.idl.hh',
'idl/migration_manager.idl.hh',
"idl/node_ops.idl.hh",
"idl/tasks.idl.hh"
"idl/tasks.idl.hh",
"idl/client_state.idl.hh",
]
scylla_tests_generic_dependencies = [

View File

@@ -68,6 +68,7 @@ set(idl_headers
migration_manager.idl.hh
node_ops.idl.hh
tasks.idl.hh
client_state.idl.hh
)
foreach(idl_header ${idl_headers})

33
idl/client_state.idl.hh Normal file
View File

@@ -0,0 +1,33 @@
/*
* Copyright 2026-present ScyllaDB
*/
/*
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
*/
#include "db/timeout_clock.hh"
#include "gms/inet_address_serializer.hh"
struct timeout_config {
db::timeout_clock::duration read_timeout;
db::timeout_clock::duration write_timeout;
db::timeout_clock::duration range_read_timeout;
db::timeout_clock::duration counter_write_timeout;
db::timeout_clock::duration truncate_timeout;
db::timeout_clock::duration cas_timeout;
db::timeout_clock::duration other_timeout;
};
namespace service {
struct forwarded_client_state {
sstring keyspace;
std::optional<sstring> username;
timeout_config timeout_config;
uint64_t protocol_extensions_mask;
gms::inet_address remote_address;
uint16_t remote_port;
};
}

View File

@@ -369,3 +369,27 @@ future<> service::client_state::set_client_options(
_client_options.emplace_back(std::move(cached_key), std::move(cached_value));
}
}
service::forwarded_client_state::forwarded_client_state(
sstring keyspace,
std::optional<sstring> username,
::timeout_config timeout_config,
uint64_t protocol_extensions_mask,
gms::inet_address remote_address,
uint16_t remote_port)
: keyspace(std::move(keyspace))
, username(std::move(username))
, timeout_config(std::move(timeout_config))
, protocol_extensions_mask(protocol_extensions_mask)
, remote_address(std::move(remote_address))
, remote_port(remote_port)
{ }
service::forwarded_client_state::forwarded_client_state(const client_state& cs)
: keyspace(cs.get_raw_keyspace())
, username(cs.user() ? std::optional<sstring>{cs.user()->name} : std::nullopt)
, timeout_config(cs.get_timeout_config())
, protocol_extensions_mask(static_cast<uint64_t>(cs.get_protocol_extensions().mask()))
, remote_address(cs.get_client_address())
, remote_port(cs.get_client_port())
{ }

View File

@@ -33,6 +33,24 @@ class database;
namespace service {
class client_state;
struct forwarded_client_state {
sstring keyspace;
std::optional<sstring> username;
timeout_config timeout_config;
uint64_t protocol_extensions_mask;
gms::inet_address remote_address;
uint16_t remote_port;
forwarded_client_state(sstring keyspace,
std::optional<sstring> username,
::timeout_config timeout_config,
uint64_t protocol_extensions_mask,
gms::inet_address remote_address,
uint16_t remote_port);
forwarded_client_state(const client_state& cs);
};
/**
* State related to a client connection.
*/
@@ -246,6 +264,23 @@ public:
, _sl_controller(&sl_controller)
{}
client_state(auth::service& auth_service,
qos::service_level_controller* sl_controller,
forwarded_client_state&& forwarded_state)
: _keyspace(std::move(forwarded_state.keyspace))
, _user(forwarded_state.username ? auth::authenticated_user(*forwarded_state.username) : auth::authenticated_user{})
, _auth_state(auth_state::READY)
, _is_internal(false)
, _bypass_auth_checks(false)
, _remote_address(socket_address(forwarded_state.remote_address, forwarded_state.remote_port))
, _auth_service(&auth_service)
, _sl_controller(sl_controller)
, _default_timeout_config(forwarded_state.timeout_config)
, _timeout_config(std::move(forwarded_state.timeout_config))
, _enabled_protocol_extensions(cql_transport::cql_protocol_extension_enum_set::from_mask(
forwarded_state.protocol_extensions_mask))
{}
client_state(const client_state&) = delete;
client_state(client_state&&) = default;
@@ -454,6 +489,10 @@ public:
return _enabled_protocol_extensions.contains(ext);
}
cql_transport::cql_protocol_extension_enum_set get_protocol_extensions() const {
return _enabled_protocol_extensions;
}
void set_protocol_extensions(cql_transport::cql_protocol_extension_enum_set exts) {
_enabled_protocol_extensions = std::move(exts);
}