Skip to content

Commit e85ff4e

Browse files
committed
Implement non-blocking SHOW READYSET TABLES with more statuses
This patch switches away from the old SHOW READYSET TABLES behavior, which would run a blocking query on all domains for their tables' statuses, to the new state-machine-backed SHOW READYSET TABLES behavior, which responds immediately with the statuses of all tables by reporting what's presently in the state machine. The old way could block for several hours when compacting many large tables, which was unfortunate if you were interested in seeing what the current status was. The blocking could also happen after creating a cache, as the cache creation might create an index on our copy of the table, which again holds up our single-threaded domains for potentially long periods of time. Previously, the reported statuses were only: - "Snapshotting" - "Snapshotted" - "Not Replicated" (with reason in the description column) Now, the reported statuses are: - "Initializing" - "Snapshotting" (with percentage in description column) - "Compacting" (with percentage in description column) - "Creating index" (with percentage in description column) - "Online" - "Not replicated" (with reason in the description column) Instead of having to read logs to determine the progress of these operations, you can now find the progress reported as percentages displayed in the description column for the table. Fixes: REA-2463, REA-2907, REA-4863, REA-5751 Release-Note-Core: Overhaul SHOW READYSET TABLES to always respond immediately, report more table statuses such as compaction and index creation, and report progress as a percentage in the description column during snapshot, compaction, and index creation. Change-Id: I094cf7e0e9aa75fb65ea036abd94db2ed5240a08 Reviewed-on: https://gerrit.readyset.name/c/readyset/+/10207 Tested-by: Buildkite CI Reviewed-by: Michael Zink <michael.z@readyset.io>
1 parent b8443c9 commit e85ff4e

File tree

8 files changed

+43
-93
lines changed

8 files changed

+43
-93
lines changed

readyset-adapter/src/backend/noria_connector.rs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -937,27 +937,14 @@ impl NoriaConnector {
937937
};
938938
let data = statuses
939939
.into_iter()
940-
.map(|(tbl, status)| {
941-
let replication_status_str = status.to_string();
942-
let replication_split = replication_status_str
943-
.splitn(2, ": ")
944-
.collect::<Vec<&str>>();
945-
let (replication_status, description) =
946-
if replication_split[0].starts_with("Not Replicated") {
947-
(
948-
replication_split[0].to_string(),
949-
replication_split.get(1).unwrap_or(&"").to_string(),
950-
)
951-
} else {
952-
(status.to_string(), "".to_string())
953-
};
940+
.map(|(table, status)| {
954941
vec![
955-
tbl.display(self.parse_dialect).to_string().into(),
956-
replication_status.into(),
957-
description.into(),
942+
table.display(self.parse_dialect).to_string().into(),
943+
status.to_string().into(),
944+
status.description().into(),
958945
]
959946
})
960-
.collect::<Vec<_>>();
947+
.collect();
961948

962949
Ok(QueryResult::from_owned(schema, vec![Results::new(data)]))
963950
}

readyset-client/src/controller.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ use crate::status::ReadySetControllerStatus;
3737
use crate::table::{PersistencePoint, Table, TableBuilder, TableRpc};
3838
use crate::view::{View, ViewBuilder, ViewRpc};
3939
use crate::{
40-
ReplicationOffset, SingleKeyEviction, TableReplicationStatus, TableStatus, ViewCreateRequest,
41-
ViewFilter, ViewRequest,
40+
ReplicationOffset, SingleKeyEviction, TableStatus, ViewCreateRequest, ViewFilter, ViewRequest,
4241
};
4342

4443
mod rpc;
@@ -519,9 +518,9 @@ impl ReadySetHandle {
519518
}
520519

521520
simple_request!(
522-
/// Query the status of all known tables, including those not replicated by ReadySet if
521+
/// Query the status of all known tables, including those not replicated by Readyset if
523522
/// the `all` parameter is set to `true`.
524-
table_statuses(all: bool) -> BTreeMap<Relation, TableReplicationStatus>
523+
table_statuses(all: bool) -> BTreeMap<Relation, TableStatus>
525524
);
526525

527526
simple_request!(

readyset-client/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,7 @@ pub use crate::controller::{
354354
};
355355
pub use crate::table::{
356356
Modification, Operation, PacketData, PacketPayload, PacketTrace, PersistencePoint, Table,
357-
TableOperation, TableReplicationStatus, TableRequest, TableStatus,
358-
TABLE_STATUS_REPORT_INTERVAL,
357+
TableOperation, TableRequest, TableStatus, TABLE_STATUS_REPORT_INTERVAL,
359358
};
360359
pub use crate::view::{
361360
KeyComparison, LookupResult, ReadQuery, ReadReply, ReadReplyBatch, ReadReplyStats, SchemaType,

readyset-client/src/table.rs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -272,30 +272,6 @@ impl fmt::Debug for PacketData {
272272
}
273273
}
274274

275-
/// The status of a single table with respect to replication
276-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
277-
pub enum TableReplicationStatus {
278-
/// The table is not being replicated by ReadySet
279-
NotReplicated(NotReplicatedReason),
280-
/// The table is currently being snapshotted by ReadySet
281-
Snapshotting,
282-
/// The table has been successfully snapshotted by ReadySet
283-
Snapshotted,
284-
}
285-
286-
impl Display for TableReplicationStatus {
287-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
288-
match self {
289-
TableReplicationStatus::NotReplicated(reason) => {
290-
write!(f, "Not Replicated : {}", reason.description())?;
291-
}
292-
TableReplicationStatus::Snapshotting => f.write_str("Snapshotting")?,
293-
TableReplicationStatus::Snapshotted => f.write_str("Snapshotted")?,
294-
}
295-
Ok(())
296-
}
297-
}
298-
299275
/// The status of a table.
300276
#[derive(Debug, Clone, Serialize, Deserialize)]
301277
pub enum TableStatus {

readyset-server/src/controller/inner.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -432,11 +432,8 @@ impl Leader {
432432
}
433433
(&Method::POST, "/table_statuses") => {
434434
let all: bool = bincode::deserialize(&body)?;
435-
let res = {
436-
let ds = self.dataflow_state_handle.read().await;
437-
ds.table_statuses(all).await?
438-
};
439-
return_serialized!(res)
435+
let table_statuses = self.table_statuses.get(all).await;
436+
return_serialized!(table_statuses)
440437
}
441438
(&Method::POST, "/set_table_status") => {
442439
let statuses: HashMap<Relation, TableStatus> = bincode::deserialize(&body)?;

readyset-server/src/controller/mod.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,9 +1415,7 @@ mod tests {
14151415
use dataflow::DomainIndex;
14161416
use readyset_client::debug::info::KeyCount;
14171417
use readyset_client::recipe::changelist::{Change, ChangeList};
1418-
use readyset_client::{
1419-
PersistencePoint, TableOperation, TableReplicationStatus, ViewCreateRequest,
1420-
};
1418+
use readyset_client::{PersistencePoint, TableOperation, TableStatus, ViewCreateRequest};
14211419
use readyset_data::Dialect as DataDialect;
14221420
use readyset_sql::ast::{NonReplicatedRelation, NotReplicatedReason, Relation};
14231421
use readyset_sql::Dialect;
@@ -1829,14 +1827,14 @@ mod tests {
18291827
schema: Some("s2".into()),
18301828
name: "snapshotting_t".into(),
18311829
},
1832-
TableReplicationStatus::Snapshotting
1830+
TableStatus::Snapshotting(None)
18331831
),
18341832
(
18351833
Relation {
18361834
schema: Some("s2".into()),
18371835
name: "snapshotted_t".into(),
18381836
},
1839-
TableReplicationStatus::Snapshotted
1837+
TableStatus::Online
18401838
),
18411839
])
18421840
);
@@ -1850,21 +1848,21 @@ mod tests {
18501848
schema: Some("s1".into()),
18511849
name: "t".into(),
18521850
},
1853-
TableReplicationStatus::NotReplicated(NotReplicatedReason::Configuration)
1851+
TableStatus::NotReplicated(NotReplicatedReason::Configuration)
18541852
),
18551853
(
18561854
Relation {
18571855
schema: Some("s2".into()),
18581856
name: "snapshotting_t".into(),
18591857
},
1860-
TableReplicationStatus::Snapshotting
1858+
TableStatus::Snapshotting(None)
18611859
),
18621860
(
18631861
Relation {
18641862
schema: Some("s2".into()),
18651863
name: "snapshotted_t".into(),
18661864
},
1867-
TableReplicationStatus::Snapshotted
1865+
TableStatus::Online
18681866
),
18691867
])
18701868
);

readyset-server/src/controller/state.rs

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ use readyset_client::query::QueryId;
4747
use readyset_client::recipe::changelist::{Change, ChangeList};
4848
use readyset_client::recipe::{CacheExpr, ExtendRecipeSpec};
4949
use readyset_client::{
50-
PersistencePoint, SingleKeyEviction, TableReplicationStatus, TableStatus, ViewCreateRequest,
51-
ViewFilter, ViewRequest, ViewSchema,
50+
PersistencePoint, SingleKeyEviction, TableStatus, ViewCreateRequest, ViewFilter, ViewRequest,
51+
ViewSchema,
5252
};
5353
use readyset_data::{DfValue, Dialect};
5454
use readyset_errors::{
@@ -1054,36 +1054,6 @@ impl DfState {
10541054
.collect()
10551055
}
10561056

1057-
/// Query the status of all known tables, including those not replicated by ReadySet if `all`
1058-
/// is set to `true`.
1059-
pub(super) async fn table_statuses(
1060-
&self,
1061-
all: bool,
1062-
) -> ReadySetResult<BTreeMap<Relation, TableReplicationStatus>> {
1063-
let known_tables = self.tables();
1064-
let snapshotting_tables = self.snapshotting_tables().await?;
1065-
let out = known_tables.into_keys().map(|tbl| {
1066-
let status = if snapshotting_tables.contains(&tbl) {
1067-
TableReplicationStatus::Snapshotting
1068-
} else {
1069-
TableReplicationStatus::Snapshotted
1070-
};
1071-
(tbl, status)
1072-
});
1073-
if all {
1074-
Ok(out
1075-
.chain(
1076-
self.non_replicated_relations()
1077-
.iter()
1078-
.cloned()
1079-
.map(|tbl| (tbl.name, TableReplicationStatus::NotReplicated(tbl.reason))),
1080-
)
1081-
.collect())
1082-
} else {
1083-
Ok(out.collect())
1084-
}
1085-
}
1086-
10871057
/// Returns a list of all table names that are currently involved in snapshotting.
10881058
pub(super) async fn snapshotting_tables(&self) -> ReadySetResult<HashSet<Relation>> {
10891059
let domains = self.domains_with_base_tables().await?;

readyset-server/src/controller/table_status.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,30 @@ impl TableStatusState {
103103
*self.state.write().await = Some(state);
104104
}
105105

106+
/// Get all known table statuses.
107+
pub async fn get(&self, all: bool) -> BTreeMap<Relation, TableStatus> {
108+
let state = self.state.read().await;
109+
let state = match state.as_ref() {
110+
Some(state) => state,
111+
None => return BTreeMap::new(),
112+
};
113+
114+
if all {
115+
state.clone()
116+
} else {
117+
state
118+
.iter()
119+
.filter_map(|(table, status)| {
120+
if matches!(status, TableStatus::NotReplicated(..)) {
121+
None
122+
} else {
123+
Some((table.clone(), status.clone()))
124+
}
125+
})
126+
.collect()
127+
}
128+
}
129+
106130
/// Update the statuses for multiple tables.
107131
///
108132
/// NOTE: Only call this if you know what you're doing. Most users should instead feed updates

0 commit comments

Comments
 (0)