scylla/client/self_identity.rs
1use std::borrow::Cow;
2
3/// Driver and application self-identifying information,
4/// to be sent in STARTUP message.
5#[derive(Debug, Clone, Default)]
6pub struct SelfIdentity<'id> {
7 // Custom driver identity can be set if a custom driver build is running,
8 // or an entirely different driver is operating on top of Rust driver
9 // (e.g. cpp-rust-driver).
10 custom_driver_name: Option<Cow<'id, str>>,
11 custom_driver_version: Option<Cow<'id, str>>,
12
13 // ### Q: Where do APPLICATION_NAME, APPLICATION_VERSION and CLIENT_ID come from?
14 // - there are no columns in system.clients dedicated to those attributes,
15 // - APPLICATION_NAME / APPLICATION_VERSION are not present in Scylla's source code at all,
16 // - only 2 results in Cassandra source is some example in docs:
17 // https://github.com/apache/cassandra/blob/d3cbf9c1f72057d2a5da9df8ed567d20cd272931/doc/modules/cassandra/pages/managing/operating/virtualtables.adoc?plain=1#L218.
18 // APPLICATION_NAME and APPLICATION_VERSION appears in client_options which
19 // is an arbitrary dict where client can send any keys.
20 // - driver variables are mentioned in protocol v5
21 // (https://github.com/apache/cassandra/blob/d3cbf9c1f72057d2a5da9df8ed567d20cd272931/doc/native_protocol_v5.spec#L480),
22 // application variables are not.
23 //
24 // ### A:
25 // The following options are not exposed anywhere in Scylla tables.
26 // They come directly from CPP driver, and they are supported in Cassandra
27 //
28 // See https://github.com/scylladb/cpp-driver/blob/fa0f27069a625057984d1fa58f434ea99b86c83f/include/cassandra.h#L2916.
29 // As we want to support as big subset of its API as possible in cpp-rust-driver, I decided to expose API for setting
30 // those particular key-value pairs, similarly to what cpp-driver does, and not an API to set arbitrary key-value pairs.
31 //
32 // Allowing users to set arbitrary options could break the driver by overwriting options that bear special meaning,
33 // e.g. the shard-aware port. Therefore, I'm against such liberal API. OTOH, we need to expose APPLICATION_NAME,
34 // APPLICATION_VERSION and CLIENT_ID for cpp-rust-driver.
35
36 // Application identity can be set to distinguish different applications
37 // connected to the same cluster.
38 application_name: Option<Cow<'id, str>>,
39 application_version: Option<Cow<'id, str>>,
40
41 // A (unique) client ID can be set to distinguish different instances
42 // of the same application connected to the same cluster.
43 client_id: Option<Cow<'id, str>>,
44}
45
46impl<'id> SelfIdentity<'id> {
47 pub fn new() -> Self {
48 Self::default()
49 }
50
51 /// Advertises a custom driver name, which can be used if a custom driver build is running,
52 /// or an entirely different driver is operating on top of Rust driver
53 /// (e.g. cpp-rust-driver).
54 pub fn set_custom_driver_name(&mut self, custom_driver_name: impl Into<Cow<'id, str>>) {
55 self.custom_driver_name = Some(custom_driver_name.into());
56 }
57
58 /// Advertises a custom driver name. See [Self::set_custom_driver_name] for use cases.
59 pub fn with_custom_driver_name(mut self, custom_driver_name: impl Into<Cow<'id, str>>) -> Self {
60 self.custom_driver_name = Some(custom_driver_name.into());
61 self
62 }
63
64 /// Custom driver name to be advertised. See [Self::set_custom_driver_name] for use cases.
65 pub fn get_custom_driver_name(&self) -> Option<&str> {
66 self.custom_driver_name.as_deref()
67 }
68
69 /// Advertises a custom driver version. See [Self::set_custom_driver_name] for use cases.
70 pub fn set_custom_driver_version(&mut self, custom_driver_version: impl Into<Cow<'id, str>>) {
71 self.custom_driver_version = Some(custom_driver_version.into());
72 }
73
74 /// Advertises a custom driver version. See [Self::set_custom_driver_name] for use cases.
75 pub fn with_custom_driver_version(
76 mut self,
77 custom_driver_version: impl Into<Cow<'id, str>>,
78 ) -> Self {
79 self.custom_driver_version = Some(custom_driver_version.into());
80 self
81 }
82
83 /// Custom driver version to be advertised. See [Self::set_custom_driver_version] for use cases.
84 pub fn get_custom_driver_version(&self) -> Option<&str> {
85 self.custom_driver_version.as_deref()
86 }
87
88 /// Advertises an application name, which can be used to distinguish different applications
89 /// connected to the same cluster.
90 pub fn set_application_name(&mut self, application_name: impl Into<Cow<'id, str>>) {
91 self.application_name = Some(application_name.into());
92 }
93
94 /// Advertises an application name. See [Self::set_application_name] for use cases.
95 pub fn with_application_name(mut self, application_name: impl Into<Cow<'id, str>>) -> Self {
96 self.application_name = Some(application_name.into());
97 self
98 }
99
100 /// Application name to be advertised. See [Self::set_application_name] for use cases.
101 pub fn get_application_name(&self) -> Option<&str> {
102 self.application_name.as_deref()
103 }
104
105 /// Advertises an application version. See [Self::set_application_name] for use cases.
106 pub fn set_application_version(&mut self, application_version: impl Into<Cow<'id, str>>) {
107 self.application_version = Some(application_version.into());
108 }
109
110 /// Advertises an application version. See [Self::set_application_name] for use cases.
111 pub fn with_application_version(
112 mut self,
113 application_version: impl Into<Cow<'id, str>>,
114 ) -> Self {
115 self.application_version = Some(application_version.into());
116 self
117 }
118
119 /// Application version to be advertised. See [Self::set_application_version] for use cases.
120 pub fn get_application_version(&self) -> Option<&str> {
121 self.application_version.as_deref()
122 }
123
124 /// Advertises a client ID, which can be set to distinguish different instances
125 /// of the same application connected to the same cluster.
126 pub fn set_client_id(&mut self, client_id: impl Into<Cow<'id, str>>) {
127 self.client_id = Some(client_id.into());
128 }
129
130 /// Advertises a client ID. See [Self::set_client_id] for use cases.
131 pub fn with_client_id(mut self, client_id: impl Into<Cow<'id, str>>) -> Self {
132 self.client_id = Some(client_id.into());
133 self
134 }
135
136 /// Client ID to be advertised. See [Self::set_client_id] for use cases.
137 pub fn get_client_id(&self) -> Option<&str> {
138 self.client_id.as_deref()
139 }
140}