Skip to content

Commit e5b7d27

Browse files
committed
adapter: Fix error msg when can't find timestamp
1 parent cef8647 commit e5b7d27

File tree

14 files changed

+97
-127
lines changed

14 files changed

+97
-127
lines changed

src/adapter/src/coord/timestamp_selection.rs

Lines changed: 30 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ pub trait TimestampProvider {
248248
id_bundle: &CollectionIdBundle,
249249
when: &QueryWhen,
250250
oracle_read_ts: Option<Timestamp>,
251-
compute_instance: ComputeInstanceId,
252251
real_time_recency_ts: Option<Timestamp>,
253252
isolation_level: &IsolationLevel,
254253
timeline: &Option<Timeline>,
@@ -413,13 +412,9 @@ pub trait TimestampProvider {
413412
if !constraints.lower_bound().less_equal(&candidate)
414413
|| constraints.upper_bound().less_than(&candidate)
415414
{
416-
// TODO: Generate a better error msg, which includes all the constraints.
417-
coord_bail!(generate_timestamp_not_valid_error_msg(
418-
id_bundle,
419-
compute_instance,
420-
read_holds,
421-
candidate
422-
));
415+
return Err(AdapterError::ImpossibleTimestampConstraints {
416+
constraints: constraints.display(timeline.as_ref()).to_string(),
417+
});
423418
} else {
424419
candidate
425420
}
@@ -444,7 +439,6 @@ pub trait TimestampProvider {
444439
session: &Session,
445440
id_bundle: &CollectionIdBundle,
446441
when: &QueryWhen,
447-
compute_instance: ComputeInstanceId,
448442
timeline_context: &TimelineContext,
449443
oracle_read_ts: Option<Timestamp>,
450444
real_time_recency_ts: Option<Timestamp>,
@@ -460,7 +454,6 @@ pub trait TimestampProvider {
460454
session,
461455
id_bundle,
462456
when,
463-
compute_instance,
464457
timeline_context,
465458
oracle_read_ts,
466459
real_time_recency_ts,
@@ -475,7 +468,6 @@ pub trait TimestampProvider {
475468
session: &Session,
476469
id_bundle: &CollectionIdBundle,
477470
when: &QueryWhen,
478-
compute_instance: ComputeInstanceId,
479471
timeline_context: &TimelineContext,
480472
oracle_read_ts: Option<Timestamp>,
481473
real_time_recency_ts: Option<Timestamp>,
@@ -514,7 +506,6 @@ pub trait TimestampProvider {
514506
id_bundle,
515507
when,
516508
oracle_read_ts,
517-
compute_instance,
518509
real_time_recency_ts,
519510
isolation_level,
520511
&timeline,
@@ -580,36 +571,6 @@ pub trait TimestampProvider {
580571
}
581572
}
582573

583-
fn generate_timestamp_not_valid_error_msg(
584-
id_bundle: &CollectionIdBundle,
585-
compute_instance: ComputeInstanceId,
586-
read_holds: &ReadHolds<mz_repr::Timestamp>,
587-
candidate: mz_repr::Timestamp,
588-
) -> String {
589-
let mut invalid = Vec::new();
590-
591-
if let Some(compute_ids) = id_bundle.compute_ids.get(&compute_instance) {
592-
for id in compute_ids {
593-
let since = read_holds.since(id);
594-
if !since.less_equal(&candidate) {
595-
invalid.push((*id, since));
596-
}
597-
}
598-
}
599-
600-
for id in id_bundle.storage_ids.iter() {
601-
let since = read_holds.since(id);
602-
if !since.less_equal(&candidate) {
603-
invalid.push((*id, since));
604-
}
605-
}
606-
607-
format!(
608-
"Timestamp ({}) is not valid for all inputs: {:?}",
609-
candidate, invalid,
610-
)
611-
}
612-
613574
impl Coordinator {
614575
pub(crate) async fn oracle_read_ts(
615576
&self,
@@ -658,7 +619,6 @@ impl Coordinator {
658619
session,
659620
id_bundle,
660621
when,
661-
compute_instance,
662622
timeline_context,
663623
oracle_read_ts,
664624
real_time_recency_ts,
@@ -688,7 +648,6 @@ impl Coordinator {
688648
session,
689649
id_bundle,
690650
when,
691-
compute_instance,
692651
timeline_context,
693652
oracle_read_ts,
694653
real_time_recency_ts,
@@ -979,15 +938,21 @@ mod constraints {
979938
if !self.lower.is_empty() {
980939
writeln!(f, "lower:")?;
981940
for (ts, reason) in &self.lower {
982-
let ts = ts.iter().map(|t| t.display(timeline)).collect::<Vec<_>>();
983-
writeln!(f, " ({:?}): {:?}", reason, ts)?;
941+
let ts: Vec<_> = ts
942+
.iter()
943+
.map(|t| format!("{}", t.display(timeline)))
944+
.collect();
945+
writeln!(f, " ({}): [{}]", reason, ts.join(", "))?;
984946
}
985947
}
986948
if !self.upper.is_empty() {
987949
writeln!(f, "upper:")?;
988950
for (ts, reason) in &self.upper {
989-
let ts = ts.iter().map(|t| t.display(timeline)).collect::<Vec<_>>();
990-
writeln!(f, " ({:?}): {:?}", reason, ts)?;
951+
let ts: Vec<_> = ts
952+
.iter()
953+
.map(|t| format!("{}", t.display(timeline)))
954+
.collect();
955+
writeln!(f, " ({}): [{}]", reason, ts.join(", "))?;
991956
}
992957
}
993958
Ok(())
@@ -1052,52 +1017,43 @@ mod constraints {
10521017
pub enum Reason {
10531018
/// A compute input at a compute instance.
10541019
/// This is something like an index or view
1055-
/// that is mantained by compute.
1020+
/// that is maintained by compute.
10561021
ComputeInput(Vec<(ComputeInstanceId, GlobalId)>),
10571022
/// A storage input.
10581023
StorageInput(Vec<GlobalId>),
10591024
/// A specified isolation level and the timestamp it requires.
10601025
IsolationLevel(IsolationLevel),
1061-
/// Real-time recency may constrains the timestamp from below.
1026+
/// Real-time recency may constrain the timestamp from below.
10621027
RealTimeRecency,
10631028
/// The query expressed its own constraint on the timestamp.
10641029
QueryAsOf,
10651030
}
10661031

1067-
impl Debug for Reason {
1032+
impl fmt::Display for Reason {
10681033
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10691034
match self {
1070-
Reason::ComputeInput(ids) => write_split_ids(f, "ComputeInput", ids),
1071-
Reason::StorageInput(ids) => write_split_ids(f, "StorageInput", ids),
1035+
Reason::ComputeInput(ids) => {
1036+
let formatted: Vec<_> =
1037+
ids.iter().map(|(c, g)| format!("({}, {})", c, g)).collect();
1038+
write!(f, "Indexed inputs: [{}]", formatted.join(", "))
1039+
}
1040+
Reason::StorageInput(ids) => {
1041+
let formatted: Vec<_> = ids.iter().map(|g| format!("{}", g)).collect();
1042+
write!(f, "Storage inputs: [{}]", formatted.join(", "))
1043+
}
10721044
Reason::IsolationLevel(level) => {
1073-
write!(f, "IsolationLevel({:?})", level)
1045+
write!(f, "Isolation level: {:?}", level)
10741046
}
10751047
Reason::RealTimeRecency => {
1076-
write!(f, "RealTimeRecency")
1048+
write!(f, "Real-time recency")
10771049
}
10781050
Reason::QueryAsOf => {
1079-
write!(f, "QueryAsOf")
1051+
write!(f, "Query's AS OF")
10801052
}
10811053
}
10821054
}
10831055
}
10841056

1085-
//TODO: This is a bit of a hack to make the debug output of constraints more readable.
1086-
//We should probably have a more structured way to do this.
1087-
fn write_split_ids<T: Debug>(f: &mut fmt::Formatter, label: &str, ids: &[T]) -> fmt::Result {
1088-
let (ids, rest) = if ids.len() > 10 {
1089-
ids.split_at(10)
1090-
} else {
1091-
let rest: &[T] = &[];
1092-
(ids, rest)
1093-
};
1094-
if rest.is_empty() {
1095-
write!(f, "{}({:?})", label, ids)
1096-
} else {
1097-
write!(f, "{}({:?}, ... {} more)", label, ids, rest.len())
1098-
}
1099-
}
1100-
11011057
/// Given an interval [read, write) of timestamp options,
11021058
/// this expresses a preference for either end of the spectrum.
11031059
pub enum Preference {
@@ -1109,12 +1065,12 @@ mod constraints {
11091065
///
11101066
/// The preference only relates to immediate query inputs,
11111067
/// but it could be extended to transitive inputs as well.
1112-
/// For example, one could imagine prefering the freshest
1068+
/// For example, one could imagine preferring the freshest
11131069
/// data known to be ingested into Materialize, under the
11141070
/// premise that those answers should soon become available,
11151071
/// and may be more fresh than the immediate inputs.
11161072
FreshestAvailable,
1117-
/// Prefer the least valid timeastamp.
1073+
/// Prefer the least valid timestamp.
11181074
///
11191075
/// This is useful when one has no expressed freshness
11201076
/// constraints, and wants to minimally impact others.

src/adapter/src/error.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,18 @@ pub enum AdapterError {
247247
UnreadableSinkCollection,
248248
/// User sessions have been blocked.
249249
UserSessionsDisallowed,
250-
/// This use session has been deneid by a NetworkPolicy.
250+
/// This use session has been denied by a NetworkPolicy.
251251
NetworkPolicyDenied(NetworkPolicyError),
252252
/// Something attempted a write (to catalog, storage, tables, etc.) while in
253253
/// read-only mode.
254254
ReadOnly,
255255
AlterClusterTimeout,
256256
AlterClusterWhilePendingReplicas,
257257
AuthenticationError(AuthenticationError),
258+
/// Could not find a valid timestamp satisfying all constraints.
259+
ImpossibleTimestampConstraints {
260+
constraints: String,
261+
},
258262
}
259263

260264
#[derive(Debug, thiserror::Error)]
@@ -380,6 +384,9 @@ impl AdapterError {
380384
AdapterError::RtrDropFailure(name) => Some(format!("{name} dropped before ingesting data to the real-time recency point")),
381385
AdapterError::UserSessionsDisallowed => Some("Your organization has been blocked. Please contact support.".to_string()),
382386
AdapterError::NetworkPolicyDenied(reason)=> Some(format!("{reason}.")),
387+
AdapterError::ImpossibleTimestampConstraints { constraints } => {
388+
Some(format!("Constraints:\n{}", constraints))
389+
}
383390
_ => None,
384391
}
385392
}
@@ -618,6 +625,8 @@ impl AdapterError {
618625
SqlState::INVALID_PASSWORD
619626
}
620627
AdapterError::AuthenticationError(_) => SqlState::INVALID_AUTHORIZATION_SPECIFICATION,
628+
// similar to AbsurdSubscribeBounds
629+
AdapterError::ImpossibleTimestampConstraints { .. } => SqlState::DATA_EXCEPTION,
621630
}
622631
}
623632

@@ -957,6 +966,9 @@ impl fmt::Display for AdapterError {
957966
AdapterError::AlterClusterWhilePendingReplicas => {
958967
write!(f, "cannot alter clusters with pending updates")
959968
}
969+
AdapterError::ImpossibleTimestampConstraints { .. } => {
970+
write!(f, "could not find a valid timestamp for the query")
971+
}
960972
}
961973
}
962974
}

src/adapter/src/frontend_peek.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,7 +1334,6 @@ impl PeekClient {
13341334
session,
13351335
id_bundle,
13361336
when,
1337-
compute_instance,
13381337
timeline_context,
13391338
oracle_read_ts,
13401339
real_time_recency_ts,
@@ -1368,7 +1367,6 @@ impl PeekClient {
13681367
session,
13691368
id_bundle,
13701369
when,
1371-
compute_instance,
13721370
timeline_context,
13731371
oracle_read_ts,
13741372
real_time_recency_ts,

0 commit comments

Comments
 (0)