1+ //! Implementation and negotiation of extensions to the CQL protocol.
2+
13use std:: borrow:: Cow ;
24use std:: collections:: HashMap ;
35
46const RATE_LIMIT_ERROR_EXTENSION : & str = "SCYLLA_RATE_LIMIT_ERROR" ;
7+ /// The extension used to add metadata for LWT optimization.
8+ /// See [ProtocolFeatures::lwt_optimization_meta_bit_mask] and
9+ /// [related issue](https://github.com/scylladb/scylla-rust-driver/issues/100)
10+ /// for more details.
511pub const SCYLLA_LWT_ADD_METADATA_MARK_EXTENSION : & str = "SCYLLA_LWT_ADD_METADATA_MARK" ;
12+ /// The key of the single entry of the LWT optimization extension,
13+ /// which entry is a bit mask for the frame flags used to mark LWT frames.
614pub const LWT_OPTIMIZATION_META_BIT_MASK_KEY : & str = "LWT_OPTIMIZATION_META_BIT_MASK" ;
715const TABLETS_ROUTING_V1_KEY : & str = "TABLETS_ROUTING_V1" ;
816
17+ /// Which protocol extensions are supported by the server.
18+ ///
19+ /// This is used to inform the server about the features that the client supports,
20+ /// so that the server can adjust its behavior accordingly.
21+ ///
22+ /// So to draw the picture:
23+ /// - server responds to an `OPTIONS` frame with a `SUPPORTED` frame with the list of
24+ /// protocol features it supports;
25+ /// - client parses the `SUPPORTED` frame by extracting extensions it recognizes (supports)
26+ /// and creates a `ProtocolFeatures` instance;
27+ /// - from now on, client uses this instance to determine how to handle certain frames,
28+ /// e.g. whether to expect a rate limit error or how to handle LWT operations;
29+ /// - client also adds the features it supports to the `STARTUP` frame and sends it to
30+ /// the server, which finishes the extensions negotiation process.
931#[ derive( Default , Clone , Copy , Debug , PartialEq , Eq ) ]
1032#[ non_exhaustive]
1133pub struct ProtocolFeatures {
34+ /// The error code to use for rate limit errors, if negotiated.
1235 pub rate_limit_error : Option < i32 > ,
36+
37+ /// The bit mask used for the LWT optimization, if negotiated.
38+ /// This is used to mark PREPARED response frames as related to LWT operations
39+ /// in order to to optimize the handling of LWT requests.
40+ ///
41+ /// The mask is ANDed with the flags of the PREPARED response frame,
42+ /// and if the result is equal to the mask, it means that the frame is related
43+ /// to an LWT operation.
1344 pub lwt_optimization_meta_bit_mask : Option < u32 > ,
45+
46+ /// Whether the server supports tablets routing v1.
1447 pub tablets_v1_supported : bool ,
1548}
1649
1750// TODO: Log information about options which failed to parse
1851
1952impl ProtocolFeatures {
53+ /// Parses the supported protocol features from the `supported` map.
2054 pub fn parse_from_supported ( supported : & HashMap < String , Vec < String > > ) -> Self {
2155 Self {
2256 rate_limit_error : Self :: maybe_parse_rate_limit_error ( supported) ,
@@ -52,6 +86,7 @@ impl ProtocolFeatures {
5286 . find_map ( |v| v. as_str ( ) . strip_prefix ( key) ?. strip_prefix ( '=' ) )
5387 }
5488
89+ /// Adds the protocol features as STARTUP options.
5590 pub fn add_startup_options ( & self , options : & mut HashMap < Cow < ' _ , str > , Cow < ' _ , str > > ) {
5691 if self . rate_limit_error . is_some ( ) {
5792 options. insert ( Cow :: Borrowed ( RATE_LIMIT_ERROR_EXTENSION ) , Cow :: Borrowed ( "" ) ) ;
@@ -68,6 +103,9 @@ impl ProtocolFeatures {
68103 }
69104 }
70105
106+ /// Checks if the given flags of a PREPARED response contain the LWT optimization mark.
107+ ///
108+ /// If the extension was not negotiated, it conservatively returns `false`.
71109 pub fn prepared_flags_contain_lwt_mark ( & self , flags : u32 ) -> bool {
72110 self . lwt_optimization_meta_bit_mask
73111 . map ( |mask| ( flags & mask) == mask)
0 commit comments