@@ -67,6 +67,18 @@ type PerTable<T> = HashMap<String, T>;
6767type PerKsTable < T > = HashMap < ( String , String ) , T > ;
6868type PerKsTableResult < T , E > = PerKsTable < Result < T , E > > ;
6969
70+ /// Indicates that reading metadata failed, but in a way
71+ /// that we can handle, by throwing out data for a keyspace.
72+ /// It is possible that some of the errors could be handled in even
73+ /// more granular way (e.g. throwing out a single table), but keyspace
74+ /// granularity seems like a good choice given how independent keyspaces
75+ /// are from each other.
76+ #[ derive( Clone , Debug , Error ) ]
77+ pub ( crate ) enum SingleKeyspaceMetadataError {
78+ #[ error( transparent) ]
79+ MissingUDT ( MissingUserDefinedType ) ,
80+ }
81+
7082/// Allows to read current metadata from the cluster
7183pub ( crate ) struct MetadataReader {
7284 control_connection_pool_config : PoolConfig ,
@@ -92,7 +104,7 @@ pub(crate) struct MetadataReader {
92104/// Describes all metadata retrieved from the cluster
93105pub ( crate ) struct Metadata {
94106 pub ( crate ) peers : Vec < Peer > ,
95- pub ( crate ) keyspaces : HashMap < String , Result < Keyspace , MissingUserDefinedType > > ,
107+ pub ( crate ) keyspaces : HashMap < String , Result < Keyspace , SingleKeyspaceMetadataError > > ,
96108}
97109
98110#[ non_exhaustive] // <- so that we can add more fields in a backwards-compatible way
@@ -902,7 +914,7 @@ async fn query_keyspaces(
902914 conn : & Arc < Connection > ,
903915 keyspaces_to_fetch : & [ String ] ,
904916 fetch_schema : bool ,
905- ) -> Result < PerKeyspaceResult < Keyspace , MissingUserDefinedType > , MetadataError > {
917+ ) -> Result < PerKeyspaceResult < Keyspace , SingleKeyspaceMetadataError > , MetadataError > {
906918 let rows = query_filter_keyspace_name :: < ( String , HashMap < String , String > ) > (
907919 conn,
908920 "select keyspace_name, replication from system_schema.keyspaces" ,
@@ -953,15 +965,20 @@ async fn query_keyspaces(
953965
954966 // As you can notice, in this file we generally operate on two layers of errors:
955967 // - Outer (MetadataError) if something went wrong with querying the cluster.
956- // - Inner (currently MissingUserDefinedType, possibly other variants in the future) if the fetched metadata
957- // turned out to not be fully consistent.
968+ // - Inner (SingleKeyspaceMetadataError) if the fetched metadata turned out to not be fully consistent.
958969 // If there is an inner error, we want to drop metadata for the whole keyspace.
959- // This logic checks if either tables views or UDTs have such inner error, and returns it if so.
970+ // This logic checks if either tables, views, or UDTs have such inner error, and returns it if so.
960971 // Notice that in the error branch, return value is wrapped in `Ok` - but this is the
961972 // outer error, so it just means there was no error while querying the cluster.
962973 let ( tables, views, user_defined_types) = match ( tables, views, user_defined_types) {
963974 ( Ok ( t) , Ok ( v) , Ok ( u) ) => ( t, v, u) ,
964- ( Err ( e) , _, _) | ( _, Err ( e) , _) | ( _, _, Err ( e) ) => return Ok ( ( keyspace_name, Err ( e) ) ) ,
975+ ( Err ( e) , _, _) | ( _, Err ( e) , _) => return Ok ( ( keyspace_name, Err ( e) ) ) ,
976+ ( _, _, Err ( e) ) => {
977+ return Ok ( (
978+ keyspace_name,
979+ Err ( SingleKeyspaceMetadataError :: MissingUDT ( e) ) ,
980+ ) )
981+ }
965982 } ;
966983
967984 let keyspace = Keyspace {
@@ -1364,8 +1381,8 @@ mod toposort_tests {
13641381async fn query_tables (
13651382 conn : & Arc < Connection > ,
13661383 keyspaces_to_fetch : & [ String ] ,
1367- tables : & mut PerKsTableResult < Table , MissingUserDefinedType > ,
1368- ) -> Result < PerKeyspaceResult < PerTable < Table > , MissingUserDefinedType > , MetadataError > {
1384+ tables : & mut PerKsTableResult < Table , SingleKeyspaceMetadataError > ,
1385+ ) -> Result < PerKeyspaceResult < PerTable < Table > , SingleKeyspaceMetadataError > , MetadataError > {
13691386 let rows = query_filter_keyspace_name :: < ( String , String ) > (
13701387 conn,
13711388 "SELECT keyspace_name, table_name FROM system_schema.tables" ,
@@ -1409,8 +1426,9 @@ async fn query_tables(
14091426async fn query_views (
14101427 conn : & Arc < Connection > ,
14111428 keyspaces_to_fetch : & [ String ] ,
1412- tables : & mut PerKsTableResult < Table , MissingUserDefinedType > ,
1413- ) -> Result < PerKeyspaceResult < PerTable < MaterializedView > , MissingUserDefinedType > , MetadataError > {
1429+ tables : & mut PerKsTableResult < Table , SingleKeyspaceMetadataError > ,
1430+ ) -> Result < PerKeyspaceResult < PerTable < MaterializedView > , SingleKeyspaceMetadataError > , MetadataError >
1431+ {
14141432 let rows = query_filter_keyspace_name :: < ( String , String , String ) > (
14151433 conn,
14161434 "SELECT keyspace_name, view_name, base_table_name FROM system_schema.views" ,
@@ -1465,7 +1483,7 @@ async fn query_tables_schema(
14651483 conn : & Arc < Connection > ,
14661484 keyspaces_to_fetch : & [ String ] ,
14671485 udts : & PerKeyspaceResult < PerTable < Arc < UserDefinedType < ' static > > > , MissingUserDefinedType > ,
1468- ) -> Result < PerKsTableResult < Table , MissingUserDefinedType > , MetadataError > {
1486+ ) -> Result < PerKsTableResult < Table , SingleKeyspaceMetadataError > , MetadataError > {
14691487 // Upon migration from thrift to CQL, Cassandra internally creates a surrogate column "value" of
14701488 // type EmptyType for dense tables. This resolves into this CQL type name.
14711489 // This column shouldn't be exposed to the user but is currently exposed in system tables.
@@ -1484,7 +1502,7 @@ async fn query_tables_schema(
14841502
14851503 let empty_ok_map = Ok ( HashMap :: new ( ) ) ;
14861504
1487- let mut tables_schema: HashMap < _ , Result < _ , MissingUserDefinedType > > = HashMap :: new ( ) ;
1505+ let mut tables_schema: HashMap < _ , Result < _ , SingleKeyspaceMetadataError > > = HashMap :: new ( ) ;
14881506
14891507 rows. map ( |row_result| {
14901508 let ( keyspace_name, table_name, column_name, kind, position, type_) = row_result?;
@@ -1518,7 +1536,10 @@ async fn query_tables_schema(
15181536 // is minor enough to ignore. Note that the first issue also applies to
15191537 // solution 1: but the keyspace won't be present in the result at all,
15201538 // which is arguably worse.
1521- tables_schema. insert ( ( keyspace_name, table_name) , Err ( e. clone ( ) ) ) ;
1539+ tables_schema. insert (
1540+ ( keyspace_name, table_name) ,
1541+ Err ( SingleKeyspaceMetadataError :: MissingUDT ( e. clone ( ) ) ) ,
1542+ ) ;
15221543 return Ok :: < _ , MetadataError > ( ( ) ) ;
15231544 }
15241545 } ;
@@ -1532,7 +1553,10 @@ async fn query_tables_schema(
15321553 let cql_type = match pre_cql_type. into_cql_type ( & keyspace_name, keyspace_udts) {
15331554 Ok ( t) => t,
15341555 Err ( e) => {
1535- tables_schema. insert ( ( keyspace_name, table_name) , Err ( e) ) ;
1556+ tables_schema. insert (
1557+ ( keyspace_name, table_name) ,
1558+ Err ( SingleKeyspaceMetadataError :: MissingUDT ( e) ) ,
1559+ ) ;
15361560 return Ok :: < _ , MetadataError > ( ( ) ) ;
15371561 }
15381562 } ;
0 commit comments