Skip to content

Commit 12a89e4

Browse files
abey79Wumpf
andauthored
First iteration of a dedicated UI and communication for the Redap server/catalog/collection browser (#9018)
### Related * Closes: #9003 ### What Implement a whole new Redap server/catalog/collection UI. --------- Co-authored-by: Andreas Reich <[email protected]>
1 parent 96832b1 commit 12a89e4

File tree

37 files changed

+1178
-463
lines changed

37 files changed

+1178
-463
lines changed

ARCHITECTURE.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ Of course, this will only take us so far. In the future we plan on caching queri
9898
Here is an overview of the crates included in the project:
9999

100100
<picture>
101-
<img src="https://static.rerun.io/crates/161078ff2b88caf8065e4bf8fb631a318329f501/full.png" alt="">
102-
<source media="(max-width: 480px)" srcset="https://static.rerun.io/crates/161078ff2b88caf8065e4bf8fb631a318329f501/480w.png">
103-
<source media="(max-width: 768px)" srcset="https://static.rerun.io/crates/161078ff2b88caf8065e4bf8fb631a318329f501/768w.png">
104-
<source media="(max-width: 1024px)" srcset="https://static.rerun.io/crates/161078ff2b88caf8065e4bf8fb631a318329f501/1024w.png">
105-
<source media="(max-width: 1200px)" srcset="https://static.rerun.io/crates/161078ff2b88caf8065e4bf8fb631a318329f501/1200w.png">
101+
<img src="https://static.rerun.io/crates/4ebb81d4dc640dfb2634d37fec5c53e80fb25f51/full.png" alt="">
102+
<source media="(max-width: 480px)" srcset="https://static.rerun.io/crates/4ebb81d4dc640dfb2634d37fec5c53e80fb25f51/480w.png">
103+
<source media="(max-width: 768px)" srcset="https://static.rerun.io/crates/4ebb81d4dc640dfb2634d37fec5c53e80fb25f51/768w.png">
104+
<source media="(max-width: 1024px)" srcset="https://static.rerun.io/crates/4ebb81d4dc640dfb2634d37fec5c53e80fb25f51/1024w.png">
105+
<source media="(max-width: 1200px)" srcset="https://static.rerun.io/crates/4ebb81d4dc640dfb2634d37fec5c53e80fb25f51/1200w.png">
106106
</picture>
107107

108108
<!-- !!! IMPORTANT!!!
@@ -134,8 +134,9 @@ Update instructions:
134134
##### UI crates
135135

136136
| Crate | Description |
137-
| --------------------- | ---------------------------------------------------------------------------------------------------------- |
137+
|-----------------------|------------------------------------------------------------------------------------------------------------|
138138
| re_blueprint_tree | The UI for the blueprint tree in the left panel. |
139+
| re_catalog_hub | The UI and communication to implement the in-viewer catalog browser |
139140
| re_chunk_store_ui | A chunk store browser UI. |
140141
| re_component_ui | Provides UI editors for Rerun component data for registration with the Rerun Viewer component UI registry. |
141142
| re_selection_panel | The UI for the selection panel. |

Cargo.lock

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5816,6 +5816,34 @@ dependencies = [
58165816
"convert_case",
58175817
]
58185818

5819+
[[package]]
5820+
name = "re_catalog_hub"
5821+
version = "0.23.0-alpha.1+dev"
5822+
dependencies = [
5823+
"ahash",
5824+
"arrow",
5825+
"egui",
5826+
"egui_table",
5827+
"once_cell",
5828+
"parking_lot",
5829+
"re_arrow_util",
5830+
"re_grpc_client",
5831+
"re_log",
5832+
"re_log_encoding",
5833+
"re_log_types",
5834+
"re_protos",
5835+
"re_sorbet",
5836+
"re_types",
5837+
"re_types_core",
5838+
"re_ui",
5839+
"re_view_dataframe",
5840+
"re_viewer_context",
5841+
"thiserror 1.0.65",
5842+
"tokio-stream",
5843+
"tonic",
5844+
"tonic-web-wasm-client",
5845+
]
5846+
58195847
[[package]]
58205848
name = "re_chunk"
58215849
version = "0.23.0-alpha.1+dev"
@@ -6000,12 +6028,15 @@ dependencies = [
60006028
"rayon",
60016029
"re_build_tools",
60026030
"re_data_loader",
6031+
"re_error",
60036032
"re_grpc_client",
60046033
"re_log",
60056034
"re_log_encoding",
60066035
"re_log_types",
60076036
"re_smart_channel",
60086037
"re_tracing",
6038+
"tokio",
6039+
"wasm-bindgen-futures",
60096040
]
60106041

60116042
[[package]]
@@ -6169,7 +6200,6 @@ dependencies = [
61696200
"re_protos",
61706201
"re_smart_channel",
61716202
"re_sorbet",
6172-
"re_types",
61736203
"thiserror 1.0.65",
61746204
"tokio",
61756205
"tokio-stream",
@@ -6889,6 +6919,7 @@ dependencies = [
68896919
"re_log",
68906920
"re_log_types",
68916921
"re_renderer",
6922+
"re_sorbet",
68926923
"re_tracing",
68936924
"re_types",
68946925
"re_types_core",
@@ -7101,6 +7132,7 @@ dependencies = [
71017132
"re_build_info",
71027133
"re_build_tools",
71037134
"re_capabilities",
7135+
"re_catalog_hub",
71047136
"re_chunk",
71057137
"re_chunk_store",
71067138
"re_chunk_store_ui",
@@ -7207,6 +7239,7 @@ dependencies = [
72077239
"smallvec",
72087240
"strum_macros",
72097241
"thiserror 1.0.65",
7242+
"tokio",
72107243
"uuid",
72117244
"wasm-bindgen-futures",
72127245
"web-sys",

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ re_video = { path = "crates/utils/re_video", version = "=0.23.0-alpha.1", defaul
9191

9292
# crates/viewer:
9393
re_blueprint_tree = { path = "crates/viewer/re_blueprint_tree", version = "=0.23.0-alpha.1", default-features = false }
94+
re_catalog_hub = { path = "crates/viewer/re_catalog_hub", version = "=0.23.0-alpha.1", default-features = false }
9495
re_component_ui = { path = "crates/viewer/re_component_ui", version = "=0.23.0-alpha.1", default-features = false }
9596
re_context_menu = { path = "crates/viewer/re_context_menu", version = "=0.23.0-alpha.1", default-features = false }
9697
re_chunk_store_ui = { path = "crates/viewer/re_chunk_store_ui", version = "=0.23.0-alpha.1", default-features = false }

bacon.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,4 @@ c = "job:clippy"
8686
d = "job:doc-open"
8787
t = "job:test"
8888
r = "job:run"
89+
a = "job:wasm"

crates/store/re_data_source/Cargo.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ grpc = ["re_grpc_client/redap"]
2828

2929
[dependencies]
3030
re_data_loader.workspace = true
31+
re_error.workspace = true
3132
re_grpc_client.workspace = true
3233
re_log_encoding = { workspace = true, features = [
3334
"decoder",
@@ -42,7 +43,13 @@ anyhow.workspace = true
4243
itertools.workspace = true
4344
rayon.workspace = true
4445

45-
# Optional dependencies:
46+
# native dependencies:
47+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
48+
tokio.workspace = true
49+
50+
# web dependencies:
51+
[target.'cfg(target_arch = "wasm32")'.dependencies]
52+
wasm-bindgen-futures.workspace = true
4653

4754
[build-dependencies]
4855
re_build_tools.workspace = true

crates/store/re_data_source/src/data_source.rs

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ pub enum DataSource {
3737
MessageProxy { url: String },
3838
}
3939

40+
// TODO(#9058): Temporary hack, see issue for how to fix this.
41+
pub enum StreamSource {
42+
LogMessages(Receiver<LogMsg>),
43+
CatalogData {
44+
origin: re_grpc_client::redap::Origin,
45+
},
46+
}
47+
4048
impl DataSource {
4149
/// Tried to classify a URI into a [`DataSource`].
4250
///
@@ -156,14 +164,15 @@ impl DataSource {
156164
pub fn stream(
157165
self,
158166
on_msg: Option<Box<dyn Fn() + Send + Sync>>,
159-
) -> anyhow::Result<Receiver<LogMsg>> {
167+
) -> anyhow::Result<StreamSource> {
160168
re_tracing::profile_function!();
169+
161170
match self {
162-
Self::RrdHttpUrl { url, follow } => Ok(
171+
Self::RrdHttpUrl { url, follow } => Ok(StreamSource::LogMessages(
163172
re_log_encoding::stream_rrd_from_http::stream_rrd_from_http_to_channel(
164173
url, follow, on_msg,
165174
),
166-
),
175+
)),
167176

168177
#[cfg(not(target_arch = "wasm32"))]
169178
Self::FilePath(file_source, path) => {
@@ -190,7 +199,7 @@ impl DataSource {
190199
on_msg();
191200
}
192201

193-
Ok(rx)
202+
Ok(StreamSource::LogMessages(rx))
194203
}
195204

196205
// When loading a file on Web, or when using drag-n-drop.
@@ -224,7 +233,7 @@ impl DataSource {
224233
on_msg();
225234
}
226235

227-
Ok(rx)
236+
Ok(StreamSource::LogMessages(rx))
228237
}
229238

230239
#[cfg(not(target_arch = "wasm32"))]
@@ -240,17 +249,54 @@ impl DataSource {
240249
on_msg();
241250
}
242251

243-
Ok(rx)
252+
Ok(StreamSource::LogMessages(rx))
244253
}
245254

246255
#[cfg(feature = "grpc")]
247256
Self::RerunGrpcUrl { url } => {
248-
re_grpc_client::redap::stream_from_redap(url, on_msg).map_err(|err| err.into())
257+
use re_grpc_client::redap::RedapAddress;
258+
259+
re_log::debug!("Loading {url}…");
260+
261+
let address = url.as_str().try_into()?;
262+
263+
match address {
264+
RedapAddress::Recording {
265+
origin,
266+
recording_id,
267+
} => {
268+
let (tx, rx) = re_smart_channel::smart_channel(
269+
re_smart_channel::SmartMessageSource::RerunGrpcStream {
270+
url: url.clone(),
271+
},
272+
re_smart_channel::SmartChannelSource::RerunGrpcStream {
273+
url: url.clone(),
274+
},
275+
);
276+
spawn_future(async move {
277+
if let Err(err) = re_grpc_client::redap::stream_recording_async(
278+
tx,
279+
origin,
280+
recording_id,
281+
on_msg,
282+
)
283+
.await
284+
{
285+
re_log::warn!(
286+
"Error while streaming {url}: {}",
287+
re_error::format_ref(&err)
288+
);
289+
}
290+
});
291+
Ok(StreamSource::LogMessages(rx))
292+
}
293+
RedapAddress::Catalog { origin } => Ok(StreamSource::CatalogData { origin }),
294+
}
249295
}
250296

251-
Self::MessageProxy { url } => {
252-
re_grpc_client::message_proxy::stream(&url, on_msg).map_err(|err| err.into())
253-
}
297+
Self::MessageProxy { url } => re_grpc_client::message_proxy::stream(&url, on_msg)
298+
.map_err(|err| err.into())
299+
.map(StreamSource::LogMessages),
254300
}
255301
}
256302
}
@@ -319,3 +365,25 @@ fn test_data_source_from_uri() {
319365

320366
assert!(!failed, "one or more test cases failed");
321367
}
368+
369+
// TODO(ab, andreas): This should be replaced by the use of `AsyncRuntimeHandle`. However, this
370+
// requires:
371+
// - `AsyncRuntimeHandle` to be moved lower in the crate hierarchy to be available here (unsure
372+
// where).
373+
// - Make sure that all callers of `DataSource::stream` have access to an `AsyncRuntimeHandle`
374+
// (maybe it should be in `GlobalContext`?).
375+
#[cfg(target_arch = "wasm32")]
376+
fn spawn_future<F>(future: F)
377+
where
378+
F: std::future::Future<Output = ()> + 'static,
379+
{
380+
wasm_bindgen_futures::spawn_local(future);
381+
}
382+
383+
#[cfg(not(target_arch = "wasm32"))]
384+
fn spawn_future<F>(future: F)
385+
where
386+
F: std::future::Future<Output = ()> + 'static + Send,
387+
{
388+
tokio::spawn(future);
389+
}

crates/store/re_data_source/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ mod data_source;
1111
#[cfg(not(target_arch = "wasm32"))]
1212
mod load_stdin;
1313

14-
pub use self::data_source::DataSource;
14+
pub use self::data_source::{DataSource, StreamSource};
1515

1616
// ----------------------------------------------------------------------------
1717

crates/store/re_grpc_client/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ re_log_types.workspace = true
3434
re_protos.workspace = true
3535
re_smart_channel.workspace = true
3636
re_sorbet.workspace = true
37-
re_types.workspace = true
3837

3938
arrow.workspace = true
4039
async-stream.workspace = true

crates/store/re_grpc_client/src/redap/address.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,14 @@ pub enum ConnectionError {
3232
#[error("unexpected base URL: {0}")]
3333
UnexpectedBaseUrl(String),
3434

35-
/// The given url is not a valid Rerun storage node URL.
36-
#[error("URL {url:?} should follow rerun://host:port/recording/12345 for recording or rerun://host:port/catalog for catalog")]
37-
InvalidAddress { url: String, msg: String },
35+
#[error("URL {url:?} cannot be loaded as a recording")]
36+
CannotLoadUrlAsRecording { url: String },
3837
}
3938

4039
/// The different schemes supported by Rerun.
4140
///
4241
/// We support `rerun`, `rerun+http`, and `rerun+https`.
43-
#[derive(Debug, PartialEq, Eq)]
42+
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
4443
pub enum Scheme {
4544
Rerun,
4645
RerunHttp,
@@ -59,15 +58,15 @@ impl std::fmt::Display for Scheme {
5958

6059
impl Scheme {
6160
/// Converts a [`Scheme`] to either `http` or `https`.
62-
fn to_http_scheme(&self) -> &str {
61+
fn as_http_scheme(&self) -> &str {
6362
match self {
6463
Self::Rerun | Self::RerunHttps => "https",
6564
Self::RerunHttp => "http",
6665
}
6766
}
6867
}
6968

70-
#[derive(Debug, PartialEq, Eq)]
69+
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
7170
pub struct Origin {
7271
scheme: Scheme,
7372
host: url::Host<String>,
@@ -82,7 +81,7 @@ impl Origin {
8281
fn to_http_scheme(&self) -> String {
8382
format!(
8483
"{}://{}:{}",
85-
self.scheme.to_http_scheme(),
84+
self.scheme.as_http_scheme(),
8685
self.host,
8786
self.port
8887
)
@@ -242,9 +241,9 @@ mod tests {
242241

243242
#[test]
244243
fn scheme_conversion() {
245-
assert_eq!(Scheme::Rerun.to_http_scheme(), "https");
246-
assert_eq!(Scheme::RerunHttp.to_http_scheme(), "http");
247-
assert_eq!(Scheme::RerunHttps.to_http_scheme(), "https");
244+
assert_eq!(Scheme::Rerun.as_http_scheme(), "https");
245+
assert_eq!(Scheme::RerunHttp.as_http_scheme(), "http");
246+
assert_eq!(Scheme::RerunHttps.as_http_scheme(), "https");
248247
}
249248

250249
#[test]

0 commit comments

Comments
 (0)