Skip to content

Commit 1b1fefd

Browse files
committed
metadata.rs: Use new error type for errors of single keyspace
In the further commits we will introduce another error condition that doesn't fail the whole metadata fetch, but only a single keyspace.
1 parent 369ee35 commit 1b1fefd

File tree

1 file changed

+38
-14
lines changed

1 file changed

+38
-14
lines changed

scylla/src/cluster/metadata.rs

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@ type PerTable<T> = HashMap<String, T>;
6767
type PerKsTable<T> = HashMap<(String, String), T>;
6868
type 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
7183
pub(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
93105
pub(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 {
13641381
async 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(
14091426
async 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

Comments
 (0)