From b16090342b282fc11f70d6ec07ce63f292de3453 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 24 Apr 2024 12:50:28 +0200 Subject: [PATCH 1/9] re_query_cache replaces re_query2 --- ARCHITECTURE.md | 2 +- Cargo.lock | 53 +- Cargo.toml | 1 - crates/re_data_ui/src/component.rs | 2 +- .../re_data_ui/src/component_ui_registry.rs | 2 +- crates/re_data_ui/src/editors.rs | 2 +- crates/re_entity_db/Cargo.toml | 2 +- crates/re_entity_db/src/entity_db.rs | 28 +- crates/re_entity_db/src/lib.rs | 4 +- crates/re_query2/Cargo.toml | 44 +- crates/re_query2/README.md | 9 +- .../benches/flat_vec_deque.rs | 2 +- crates/re_query2/benches/latest_at.rs | 185 +-- crates/re_query2/examples/latest_at.rs | 43 +- .../examples/latest_at_archetype.rs | 6 +- crates/re_query2/examples/range.rs | 111 +- crates/re_query2/src/bin/clamped_zip.rs | 2 +- crates/re_query2/src/bin/range_zip.rs | 2 +- .../src/cache.rs | 0 .../src/cache_stats.rs | 0 crates/re_query2/src/clamped_zip/generated.rs | 2 +- .../src/flat_vec_deque.rs | 0 .../src/latest_at/helpers.rs | 0 crates/re_query2/src/latest_at/mod.rs | 9 +- crates/re_query2/src/latest_at/query.rs | 329 ++++- crates/re_query2/src/latest_at/results.rs | 263 ++-- .../src/latest_at/to_archetype/.gitattributes | 0 .../to_archetype/annotation_context.rs | 2 +- .../src/latest_at/to_archetype/arrows2d.rs | 2 +- .../src/latest_at/to_archetype/arrows3d.rs | 2 +- .../src/latest_at/to_archetype/asset3d.rs | 2 +- .../src/latest_at/to_archetype/bar_chart.rs | 2 +- .../src/latest_at/to_archetype/boxes2d.rs | 2 +- .../src/latest_at/to_archetype/boxes3d.rs | 2 +- .../src/latest_at/to_archetype/clear.rs | 2 +- .../to_archetype/container_blueprint.rs | 2 +- .../src/latest_at/to_archetype/depth_image.rs | 2 +- .../to_archetype/disconnected_space.rs | 2 +- .../src/latest_at/to_archetype/image.rs | 2 +- .../latest_at/to_archetype/line_strips2d.rs | 2 +- .../latest_at/to_archetype/line_strips3d.rs | 2 +- .../src/latest_at/to_archetype/mesh3d.rs | 2 +- .../src/latest_at/to_archetype/mod.rs | 0 .../latest_at/to_archetype/panel_blueprint.rs | 2 +- .../src/latest_at/to_archetype/pinhole.rs | 2 +- .../src/latest_at/to_archetype/plot_legend.rs | 2 +- .../src/latest_at/to_archetype/points2d.rs | 2 +- .../src/latest_at/to_archetype/points3d.rs | 2 +- .../src/latest_at/to_archetype/scalar.rs | 2 +- .../src/latest_at/to_archetype/scalar_axis.rs | 2 +- .../to_archetype/segmentation_image.rs | 2 +- .../src/latest_at/to_archetype/series_line.rs | 2 +- .../latest_at/to_archetype/series_point.rs | 2 +- .../to_archetype/space_view_blueprint.rs | 2 +- .../to_archetype/space_view_contents.rs | 2 +- .../src/latest_at/to_archetype/tensor.rs | 2 +- .../latest_at/to_archetype/text_document.rs | 2 +- .../src/latest_at/to_archetype/text_log.rs | 2 +- .../src/latest_at/to_archetype/transform3d.rs | 2 +- .../to_archetype/view_coordinates.rs | 2 +- .../to_archetype/viewport_blueprint.rs | 2 +- crates/re_query2/src/lib.rs | 46 +- crates/re_query2/src/range/mod.rs | 7 +- crates/re_query2/src/range/query.rs | 407 ++++++- crates/re_query2/src/range/results.rs | 829 +++++++++++-- crates/re_query2/src/range_zip/generated.rs | 2 +- crates/re_query2/tests/latest_at.rs | 737 ++++++++---- crates/re_query2/tests/range.rs | 1064 +++++++++-------- crates/re_query_cache/Cargo.toml | 81 -- crates/re_query_cache/README.md | 10 - crates/re_query_cache/benches/latest_at.rs | 374 ------ crates/re_query_cache/examples/latest_at.rs | 133 --- crates/re_query_cache/examples/range.rs | 151 --- crates/re_query_cache/src/latest_at/mod.rs | 10 - crates/re_query_cache/src/latest_at/query.rs | 315 ----- .../re_query_cache/src/latest_at/results.rs | 299 ----- .../src/latest_at/to_archetype/background.rs | 66 - crates/re_query_cache/src/lib.rs | 54 - crates/re_query_cache/src/range/mod.rs | 8 - crates/re_query_cache/src/range/query.rs | 393 ------ crates/re_query_cache/src/range/results.rs | 819 ------------- crates/re_query_cache/tests/latest_at.rs | 526 -------- crates/re_query_cache/tests/range.rs | 586 --------- crates/re_space_view/Cargo.toml | 2 +- crates/re_space_view/src/space_view.rs | 2 +- .../re_space_view/src/space_view_contents.rs | 2 +- crates/re_space_view/src/sub_archetypes.rs | 2 +- crates/re_space_view/src/visual_time_range.rs | 2 +- crates/re_space_view_dataframe/Cargo.toml | 2 +- crates/re_space_view_spatial/Cargo.toml | 2 +- .../src/visualizers/arrows2d.rs | 2 +- .../src/visualizers/arrows3d.rs | 2 +- .../src/visualizers/assets3d.rs | 2 +- .../src/visualizers/boxes2d.rs | 2 +- .../src/visualizers/boxes3d.rs | 2 +- .../src/visualizers/entity_iterator.rs | 2 +- .../src/visualizers/images.rs | 2 +- .../src/visualizers/lines2d.rs | 2 +- .../src/visualizers/lines3d.rs | 2 +- .../src/visualizers/meshes.rs | 2 +- .../src/visualizers/points2d.rs | 2 +- .../src/visualizers/points3d.rs | 2 +- .../src/visualizers/results_ext.rs | 34 +- .../src/visualizer_system.rs | 2 +- .../src/visualizer_system.rs | 2 +- crates/re_space_view_text_log/Cargo.toml | 2 +- .../src/visualizer_system.rs | 8 +- crates/re_space_view_time_series/Cargo.toml | 2 +- .../src/line_visualizer_system.rs | 6 +- .../src/point_visualizer_system.rs | 8 +- .../src/codegen/rust/to_archetype.rs | 6 +- crates/re_viewer/Cargo.toml | 2 +- crates/re_viewer/src/lib.rs | 2 +- crates/re_viewer/src/ui/memory_panel.rs | 2 +- crates/re_viewer_context/Cargo.toml | 2 +- .../src/component_ui_registry.rs | 2 +- crates/re_viewer_context/src/item.rs | 2 +- .../re_viewer_context/src/space_view/mod.rs | 2 +- crates/re_viewer_context/src/store_hub.rs | 2 +- crates/re_viewport/src/container.rs | 2 +- crates/re_viewport/src/viewport_blueprint.rs | 2 +- .../color_coordinates_visualizer_system.rs | 6 +- 122 files changed, 3086 insertions(+), 5134 deletions(-) rename crates/{re_query_cache => re_query2}/benches/flat_vec_deque.rs (99%) rename crates/{re_query_cache => re_query2}/examples/latest_at_archetype.rs (94%) rename crates/{re_query_cache => re_query2}/src/cache.rs (100%) rename crates/{re_query_cache => re_query2}/src/cache_stats.rs (100%) rename crates/{re_query_cache => re_query2}/src/flat_vec_deque.rs (100%) rename crates/{re_query_cache => re_query2}/src/latest_at/helpers.rs (100%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/.gitattributes (100%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/annotation_context.rs (97%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/arrows2d.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/arrows3d.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/asset3d.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/bar_chart.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/boxes2d.rs (99%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/boxes3d.rs (99%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/clear.rs (97%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/container_blueprint.rs (99%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/depth_image.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/disconnected_space.rs (97%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/image.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/line_strips2d.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/line_strips3d.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/mesh3d.rs (99%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/mod.rs (100%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/panel_blueprint.rs (97%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/pinhole.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/plot_legend.rs (97%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/points2d.rs (99%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/points3d.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/scalar.rs (97%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/scalar_axis.rs (97%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/segmentation_image.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/series_line.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/series_point.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/space_view_blueprint.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/space_view_contents.rs (96%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/tensor.rs (97%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/text_document.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/text_log.rs (98%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/transform3d.rs (97%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/view_coordinates.rs (97%) rename crates/{re_query_cache => re_query2}/src/latest_at/to_archetype/viewport_blueprint.rs (98%) delete mode 100644 crates/re_query_cache/Cargo.toml delete mode 100644 crates/re_query_cache/README.md delete mode 100644 crates/re_query_cache/benches/latest_at.rs delete mode 100644 crates/re_query_cache/examples/latest_at.rs delete mode 100644 crates/re_query_cache/examples/range.rs delete mode 100644 crates/re_query_cache/src/latest_at/mod.rs delete mode 100644 crates/re_query_cache/src/latest_at/query.rs delete mode 100644 crates/re_query_cache/src/latest_at/results.rs delete mode 100644 crates/re_query_cache/src/latest_at/to_archetype/background.rs delete mode 100644 crates/re_query_cache/src/lib.rs delete mode 100644 crates/re_query_cache/src/range/mod.rs delete mode 100644 crates/re_query_cache/src/range/query.rs delete mode 100644 crates/re_query_cache/src/range/results.rs delete mode 100644 crates/re_query_cache/tests/latest_at.rs delete mode 100644 crates/re_query_cache/tests/range.rs diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 0bc22487db3f..0c23e5f22566 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -149,7 +149,7 @@ Update instructions: |----------------------|--------------------------------------------------------------------------| | re_entity_db | In-memory storage of Rerun entities | | re_query | Querying data in the re_data_store | -| re_query_cache | Caching datastructures for re_query | +| re_query2 | Caching datastructures for re_query | | re_types | The built-in Rerun data types, component types, and archetypes. | | re_types_blueprint | The core traits and types that power Rerun's Blueprint sub-system. | | re_log_encoding | Helpers for encoding and transporting Rerun log messages | diff --git a/Cargo.lock b/Cargo.lock index b5a8526152b7..f3a0b2e65728 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4309,7 +4309,7 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_query", - "re_query_cache", + "re_query2", "re_smart_channel", "re_tracing", "re_types", @@ -4483,37 +4483,6 @@ dependencies = [ [[package]] name = "re_query2" version = "0.16.0-alpha.2" -dependencies = [ - "ahash", - "anyhow", - "backtrace", - "criterion", - "document-features", - "itertools 0.12.0", - "mimalloc", - "nohash-hasher", - "rand", - "re_arrow2", - "re_data_store", - "re_format", - "re_format_arrow", - "re_log", - "re_log_types", - "re_tracing", - "re_tuid", - "re_types", - "re_types_core", - "serde", - "similar-asserts", - "smallvec", - "static_assertions", - "thiserror", - "unindent", -] - -[[package]] -name = "re_query_cache" -version = "0.16.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -4527,18 +4496,22 @@ dependencies = [ "parking_lot", "paste", "rand", + "re_arrow2", "re_data_store", "re_error", "re_format", "re_log", "re_log_types", - "re_query2", "re_tracing", + "re_tuid", "re_types", "re_types_blueprint", "re_types_core", "seq-macro", "similar-asserts", + "static_assertions", + "thiserror", + "unindent", "web-time", ] @@ -4683,7 +4656,7 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", + "re_query2", "re_tracing", "re_types", "re_types_core", @@ -4721,7 +4694,7 @@ dependencies = [ "re_entity_db", "re_log_types", "re_query", - "re_query_cache", + "re_query2", "re_renderer", "re_tracing", "re_types_core", @@ -4754,7 +4727,7 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", + "re_query2", "re_renderer", "re_space_view", "re_tracing", @@ -4822,7 +4795,7 @@ dependencies = [ "re_entity_db", "re_log", "re_log_types", - "re_query_cache", + "re_query2", "re_renderer", "re_tracing", "re_types", @@ -4843,7 +4816,7 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", + "re_query2", "re_renderer", "re_space_view", "re_tracing", @@ -5059,7 +5032,7 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_memory", - "re_query_cache", + "re_query2", "re_renderer", "re_smart_channel", "re_space_view", @@ -5119,7 +5092,7 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", + "re_query2", "re_renderer", "re_smart_channel", "re_string_interner", diff --git a/Cargo.toml b/Cargo.toml index d391fc4bcab3..47f2d1dff06e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,6 @@ re_log_encoding = { path = "crates/re_log_encoding", version = "=0.16.0-alpha.2" re_log_types = { path = "crates/re_log_types", version = "=0.16.0-alpha.2", default-features = false } re_memory = { path = "crates/re_memory", version = "=0.16.0-alpha.2", default-features = false } re_query = { path = "crates/re_query", version = "=0.16.0-alpha.2", default-features = false } -re_query_cache = { path = "crates/re_query_cache", version = "=0.16.0-alpha.2", default-features = false } re_query2 = { path = "crates/re_query2", version = "=0.16.0-alpha.2", default-features = false } re_renderer = { path = "crates/re_renderer", version = "=0.16.0-alpha.2", default-features = false } re_sdk = { path = "crates/re_sdk", version = "=0.16.0-alpha.2", default-features = false } diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index 6c6e9a2fa4c6..09498e200955 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use egui::NumExt; use re_entity_db::{ - external::re_query_cache::CachedLatestAtComponentResults, EntityPath, InstancePath, + external::re_query2::CachedLatestAtComponentResults, EntityPath, InstancePath, }; use re_types::ComponentName; use re_ui::SyntaxHighlighting as _; diff --git a/crates/re_data_ui/src/component_ui_registry.rs b/crates/re_data_ui/src/component_ui_registry.rs index 98e4afbf148d..0c81db82a40d 100644 --- a/crates/re_data_ui/src/component_ui_registry.rs +++ b/crates/re_data_ui/src/component_ui_registry.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query2::CachedLatestAtComponentResults, EntityDb}; use re_log_types::{external::arrow2, EntityPath}; use re_types::external::arrow2::array::Utf8Array; use re_viewer_context::{ComponentUiRegistry, UiVerbosity, ViewerContext}; diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index 61b96d4eade1..4b05b89381c4 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -2,7 +2,7 @@ use egui::NumExt as _; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query2::CachedLatestAtComponentResults, EntityDb}; use re_log_types::EntityPath; use re_types::{ components::{ diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index db210bcf7b48..2bf8bed8d33e 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -34,7 +34,7 @@ re_log.workspace = true re_log_encoding = { workspace = true, features = ["decoder"] } re_log_types.workspace = true re_query.workspace = true -re_query_cache = { workspace = true, features = ["to_archetype"] } +re_query2 = { workspace = true, features = ["to_archetype"] } re_smart_channel.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index 4d618e81a71a..f77dd7ad1e32 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -12,7 +12,7 @@ use re_log_types::{ EntityPathHash, LogMsg, RowId, SetStoreInfo, StoreId, StoreInfo, StoreKind, TimePoint, TimeRange, TimeRangeF, Timeline, }; -use re_query_cache::PromiseResult; +use re_query2::PromiseResult; use re_types_core::{components::InstanceKey, Archetype, Loggable}; use crate::{ClearCascade, CompactedStoreEvents, Error, TimesPerTimeline}; @@ -117,10 +117,10 @@ pub struct EntityDb { data_store: DataStore, /// The active promise resolver for this DB. - resolver: re_query_cache::PromiseResolver, + resolver: re_query2::PromiseResolver, /// Query caches for the data in [`Self::data_store`]. - query_caches: re_query_cache::Caches, + query_caches: re_query2::Caches, stats: IngestionStatistics, } @@ -132,7 +132,7 @@ impl EntityDb { InstanceKey::name(), DataStoreConfig::default(), ); - let query_caches = re_query_cache::Caches::new(&data_store); + let query_caches = re_query2::Caches::new(&data_store); Self { data_source: None, set_store_info: None, @@ -142,7 +142,7 @@ impl EntityDb { times_per_timeline: Default::default(), tree: crate::EntityTree::root(), data_store, - resolver: re_query_cache::PromiseResolver::default(), + resolver: re_query2::PromiseResolver::default(), query_caches, stats: IngestionStatistics::new(store_id), } @@ -192,12 +192,12 @@ impl EntityDb { } #[inline] - pub fn query_caches(&self) -> &re_query_cache::Caches { + pub fn query_caches(&self) -> &re_query2::Caches { &self.query_caches } #[inline] - pub fn resolver(&self) -> &re_query_cache::PromiseResolver { + pub fn resolver(&self) -> &re_query2::PromiseResolver { &self.resolver } @@ -209,7 +209,7 @@ impl EntityDb { query: &re_data_store::LatestAtQuery, ) -> PromiseResult> where - re_query_cache::CachedLatestAtResults: re_query_cache::ToArchetype, + re_query2::CachedLatestAtResults: re_query2::ToArchetype, { let results = self.query_caches().latest_at( self.store(), @@ -218,12 +218,12 @@ impl EntityDb { A::all_components().iter().copied(), // no generics! ); - use re_query_cache::ToArchetype as _; + use re_query2::ToArchetype as _; match results.to_archetype(self.resolver()).flatten() { PromiseResult::Pending => PromiseResult::Pending, PromiseResult::Error(err) => { - if let Some(err) = err.downcast_ref::() { - if matches!(err, re_query_cache::QueryError::PrimaryNotFound(_)) { + if let Some(err) = err.downcast_ref::() { + if matches!(err, re_query2::QueryError::PrimaryNotFound(_)) { return PromiseResult::Ready(None); } } @@ -240,7 +240,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { + ) -> Option> { self.query_caches().latest_at_component::( self.store(), self.resolver(), @@ -254,7 +254,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { + ) -> Option> { self.query_caches().latest_at_component_quiet::( self.store(), self.resolver(), @@ -268,7 +268,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option<(EntityPath, re_query_cache::CachedLatestAtMonoResult)> { + ) -> Option<(EntityPath, re_query2::CachedLatestAtMonoResult)> { self.query_caches() .latest_at_component_at_closest_ancestor::( self.store(), diff --git a/crates/re_entity_db/src/lib.rs b/crates/re_entity_db/src/lib.rs index e431475ea747..c403a71de340 100644 --- a/crates/re_entity_db/src/lib.rs +++ b/crates/re_entity_db/src/lib.rs @@ -34,7 +34,7 @@ pub(crate) use self::entity_tree::{ClearCascade, CompactedStoreEvents}; use re_log_types::DataTableError; pub use re_log_types::{EntityPath, EntityPathPart, TimeInt, Timeline}; -pub use re_query_cache::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +pub use re_query2::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; #[cfg(feature = "serde")] pub use blueprint::components::EntityPropertiesComponent; @@ -43,7 +43,7 @@ pub use editable_auto_value::EditableAutoValue; pub mod external { pub use re_data_store; - pub use re_query_cache; + pub use re_query2; } // ---------------------------------------------------------------------------- diff --git a/crates/re_query2/Cargo.toml b/crates/re_query2/Cargo.toml index 6953d372cd15..6ad863379d29 100644 --- a/crates/re_query2/Cargo.toml +++ b/crates/re_query2/Cargo.toml @@ -1,13 +1,12 @@ [package] name = "re_query2" authors.workspace = true -description = "Temporary crate meant to replace re_query" +description = "High-level query APIs" edition.workspace = true homepage.workspace = true include.workspace = true license.workspace = true -# TODO(cmc): Replace re_query with this crate. Never publish this one. -publish = false +publish = true readme = "README.md" repository.workspace = true rust-version.workspace = true @@ -21,10 +20,10 @@ all-features = true [features] -default = [] +default = ["to_archetype"] -## Enable (de)serialization using serde. -serde = ["dep:serde"] +## Implements `ToArchetype` for all builtin archetypes on `CachedLatestAtResults`. +to_archetype = ["dep:re_types", "dep:re_types_blueprint"] ## Enable codegen helper binaries (generates ClampedZip & RangeZip implementations). codegen = ["unindent"] @@ -33,28 +32,35 @@ codegen = ["unindent"] [dependencies] # Rerun dependencies: re_data_store.workspace = true +re_error.workspace = true re_format.workspace = true -re_format_arrow.workspace = true -re_log_types.workspace = true -re_types_core.workspace = true re_log.workspace = true +re_log_types.workspace = true re_tracing.workspace = true re_tuid.workspace = true +re_types_core.workspace = true + +# Rerun dependencies (optional): +re_types = { workspace = true, optional = true } +re_types_blueprint = { workspace = true, optional = true } # External dependencies: ahash.workspace = true anyhow.workspace = true arrow2.workspace = true backtrace.workspace = true -document-features.workspace = true -itertools = { workspace = true } +indent.workspace = true +indexmap.workspace = true +itertools.workspace = true nohash-hasher.workspace = true -serde = { workspace = true, features = ["derive", "rc"], optional = true } -smallvec.workspace = true +parking_lot.workspace = true +paste.workspace = true +seq-macro.workspace = true static_assertions.workspace = true thiserror.workspace = true +web-time.workspace = true -# Optional: +# External dependencies (optional): unindent = { workspace = true, optional = true } @@ -62,7 +68,6 @@ unindent = { workspace = true, optional = true } re_types = { workspace = true, features = ["datagen"] } criterion.workspace = true -itertools = { workspace = true } mimalloc.workspace = true rand = { workspace = true, features = ["std", "std_rng"] } similar-asserts.workspace = true @@ -72,6 +77,11 @@ similar-asserts.workspace = true bench = false +[[example]] +name = "latest_at_archetype" +required-features = ["to_archetype"] + + [[bin]] name = "clamped_zip" required-features = ["codegen"] @@ -82,6 +92,10 @@ name = "range_zip" required-features = ["codegen"] +[[bench]] +name = "flat_vec_deque" +harness = false + [[bench]] name = "latest_at" harness = false diff --git a/crates/re_query2/README.md b/crates/re_query2/README.md index 42bcc981d336..2928fb493f1f 100644 --- a/crates/re_query2/README.md +++ b/crates/re_query2/README.md @@ -1,5 +1,10 @@ # re_query2 -Temporary crate for implementing the new data APIs. Not published. +Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -Will replace `re_query` when ready. +[![Latest version](https://img.shields.io/crates/v/re_query2.svg)](https://crates.io/crates/re_query2) +[![Documentation](https://docs.rs/re_query/badge.svg)](https://docs.rs/re_query) +![MIT](https://img.shields.io/badge/license-MIT-blue.svg) +![Apache](https://img.shields.io/badge/license-Apache-blue.svg) + +High-level query APIs. diff --git a/crates/re_query_cache/benches/flat_vec_deque.rs b/crates/re_query2/benches/flat_vec_deque.rs similarity index 99% rename from crates/re_query_cache/benches/flat_vec_deque.rs rename to crates/re_query2/benches/flat_vec_deque.rs index d12e10293c0e..a435d40d64ae 100644 --- a/crates/re_query_cache/benches/flat_vec_deque.rs +++ b/crates/re_query2/benches/flat_vec_deque.rs @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use itertools::Itertools as _; -use re_query_cache::FlatVecDeque; +use re_query2::FlatVecDeque; // --- diff --git a/crates/re_query2/benches/latest_at.rs b/crates/re_query2/benches/latest_at.rs index 28b9cf14f94e..a724c2e1e301 100644 --- a/crates/re_query2/benches/latest_at.rs +++ b/crates/re_query2/benches/latest_at.rs @@ -1,12 +1,13 @@ -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +//! Contains: +//! - A 1:1 port of the benchmarks in `crates/re_query/benches/query_benchmarks.rs`, with caching enabled. use criterion::{criterion_group, criterion_main, Criterion}; use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; +use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query2::{clamped_zip_1x1, LatestAtResults, PromiseResolver}; +use re_query2::{clamped_zip_1x1, PromiseResolver}; +use re_query2::{CachedLatestAtResults, Caches}; use re_types::{ archetypes::Points2D, components::{Color, InstanceKey, Position2D, Text}, @@ -16,24 +17,30 @@ use re_types_core::Loggable as _; // --- -#[cfg(not(debug_assertions))] -const NUM_FRAMES_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_FRAMES_STRINGS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_STRINGS: u32 = 1_000; - // `cargo test` also runs the benchmark setup code, so make sure they run quickly: #[cfg(debug_assertions)] -const NUM_FRAMES_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_FRAMES_STRINGS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_STRINGS: u32 = 1; +mod constants { + pub const NUM_FRAMES_POINTS: u32 = 1; + pub const NUM_POINTS: u32 = 1; + pub const NUM_FRAMES_STRINGS: u32 = 1; + pub const NUM_STRINGS: u32 = 1; +} + +#[cfg(not(debug_assertions))] +mod constants { + pub const NUM_FRAMES_POINTS: u32 = 1_000; + pub const NUM_POINTS: u32 = 1_000; + pub const NUM_FRAMES_STRINGS: u32 = 1_000; + pub const NUM_STRINGS: u32 = 1_000; +} + +#[allow(clippy::wildcard_imports)] +use self::constants::*; + +// --- + +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; criterion_group!( benches, @@ -44,48 +51,12 @@ criterion_group!( ); criterion_main!(benches); -// --- Benchmarks --- - -pub fn build_some_point2d(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) - .collect() -} - -/// Create `len` dummy colors -pub fn build_some_colors(len: usize) -> Vec { - (0..len).map(|i| Color::from(i as u32)).collect() -} - -/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. -pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { - (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) -} - -pub fn build_some_strings(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| { - let ilen: usize = rng.gen_range(0..10000); - let s: String = rand::thread_rng() - .sample_iter(&rand::distributions::Alphanumeric) - .take(ilen) - .map(char::from) - .collect(); - Text::from(s) - }) - .collect() -} +// --- fn mono_points(c: &mut Criterion) { // Each mono point gets logged at a different path let paths = (0..NUM_POINTS) - .map(move |point_idx| entity_path!("points", point_idx.to_string())) + .map(move |point_idx| entity_path!("points", point_idx)) .collect_vec(); let msgs = build_points_rows(&paths, 1); @@ -104,9 +75,9 @@ fn mono_points(c: &mut Criterion) { { let mut group = c.benchmark_group("arrow_mono_points2"); group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); + let (caches, store) = insert_rows(msgs.iter()); group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); + b.iter(|| query_and_visit_points(&caches, &store, &paths)); }); } } @@ -114,7 +85,7 @@ fn mono_points(c: &mut Criterion) { fn mono_strings(c: &mut Criterion) { // Each mono string gets logged at a different path let paths = (0..NUM_STRINGS) - .map(move |string_idx| entity_path!("strings", string_idx.to_string())) + .map(move |string_idx| entity_path!("strings", string_idx)) .collect_vec(); let msgs = build_strings_rows(&paths, 1); @@ -132,9 +103,9 @@ fn mono_strings(c: &mut Criterion) { { let mut group = c.benchmark_group("arrow_mono_strings2"); group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); + let (caches, store) = insert_rows(msgs.iter()); group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); + b.iter(|| query_and_visit_strings(&caches, &store, &paths)); }); } } @@ -157,9 +128,9 @@ fn batch_points(c: &mut Criterion) { { let mut group = c.benchmark_group("arrow_batch_points2"); group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); + let (caches, store) = insert_rows(msgs.iter()); group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); + b.iter(|| query_and_visit_points(&caches, &store, &paths)); }); } } @@ -182,15 +153,51 @@ fn batch_strings(c: &mut Criterion) { { let mut group = c.benchmark_group("arrow_batch_strings2"); group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); + let (caches, store) = insert_rows(msgs.iter()); group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); + b.iter(|| query_and_visit_strings(&caches, &store, &paths)); }); } } // --- Helpers --- +pub fn build_some_point2d(len: usize) -> Vec { + use rand::Rng as _; + let mut rng = rand::thread_rng(); + + (0..len) + .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) + .collect() +} + +/// Create `len` dummy colors +pub fn build_some_colors(len: usize) -> Vec { + (0..len).map(|i| Color::from(i as u32)).collect() +} + +/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. +pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { + (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) +} + +pub fn build_some_strings(len: usize) -> Vec { + use rand::Rng as _; + let mut rng = rand::thread_rng(); + + (0..len) + .map(|_| { + let ilen: usize = rng.gen_range(0..10000); + let s: String = rand::thread_rng() + .sample_iter(&rand::distributions::Alphanumeric) + .take(ilen) + .map(char::from) + .collect(); + Text::from(s) + }) + .collect() +} + fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { (0..NUM_FRAMES_POINTS) .flat_map(move |frame_idx| { @@ -248,16 +255,19 @@ fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec .collect() } -fn insert_rows<'a>(msgs: impl Iterator) -> DataStore { +fn insert_rows<'a>(msgs: impl Iterator) -> (Caches, DataStore) { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), InstanceKey::name(), Default::default(), ); + let mut caches = Caches::new(&store); + msgs.for_each(|row| { - store.insert_row(row).unwrap(); + caches.on_events(&[store.insert_row(row).unwrap()]); }); - store + + (caches, store) } struct SavePoint { @@ -265,7 +275,11 @@ struct SavePoint { _color: Option, } -fn query_and_visit_points(store: &DataStore, paths: &[EntityPath]) -> Vec { +fn query_and_visit_points( + caches: &Caches, + store: &DataStore, + paths: &[EntityPath], +) -> Vec { let resolver = PromiseResolver::default(); let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); @@ -275,7 +289,7 @@ fn query_and_visit_points(store: &DataStore, paths: &[EntityPath]) -> Vec Vec(&resolver) .flatten() - .unwrap(); + .unwrap() + .copied(); - let colors = colors.iter_dense::(&resolver).flatten().unwrap(); + let colors = colors + .iter_dense::(&resolver) + .flatten() + .unwrap() + .copied(); let color_default_fn = || Color::from(0xFF00FFFF); for (point, color) in clamped_zip_1x1(points, colors, color_default_fn) { @@ -308,7 +327,11 @@ struct SaveString { _label: Option, } -fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec { +fn query_and_visit_strings( + caches: &Caches, + store: &DataStore, + paths: &[EntityPath], +) -> Vec { let resolver = PromiseResolver::default(); let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); @@ -317,7 +340,7 @@ fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec Vec(&resolver) .flatten() - .unwrap(); + .unwrap() + .copied(); - let labels = colors.iter_dense::(&resolver).flatten().unwrap(); + let labels = colors + .iter_dense::(&resolver) + .flatten() + .unwrap() + .cloned(); let label_default_fn = || Text(String::new().into()); for (_point, label) in clamped_zip_1x1(points, labels, label_default_fn) { @@ -342,6 +370,5 @@ fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec anyhow::Result<()> { let query = LatestAtQuery::latest(timeline); eprintln!("query:{query:?}"); - // First, get the raw results for this query. + let caches = re_query2::Caches::new(&store); + + // First, get the results for this query. // - // Raw here means that these results are neither deserialized, nor resolved/converted. - // I.e. this corresponds to the raw `DataCell`s, straight from our datastore. - let results: LatestAtResults = re_query2::latest_at( + // They might or might not already be cached. We won't know for sure until we try to access + // each individual component's data below. + let results: CachedLatestAtResults = caches.latest_at( &store, &query, &entity_path.into(), MyPoints::all_components().iter().copied(), // no generics! ); - // Then, grab the raw results for each individual components. - // - // This is still raw data, but now a choice has been made regarding the nullability of the - // _component batch_ itself (that says nothing about its _instances_!). - // + // Then, grab the results for each individual components. // * `get_required` returns an error if the component batch is missing // * `get_or_empty` returns an empty set of results if the component if missing // * `get` returns an option - let points: &LatestAtComponentResults = results.get_required(MyPoint::name())?; - let colors: &LatestAtComponentResults = results.get_or_empty(MyColor::name()); - let labels: &LatestAtComponentResults = results.get_or_empty(MyLabel::name()); + // + // At this point we still don't know whether they are cached or not. That's the next step. + let points: &CachedLatestAtComponentResults = results.get_required(MyPoint::name())?; + let colors: &CachedLatestAtComponentResults = results.get_or_empty(MyColor::name()); + let labels: &CachedLatestAtComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. @@ -50,9 +51,10 @@ fn main() -> anyhow::Result<()> { // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. // Use `PromiseResult::flatten` to simplify it down to a single result. // - // A choice now has to be made regarding the nullability of the _component batch's instances_. - // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably - // shouldn't be using anything but `iter_dense`. + // This is the step at which caching comes into play. + // If the data has already been accessed in the past, then this will just grab the pre-deserialized, + // pre-resolved/pre-converted result from the cache. + // Otherwise, this will trigger a deserialization and cache the result for next time. let points = match points.iter_dense::(&resolver).flatten() { PromiseResult::Pending => { @@ -72,12 +74,12 @@ fn main() -> anyhow::Result<()> { PromiseResult::Error(err) => return Err(err.into()), }; - let labels = match labels.iter_sparse::(&resolver).flatten() { + let labels = match labels.iter_dense::(&resolver).flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. return Ok(()); } - PromiseResult::Ready(data) => data, + PromiseResult::Ready(data) => data.map(Some), PromiseResult::Error(err) => return Err(err.into()), }; @@ -86,7 +88,10 @@ fn main() -> anyhow::Result<()> { // // In most cases this will be either a clamped zip, or no joining at all. - let color_default_fn = || MyColor::from(0xFF00FFFF); + let color_default_fn = || { + static DEFAULT: MyColor = MyColor(0xFF00FFFF); + &DEFAULT + }; let label_default_fn = || None; let results = diff --git a/crates/re_query_cache/examples/latest_at_archetype.rs b/crates/re_query2/examples/latest_at_archetype.rs similarity index 94% rename from crates/re_query_cache/examples/latest_at_archetype.rs rename to crates/re_query2/examples/latest_at_archetype.rs index 94caab585ce2..3205598557e5 100644 --- a/crates/re_query_cache/examples/latest_at_archetype.rs +++ b/crates/re_query2/examples/latest_at_archetype.rs @@ -7,7 +7,7 @@ use re_types::{ }; use re_types_core::{Archetype as _, Loggable as _}; -use re_query_cache::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; +use re_query2::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; // --- @@ -22,7 +22,7 @@ fn main() -> anyhow::Result<()> { let query = LatestAtQuery::latest(timeline); eprintln!("query:{query:?}"); - let caches = re_query_cache::Caches::new(&store); + let caches = re_query2::Caches::new(&store); // First, get the results for this query. // @@ -37,7 +37,7 @@ fn main() -> anyhow::Result<()> { // Then make use of the `ToArchetype` helper trait in order to query, resolve, deserialize and // cache an entire archetype all at once. - use re_query_cache::ToArchetype as _; + use re_query2::ToArchetype as _; let arch: Points2D = match results.to_archetype(&resolver).flatten() { PromiseResult::Pending => { diff --git a/crates/re_query2/examples/range.rs b/crates/re_query2/examples/range.rs index e8c1a5227dc8..d1bd8e4d55da 100644 --- a/crates/re_query2/examples/range.rs +++ b/crates/re_query2/examples/range.rs @@ -1,12 +1,12 @@ -use itertools::{izip, Itertools}; +use itertools::Itertools; use re_data_store::{DataStore, RangeQuery}; use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline}; use re_types_core::{Archetype as _, Loggable as _}; use re_query2::{ - clamped_zip_1x2, range_zip_1x2, PromiseResolver, PromiseResult, RangeComponentResults, - RangeResults, + clamped_zip_1x2, range_zip_1x2, CachedRangeComponentResults, CachedRangeResults, + PromiseResolver, PromiseResult, }; // --- @@ -22,90 +22,73 @@ fn main() -> anyhow::Result<()> { let query = RangeQuery::new(timeline, TimeRange::EVERYTHING); eprintln!("query:{query:?}"); + let caches = re_query2::Caches::new(&store); + // First, get the raw results for this query. // - // Raw here means that these results are neither deserialized, nor resolved/converted. - // I.e. this corresponds to the raw `DataCell`s, straight from our datastore. - let results: RangeResults = re_query2::range( + // They might or might not already be cached. We won't know for sure until we try to access + // each individual component's data below. + let results: CachedRangeResults = caches.range( &store, &query, &entity_path.into(), MyPoints::all_components().iter().copied(), // no generics! ); - // Then, grab the raw results for each individual components. - // - // This is still raw data, but now a choice has been made regarding the nullability of the - // _component batch_ itself (that says nothing about its _instances_!). - // + // Then, grab the results for each individual components. // * `get_required` returns an error if the component batch is missing // * `get_or_empty` returns an empty set of results if the component if missing // * `get` returns an option - let all_points: &RangeComponentResults = results.get_required(MyPoint::name())?; - let all_colors: &RangeComponentResults = results.get_or_empty(MyColor::name()); - let all_labels: &RangeComponentResults = results.get_or_empty(MyLabel::name()); + // + // At this point we still don't know whether they are cached or not. That's the next step. + let all_points: &CachedRangeComponentResults = results.get_required(MyPoint::name())?; + let all_colors: &CachedRangeComponentResults = results.get_or_empty(MyColor::name()); + let all_labels: &CachedRangeComponentResults = results.get_or_empty(MyLabel::name()); - let all_indexed_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_indexed_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - let all_indexed_labels = izip!( - all_labels.iter_indices(), - all_labels.iter_sparse::(&resolver) + // Then comes the time to resolve/convert and deserialize the data. + // These steps have to be done together for efficiency reasons. + // + // That's when caching comes into play. + // If the data has already been accessed in the past, then this will just grab the + // pre-deserialized, pre-resolved/pre-converted result from the cache. + // Otherwise, this will trigger a deserialization and cache the result for next time. + let all_points = all_points.to_dense::(&resolver); + let all_colors = all_colors.to_dense::(&resolver); + let all_labels = all_labels.to_dense::(&resolver); + + // The cache might not have been able to resolve and deserialize the entire dataset across all + // available timestamps. + // + // We can use the following APIs to check the status of the front and back sides of the data range. + // + // E.g. it is possible that the front-side of the range is still waiting for pending data while + // the back-side has been fully loaded. + assert!(matches!( + all_points.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())) + )); + + // Zip the results together using a stateful time-based join. + let all_frames = range_zip_1x2( + all_points.range_indexed(), + all_colors.range_indexed(), + all_labels.range_indexed(), ); - let all_frames = range_zip_1x2(all_indexed_points, all_indexed_colors, all_indexed_labels); - // Then comes the time to resolve/convert and deserialize the data, _for each timestamp_. // These steps have to be done together for efficiency reasons. // // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. // Use `PromiseResult::flatten` to simplify it down to a single result. - // - // A choice now has to be made regarding the nullability of the _component batch's instances_. - // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably - // shouldn't be using anything but `iter_dense`. eprintln!("results:"); for ((data_time, row_id), points, colors, labels) in all_frames { - let points = match points.flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - continue; - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), + let colors = colors.unwrap_or(&[]); + let color_default_fn = || { + static DEFAULT: MyColor = MyColor(0xFF00FFFF); + &DEFAULT }; - let colors = if let Some(colors) = colors { - match colors.flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - continue; - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - } - } else { - vec![] - }; - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let labels = if let Some(labels) = labels { - match labels.flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - continue; - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - } - } else { - vec![] - }; + let labels = labels.unwrap_or(&[]).iter().cloned().map(Some); let label_default_fn = || None; // With the data now fully resolved/converted and deserialized, the joining logic can be diff --git a/crates/re_query2/src/bin/clamped_zip.rs b/crates/re_query2/src/bin/clamped_zip.rs index bb4b642f4ac7..571e9b89f27f 100644 --- a/crates/re_query2/src/bin/clamped_zip.rs +++ b/crates/re_query2/src/bin/clamped_zip.rs @@ -340,7 +340,7 @@ fn main() { println!( " - // This file was generated using `cargo r -p re_query2 --all-features --bin clamped_zip`. + // This file was generated using `cargo r -p crate --all-features --bin clamped_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query2/src/bin/range_zip.rs b/crates/re_query2/src/bin/range_zip.rs index f4af9aae0276..1a843dd5c215 100644 --- a/crates/re_query2/src/bin/range_zip.rs +++ b/crates/re_query2/src/bin/range_zip.rs @@ -486,7 +486,7 @@ fn main() { println!( " - // This file was generated using `cargo r -p re_query2 --all-features --bin range_zip`. + // This file was generated using `cargo r -p crate --all-features --bin range_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query_cache/src/cache.rs b/crates/re_query2/src/cache.rs similarity index 100% rename from crates/re_query_cache/src/cache.rs rename to crates/re_query2/src/cache.rs diff --git a/crates/re_query_cache/src/cache_stats.rs b/crates/re_query2/src/cache_stats.rs similarity index 100% rename from crates/re_query_cache/src/cache_stats.rs rename to crates/re_query2/src/cache_stats.rs diff --git a/crates/re_query2/src/clamped_zip/generated.rs b/crates/re_query2/src/clamped_zip/generated.rs index 7a5c2222b40a..e682a50da861 100644 --- a/crates/re_query2/src/clamped_zip/generated.rs +++ b/crates/re_query2/src/clamped_zip/generated.rs @@ -1,4 +1,4 @@ -// This file was generated using `cargo r -p re_query2 --all-features --bin clamped_zip`. +// This file was generated using `cargo r -p crate --all-features --bin clamped_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query_cache/src/flat_vec_deque.rs b/crates/re_query2/src/flat_vec_deque.rs similarity index 100% rename from crates/re_query_cache/src/flat_vec_deque.rs rename to crates/re_query2/src/flat_vec_deque.rs diff --git a/crates/re_query_cache/src/latest_at/helpers.rs b/crates/re_query2/src/latest_at/helpers.rs similarity index 100% rename from crates/re_query_cache/src/latest_at/helpers.rs rename to crates/re_query2/src/latest_at/helpers.rs diff --git a/crates/re_query2/src/latest_at/mod.rs b/crates/re_query2/src/latest_at/mod.rs index dd86e3d68e3c..82fd889bce0b 100644 --- a/crates/re_query2/src/latest_at/mod.rs +++ b/crates/re_query2/src/latest_at/mod.rs @@ -1,5 +1,10 @@ +mod helpers; mod query; mod results; -pub use self::query::latest_at; -pub use self::results::{LatestAtComponentResults, LatestAtResults}; +#[cfg(feature = "to_archetype")] +mod to_archetype; + +pub use self::helpers::CachedLatestAtMonoResult; +pub use self::query::LatestAtCache; +pub use self::results::{CachedLatestAtComponentResults, CachedLatestAtResults}; diff --git a/crates/re_query2/src/latest_at/query.rs b/crates/re_query2/src/latest_at/query.rs index a9da12168890..825830e9a731 100644 --- a/crates/re_query2/src/latest_at/query.rs +++ b/crates/re_query2/src/latest_at/query.rs @@ -1,40 +1,315 @@ -use re_data_store::{DataStore, LatestAtQuery}; +use std::collections::BTreeSet; +use std::{collections::BTreeMap, sync::Arc}; + +use indexmap::IndexMap; +use itertools::Itertools; +use parking_lot::RwLock; + +use re_data_store::{DataStore, LatestAtQuery, TimeInt}; use re_log_types::EntityPath; +use re_query2::Promise; use re_types_core::ComponentName; +use re_types_core::SizeBytes; -use crate::LatestAtResults; +use crate::{CacheKey, CachedLatestAtComponentResults, CachedLatestAtResults, Caches}; // --- -/// Queries for the given `component_names` using latest-at semantics. -/// -/// See [`LatestAtResults`] for more information about how to handle the results. -pub fn latest_at( - store: &DataStore, - query: &LatestAtQuery, - entity_path: &EntityPath, - component_names: impl IntoIterator, -) -> LatestAtResults { - re_tracing::profile_function!(entity_path.to_string()); - - let mut results = LatestAtResults::default(); - - for component_name in component_names { - let Some((time, row_id, mut cells)) = - store.latest_at(query, entity_path, component_name, &[component_name]) - else { - continue; +impl Caches { + /// Queries for the given `component_names` using latest-at semantics. + /// + /// See [`CachedLatestAtResults`] for more information about how to handle the results. + /// + /// This is a cached API -- data will be lazily cached upon access. + pub fn latest_at( + &self, + store: &DataStore, + query: &LatestAtQuery, + entity_path: &EntityPath, + component_names: impl IntoIterator, + ) -> CachedLatestAtResults { + re_tracing::profile_function!(entity_path.to_string()); + + let mut results = CachedLatestAtResults::default(); + + for component_name in component_names { + let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); + let cache = Arc::clone( + self.latest_at_per_cache_key + .write() + .entry(key.clone()) + .or_insert_with(|| Arc::new(RwLock::new(LatestAtCache::new(key.clone())))), + ); + + let mut cache = cache.write(); + cache.handle_pending_invalidation(); + if let Some(cached) = cache.latest_at(store, query, entity_path, component_name) { + results.add(component_name, cached); + } + } + + results + } +} + +// --- + +/// Caches the results of `LatestAt` queries for a given [`CacheKey`]. +pub struct LatestAtCache { + /// For debugging purposes. + pub cache_key: CacheKey, + + /// Organized by _query_ time. + /// + /// If the data you're looking for isn't in here, try partially running the query and check + /// if there is any data available for the resulting _data_ time in [`Self::per_data_time`]. + // + // NOTE: `Arc` so we can share buckets across query time & data time. + pub per_query_time: BTreeMap>, + + /// Organized by _data_ time. + /// + /// Due to how our latest-at semantics work, any number of queries at time `T+n` where `n >= 0` + /// can result in a data time of `T`. + // + // NOTE: `Arc` so we can share buckets across query time & data time. + pub per_data_time: BTreeMap>, + + /// These timestamps have been invalidated asynchronously. + /// + /// The next time this cache gets queried, it must remove any invalidated entries accordingly. + /// + /// Invalidation is deferred to query time because it is far more efficient that way: the frame + /// time effectively behaves as a natural micro-batching mechanism. + pub pending_invalidations: BTreeSet, +} + +impl LatestAtCache { + #[inline] + pub fn new(cache_key: CacheKey) -> Self { + Self { + cache_key, + per_query_time: Default::default(), + per_data_time: Default::default(), + pending_invalidations: Default::default(), + } + } +} + +impl std::fmt::Debug for LatestAtCache { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + cache_key, + per_query_time, + per_data_time, + pending_invalidations: _, + } = self; + + let mut strings = Vec::new(); + + struct StatsPerBucket { + query_times: BTreeSet, + data_time: TimeInt, + total_size_bytes: u64, + } + + let mut buckets: IndexMap<_, _> = per_data_time + .iter() + .map(|(&data_time, bucket)| { + ( + Arc::as_ptr(bucket), + StatsPerBucket { + query_times: Default::default(), + data_time, + total_size_bytes: bucket.total_size_bytes(), + }, + ) + }) + .collect(); + + for (&query_time, bucket) in per_query_time { + if let Some(bucket) = buckets.get_mut(&Arc::as_ptr(bucket)) { + bucket.query_times.insert(query_time); + } + } + + for bucket in buckets.values() { + strings.push(format!( + "query_times=[{}] -> data_time={:?} ({})", + bucket + .query_times + .iter() + .map(|t| cache_key.timeline.typ().format_utc(*t)) + .collect_vec() + .join(", "), + bucket.data_time.as_i64(), + re_format::format_bytes(bucket.total_size_bytes as _), + )); + } + + if strings.is_empty() { + return f.write_str(""); + } + + f.write_str(&strings.join("\n").replace("\n\n", "\n")) + } +} + +impl SizeBytes for LatestAtCache { + #[inline] + fn heap_size_bytes(&self) -> u64 { + let Self { + cache_key: _, + per_query_time, + per_data_time, + pending_invalidations, + } = self; + + let per_query_time = per_query_time + .keys() + .map(|k| k.total_size_bytes()) + .sum::(); + // NOTE: per query time buckets are just pointers, don't count them. + + let per_data_time_keys = per_data_time + .keys() + .map(|k| k.total_size_bytes()) + .sum::(); + let per_data_time_values = per_data_time + .values() + // NOTE: make sure to dereference the Arc, else this will account for zero (assumed amortized!) + .map(|arc| (**arc).total_size_bytes()) + .sum::(); + + let per_data_time = per_data_time_keys + per_data_time_values; + let pending_invalidations = pending_invalidations.total_size_bytes(); + + per_query_time + per_data_time + pending_invalidations + } +} + +impl LatestAtCache { + /// Queries cached latest-at data for a single component. + pub fn latest_at( + &mut self, + store: &DataStore, + query: &LatestAtQuery, + entity_path: &EntityPath, + component_name: ComponentName, + ) -> Option> { + re_tracing::profile_scope!("latest_at", format!("{query:?}")); + + let LatestAtCache { + cache_key: _, + per_query_time, + per_data_time, + pending_invalidations: _, + } = self; + + let query_time_bucket_at_query_time = match per_query_time.entry(query.at()) { + std::collections::btree_map::Entry::Occupied(entry) => { + // Fastest path: we have an entry for this exact query time, no need to look any + // further. + re_log::trace!(query_time=?query.at(), "cache hit (query time)"); + return Some(Arc::clone(entry.get())); + } + std::collections::btree_map::Entry::Vacant(entry) => entry, }; - // Soundness: - // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` - // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null - if let Some(cell) = cells[0].take() { - results.add(component_name, (time, row_id), cell); + let result = store.latest_at(query, entity_path, component_name, &[component_name]); + + // NOTE: cannot `result.and_then(...)` or borrowck gets lost. + if let Some((data_time, row_id, mut cells)) = result { + // Fast path: we've run the query and realized that we already have the data for the resulting + // _data_ time, so let's use that to avoid join & deserialization costs. + if let Some(data_time_bucket_at_data_time) = per_data_time.get(&data_time) { + re_log::trace!(query_time=?query.at(), ?data_time, "cache hit (data time)"); + + query_time_bucket_at_query_time.insert(Arc::clone(data_time_bucket_at_data_time)); + + // We now know for a fact that a query at that data time would yield the same + // results: copy the bucket accordingly so that the next cache hit for that query + // time ends up taking the fastest path. + let query_time_bucket_at_data_time = per_query_time.entry(data_time); + query_time_bucket_at_data_time + .and_modify(|v| *v = Arc::clone(data_time_bucket_at_data_time)) + .or_insert(Arc::clone(data_time_bucket_at_data_time)); + + return Some(Arc::clone(data_time_bucket_at_data_time)); + } + + // Soundness: + // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` + // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null + let Some(cell) = cells[0].take() else { + debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); + return None; + }; + + let bucket = Arc::new(CachedLatestAtComponentResults { + index: (data_time, row_id), + promise: Some(Promise::new(cell)), + cached_dense: Default::default(), + }); + + // Slowest path: this is a complete cache miss. + { + re_log::trace!(query_time=?query.at(), ?data_time, "cache miss"); + + let query_time_bucket_at_query_time = + query_time_bucket_at_query_time.insert(Arc::clone(&bucket)); + + let data_time_bucket_at_data_time = per_data_time.entry(data_time); + data_time_bucket_at_data_time + .and_modify(|v| *v = Arc::clone(query_time_bucket_at_query_time)) + .or_insert(Arc::clone(query_time_bucket_at_query_time)); + } + + Some(bucket) } else { - debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); + None } } - results + pub fn handle_pending_invalidation(&mut self) { + let Self { + cache_key: _, + per_query_time, + per_data_time, + pending_invalidations, + } = self; + + // First, remove any data indexed by a _query time_ that's more recent than the oldest + // _data time_ that's been invalidated. + // + // Note that this data time might very well be `TimeInt::STATIC`, in which case the entire + // query-time-based index will be dropped. + if let Some(&oldest_data_time) = pending_invalidations.first() { + per_query_time.retain(|&query_time, _| query_time < oldest_data_time); + } + + // Second, remove any data indexed by _data time_, if it's been invalidated. + let mut dropped_data_times = Vec::new(); + per_data_time.retain(|data_time, _| { + if pending_invalidations.contains(data_time) { + dropped_data_times.push(*data_time); + false + } else { + true + } + }); + + // TODO(#5974): Because of non-deterministic ordering and parallelism and all things of that + // nature, it can happen that we try to handle pending invalidations before we even cached + // the associated data. + // + // If that happens, the data will be cached after we've invalidated *nothing*, and will stay + // there indefinitely since the cache doesn't have a dedicated GC yet. + // + // TL;DR: make sure to keep track of pending invalidations indefinitely as long as we + // haven't had the opportunity to actually invalidate the associated data. + for data_time in dropped_data_times { + pending_invalidations.remove(&data_time); + } + } } diff --git a/crates/re_query2/src/latest_at/results.rs b/crates/re_query2/src/latest_at/results.rs index aef7167423dc..44691217ac9d 100644 --- a/crates/re_query2/src/latest_at/results.rs +++ b/crates/re_query2/src/latest_at/results.rs @@ -1,21 +1,24 @@ +use std::sync::{Arc, OnceLock}; + use nohash_hasher::IntMap; + use re_log_types::{DataCell, RowId, TimeInt}; -use re_types_core::ComponentName; -use re_types_core::{Component, DeserializationError, DeserializationResult}; +use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes}; -use crate::{Promise, PromiseResolver, PromiseResult}; +use crate::{ + ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, PromiseResult, QueryError, +}; // --- -/// Raw results for a latest-at query. +/// Cached results for a latest-at query. /// -/// The data is neither deserialized, nor resolved/converted. -/// It it the raw [`DataCell`]s, straight from our datastore. +/// The data is both deserialized and resolved/converted. /// -/// Use [`LatestAtResults::get`], [`LatestAtResults::get_required`] and [`LatestAtResults::get_or_empty`] -/// in order to access the raw results for each individual component. -#[derive(Debug, Clone)] -pub struct LatestAtResults { +/// Use [`CachedLatestAtResults::get`], [`CachedLatestAtResults::get_required`] and +/// [`CachedLatestAtResults::get_or_empty`] in order to access the results for each individual component. +#[derive(Debug)] +pub struct CachedLatestAtResults { /// The compound index of this query result. /// /// A latest-at query is a compound operation that gathers data from many different rows. @@ -23,11 +26,11 @@ pub struct LatestAtResults { /// sub-results, as defined by time and row-id order. pub compound_index: (TimeInt, RowId), - /// Raw results for each individual component. - pub components: IntMap, + /// Results for each individual component. + pub components: IntMap>, } -impl Default for LatestAtResults { +impl Default for CachedLatestAtResults { #[inline] fn default() -> Self { Self { @@ -37,63 +40,65 @@ impl Default for LatestAtResults { } } -impl LatestAtResults { +impl CachedLatestAtResults { #[inline] pub fn contains(&self, component_name: impl Into) -> bool { self.components.contains_key(&component_name.into()) } - /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. + /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. #[inline] pub fn get( &self, component_name: impl Into, - ) -> Option<&LatestAtComponentResults> { - self.components.get(&component_name.into()) + ) -> Option<&CachedLatestAtComponentResults> { + self.components + .get(&component_name.into()) + .map(|arc| &**arc) } - /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. + /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. /// /// Returns an error if the component is not present. #[inline] pub fn get_required( &self, component_name: impl Into, - ) -> crate::Result<&LatestAtComponentResults> { + ) -> crate::Result<&CachedLatestAtComponentResults> { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { Ok(component) } else { - Err(DeserializationError::MissingComponent { - component: component_name, - backtrace: ::backtrace::Backtrace::new_unresolved(), - } - .into()) + Err(QueryError::PrimaryNotFound(component_name)) } } - /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. + /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. /// /// Returns empty results if the component is not present. #[inline] pub fn get_or_empty( &self, component_name: impl Into, - ) -> &LatestAtComponentResults { + ) -> &CachedLatestAtComponentResults { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { component } else { - static DEFAULT: LatestAtComponentResults = LatestAtComponentResults::EMPTY; - &DEFAULT + static EMPTY: CachedLatestAtComponentResults = CachedLatestAtComponentResults::empty(); + &EMPTY } } } -impl LatestAtResults { +impl CachedLatestAtResults { #[doc(hidden)] #[inline] - pub fn add(&mut self, component_name: ComponentName, index: (TimeInt, RowId), cell: DataCell) { + pub fn add( + &mut self, + component_name: ComponentName, + cached: Arc, + ) { // NOTE: Since this is a compound API that actually emits multiple queries, the index of the // final result is the most recent index among all of its components, as defined by time // and row-id order. @@ -102,52 +107,119 @@ impl LatestAtResults { // reasons with the legacy instance-key model. This will go away next. use re_types_core::Loggable as _; if component_name != re_types_core::components::InstanceKey::name() - && index > self.compound_index + && cached.index > self.compound_index { - self.compound_index = index; + self.compound_index = cached.index; } - self.components.insert( - component_name, - LatestAtComponentResults { - index, - promise: Some(Promise::new(cell)), - }, - ); + self.components.insert(component_name, cached); } } // --- -/// Uncached results for a particular component when using a latest-at query. -#[derive(Debug, Clone)] -pub struct LatestAtComponentResults { - index: (TimeInt, RowId), +/// Lazily cached results for a particular component when using a cached latest-at query. +pub struct CachedLatestAtComponentResults { + pub(crate) index: (TimeInt, RowId), - // Option so we can have a constant default value for `Self` for the optional+empty case. - promise: Option, + // Option so we can have a constant default value for `Self`. + pub(crate) promise: Option, + + /// The resolved, converted, deserialized dense data. + pub(crate) cached_dense: OnceLock>, } -impl Default for LatestAtComponentResults { +impl CachedLatestAtComponentResults { #[inline] - fn default() -> Self { - Self::EMPTY + pub const fn empty() -> Self { + Self { + index: (TimeInt::STATIC, RowId::ZERO), + promise: None, + cached_dense: OnceLock::new(), + } + } + + /// Returns the [`ComponentName`] of the resolved data, if available. + #[inline] + pub fn component_name(&self, resolver: &PromiseResolver) -> Option { + match self.resolved(resolver) { + PromiseResult::Ready(cell) => Some(cell.component_name()), + _ => None, + } + } + + /// Returns whether the resolved data is static. + #[inline] + pub fn is_static(&self) -> bool { + self.index.0 == TimeInt::STATIC + } + + /// How many _indices_ across this entire cache? + #[inline] + pub fn num_indices(&self) -> u64 { + _ = self; + 1 + } + + /// How many _instances_ across this entire cache? + #[inline] + pub fn num_instances(&self) -> u64 { + self.cached_dense + .get() + .map_or(0u64, |cached| cached.dyn_num_values() as _) + } +} + +impl SizeBytes for CachedLatestAtComponentResults { + #[inline] + fn heap_size_bytes(&self) -> u64 { + let Self { + index, + promise, + cached_dense, + } = self; + + index.total_size_bytes() + + promise.total_size_bytes() + + cached_dense + .get() + .map_or(0, |data| data.dyn_total_size_bytes()) } } -impl LatestAtComponentResults { - const EMPTY: Self = Self { - index: (TimeInt::STATIC, RowId::ZERO), - promise: None, - }; +impl std::fmt::Debug for CachedLatestAtComponentResults { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + index, + promise: _, + cached_dense: _, // we can't, we don't know the type + } = self; + + f.write_fmt(format_args!( + "[{:?}#{}] {}", + index.0, + index.1, + re_format::format_bytes(self.total_size_bytes() as _) + )) + } } -impl LatestAtComponentResults { +impl CachedLatestAtComponentResults { #[inline] pub fn index(&self) -> &(TimeInt, RowId) { &self.index } + /// Returns the raw resolved data, if it's ready. + #[inline] + pub fn resolved(&self, resolver: &PromiseResolver) -> PromiseResult { + if let Some(cell) = self.promise.as_ref() { + resolver.resolve(cell) + } else { + PromiseResult::Pending + } + } + /// Returns the component data as a dense vector. /// /// Returns an error if the component is missing or cannot be deserialized. @@ -158,15 +230,14 @@ impl LatestAtComponentResults { pub fn to_dense( &self, resolver: &PromiseResolver, - ) -> PromiseResult>> { + ) -> PromiseResult> { if let Some(cell) = self.promise.as_ref() { - resolver.resolve(cell).map(|cell| { - cell.try_to_native() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) + resolver + .resolve(cell) + .map(|cell| self.downcast_dense::(&cell)) } else { // Manufactured empty result. - PromiseResult::Ready(Ok(vec![])) + PromiseResult::Ready(Ok(&[])) } } @@ -180,45 +251,49 @@ impl LatestAtComponentResults { pub fn iter_dense( &self, resolver: &PromiseResolver, - ) -> PromiseResult>> { + ) -> PromiseResult>> { self.to_dense(resolver) - .map(|data| data.map(|data| data.into_iter())) + .map(|data| data.map(|data| data.iter())) } +} - /// Returns the component data as a sparse vector. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_sparse( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>>> { - if let Some(cell) = self.promise.as_ref() { - resolver.resolve(cell).map(|cell| { - cell.try_to_native_opt() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) - } else { - // Manufactured empty result. - PromiseResult::Ready(Ok(vec![])) +impl CachedLatestAtComponentResults { + fn downcast_dense(&self, cell: &DataCell) -> crate::Result<&[C]> { + // `OnceLock::get` is non-blocking -- this is a best-effort fast path in case the + // data has already been computed. + // + // See next comment as to why we need this. + if let Some(cached) = self.cached_dense.get() { + return downcast(&**cached); } + + // We have to do this outside of the callback in order to propagate errors. + // Hence the early exit check above. + let data = cell + .try_to_native::() + .map_err(|err| DeserializationError::DataCellError(err.to_string()))?; + + #[allow(clippy::borrowed_box)] + let cached: &Arc = self + .cached_dense + .get_or_init(move || Arc::new(FlatVecDeque::from(data))); + + downcast(&**cached) } +} - /// Iterates over the component data, assuming it is sparse. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_sparse( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>>> { - self.to_sparse(resolver) - .map(|data| data.map(|data| data.into_iter())) +fn downcast(cached: &(dyn ErasedFlatVecDeque + Send + Sync)) -> crate::Result<&[C]> { + let cached = cached + .as_any() + .downcast_ref::>() + .ok_or_else(|| QueryError::TypeMismatch { + actual: "".into(), + requested: C::name(), + })?; + + if cached.num_entries() != 1 { + return Err(anyhow::anyhow!("latest_at deque must be single entry").into()); } + // unwrap checked just above ^^^ + Ok(cached.iter().next().unwrap()) } diff --git a/crates/re_query_cache/src/latest_at/to_archetype/.gitattributes b/crates/re_query2/src/latest_at/to_archetype/.gitattributes similarity index 100% rename from crates/re_query_cache/src/latest_at/to_archetype/.gitattributes rename to crates/re_query2/src/latest_at/to_archetype/.gitattributes diff --git a/crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs b/crates/re_query2/src/latest_at/to_archetype/annotation_context.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs rename to crates/re_query2/src/latest_at/to_archetype/annotation_context.rs index 53d7683b3ce8..32c55996d1d4 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs +++ b/crates/re_query2/src/latest_at/to_archetype/annotation_context.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs b/crates/re_query2/src/latest_at/to_archetype/arrows2d.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs rename to crates/re_query2/src/latest_at/to_archetype/arrows2d.rs index f040190bd594..04183db62d79 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/arrows2d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs b/crates/re_query2/src/latest_at/to_archetype/arrows3d.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs rename to crates/re_query2/src/latest_at/to_archetype/arrows3d.rs index 4a2a0eb34032..06436d914c7a 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/arrows3d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs b/crates/re_query2/src/latest_at/to_archetype/asset3d.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs rename to crates/re_query2/src/latest_at/to_archetype/asset3d.rs index be8c7893f790..a1ad89a64e70 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/asset3d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs b/crates/re_query2/src/latest_at/to_archetype/bar_chart.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs rename to crates/re_query2/src/latest_at/to_archetype/bar_chart.rs index 5e291449999b..ae974df725af 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs +++ b/crates/re_query2/src/latest_at/to_archetype/bar_chart.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs b/crates/re_query2/src/latest_at/to_archetype/boxes2d.rs similarity index 99% rename from crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs rename to crates/re_query2/src/latest_at/to_archetype/boxes2d.rs index 84559fa17b0f..2a41e9b3896e 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/boxes2d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs b/crates/re_query2/src/latest_at/to_archetype/boxes3d.rs similarity index 99% rename from crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs rename to crates/re_query2/src/latest_at/to_archetype/boxes3d.rs index bc9736f831be..4aff333508f6 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/boxes3d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/clear.rs b/crates/re_query2/src/latest_at/to_archetype/clear.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/clear.rs rename to crates/re_query2/src/latest_at/to_archetype/clear.rs index a71abd061fc4..c3cea969637b 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/clear.rs +++ b/crates/re_query2/src/latest_at/to_archetype/clear.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs b/crates/re_query2/src/latest_at/to_archetype/container_blueprint.rs similarity index 99% rename from crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs rename to crates/re_query2/src/latest_at/to_archetype/container_blueprint.rs index 2e89b1ff2d1d..03a0757bf605 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs +++ b/crates/re_query2/src/latest_at/to_archetype/container_blueprint.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs b/crates/re_query2/src/latest_at/to_archetype/depth_image.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs rename to crates/re_query2/src/latest_at/to_archetype/depth_image.rs index b0a610bc151b..c40adca04815 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs +++ b/crates/re_query2/src/latest_at/to_archetype/depth_image.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs b/crates/re_query2/src/latest_at/to_archetype/disconnected_space.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs rename to crates/re_query2/src/latest_at/to_archetype/disconnected_space.rs index 21bdfadbbc2a..8f497f463645 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs +++ b/crates/re_query2/src/latest_at/to_archetype/disconnected_space.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/image.rs b/crates/re_query2/src/latest_at/to_archetype/image.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/image.rs rename to crates/re_query2/src/latest_at/to_archetype/image.rs index f5d8ea7d7c6f..c051ca501069 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/image.rs +++ b/crates/re_query2/src/latest_at/to_archetype/image.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs b/crates/re_query2/src/latest_at/to_archetype/line_strips2d.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs rename to crates/re_query2/src/latest_at/to_archetype/line_strips2d.rs index ab6216861a69..d0d8c607294e 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/line_strips2d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs b/crates/re_query2/src/latest_at/to_archetype/line_strips3d.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs rename to crates/re_query2/src/latest_at/to_archetype/line_strips3d.rs index 0954bf35bb5f..1ac3c7629104 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/line_strips3d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs b/crates/re_query2/src/latest_at/to_archetype/mesh3d.rs similarity index 99% rename from crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs rename to crates/re_query2/src/latest_at/to_archetype/mesh3d.rs index 0b2462e1eb1a..d3b526d7da4c 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/mesh3d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/mod.rs b/crates/re_query2/src/latest_at/to_archetype/mod.rs similarity index 100% rename from crates/re_query_cache/src/latest_at/to_archetype/mod.rs rename to crates/re_query2/src/latest_at/to_archetype/mod.rs diff --git a/crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs b/crates/re_query2/src/latest_at/to_archetype/panel_blueprint.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs rename to crates/re_query2/src/latest_at/to_archetype/panel_blueprint.rs index 307555ffaa4b..f45127c1fe63 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs +++ b/crates/re_query2/src/latest_at/to_archetype/panel_blueprint.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs b/crates/re_query2/src/latest_at/to_archetype/pinhole.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs rename to crates/re_query2/src/latest_at/to_archetype/pinhole.rs index b192479b28d8..6ee4d70f6fbd 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs +++ b/crates/re_query2/src/latest_at/to_archetype/pinhole.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs b/crates/re_query2/src/latest_at/to_archetype/plot_legend.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs rename to crates/re_query2/src/latest_at/to_archetype/plot_legend.rs index 241ec44a6840..39afedddce07 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs +++ b/crates/re_query2/src/latest_at/to_archetype/plot_legend.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/points2d.rs b/crates/re_query2/src/latest_at/to_archetype/points2d.rs similarity index 99% rename from crates/re_query_cache/src/latest_at/to_archetype/points2d.rs rename to crates/re_query2/src/latest_at/to_archetype/points2d.rs index ba928c21f306..f3a232cad0a9 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/points2d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/points2d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/points3d.rs b/crates/re_query2/src/latest_at/to_archetype/points3d.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/points3d.rs rename to crates/re_query2/src/latest_at/to_archetype/points3d.rs index f6802a051736..46e0378bb920 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/points3d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/points3d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/scalar.rs b/crates/re_query2/src/latest_at/to_archetype/scalar.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/scalar.rs rename to crates/re_query2/src/latest_at/to_archetype/scalar.rs index b14c08327799..5cf1e24252c2 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/scalar.rs +++ b/crates/re_query2/src/latest_at/to_archetype/scalar.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs b/crates/re_query2/src/latest_at/to_archetype/scalar_axis.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs rename to crates/re_query2/src/latest_at/to_archetype/scalar_axis.rs index 8a7fe1107ad0..435c508a6631 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs +++ b/crates/re_query2/src/latest_at/to_archetype/scalar_axis.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs b/crates/re_query2/src/latest_at/to_archetype/segmentation_image.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs rename to crates/re_query2/src/latest_at/to_archetype/segmentation_image.rs index 15cf8e991355..75dcc768d020 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs +++ b/crates/re_query2/src/latest_at/to_archetype/segmentation_image.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/series_line.rs b/crates/re_query2/src/latest_at/to_archetype/series_line.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/series_line.rs rename to crates/re_query2/src/latest_at/to_archetype/series_line.rs index eae0d8411532..dea250769fd5 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/series_line.rs +++ b/crates/re_query2/src/latest_at/to_archetype/series_line.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/series_point.rs b/crates/re_query2/src/latest_at/to_archetype/series_point.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/series_point.rs rename to crates/re_query2/src/latest_at/to_archetype/series_point.rs index 4487e290958a..29bf8d0cc8b8 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/series_point.rs +++ b/crates/re_query2/src/latest_at/to_archetype/series_point.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs b/crates/re_query2/src/latest_at/to_archetype/space_view_blueprint.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs rename to crates/re_query2/src/latest_at/to_archetype/space_view_blueprint.rs index 9449705381c6..85062f94fe02 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs +++ b/crates/re_query2/src/latest_at/to_archetype/space_view_blueprint.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs b/crates/re_query2/src/latest_at/to_archetype/space_view_contents.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs rename to crates/re_query2/src/latest_at/to_archetype/space_view_contents.rs index 3fa4e0035f65..f66bffb13718 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs +++ b/crates/re_query2/src/latest_at/to_archetype/space_view_contents.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/tensor.rs b/crates/re_query2/src/latest_at/to_archetype/tensor.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/tensor.rs rename to crates/re_query2/src/latest_at/to_archetype/tensor.rs index d275be94b2b4..2b6e569aac7e 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/tensor.rs +++ b/crates/re_query2/src/latest_at/to_archetype/tensor.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/text_document.rs b/crates/re_query2/src/latest_at/to_archetype/text_document.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/text_document.rs rename to crates/re_query2/src/latest_at/to_archetype/text_document.rs index 25c97086443e..f423045cb5e9 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/text_document.rs +++ b/crates/re_query2/src/latest_at/to_archetype/text_document.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/text_log.rs b/crates/re_query2/src/latest_at/to_archetype/text_log.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/text_log.rs rename to crates/re_query2/src/latest_at/to_archetype/text_log.rs index 90bff49a5628..6e4cf9e7e6db 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/text_log.rs +++ b/crates/re_query2/src/latest_at/to_archetype/text_log.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs b/crates/re_query2/src/latest_at/to_archetype/transform3d.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs rename to crates/re_query2/src/latest_at/to_archetype/transform3d.rs index 05abe63d9a59..ecbe2a651c2f 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs +++ b/crates/re_query2/src/latest_at/to_archetype/transform3d.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs b/crates/re_query2/src/latest_at/to_archetype/view_coordinates.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs rename to crates/re_query2/src/latest_at/to_archetype/view_coordinates.rs index db3ad868c8ac..d9ea4c9de036 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs +++ b/crates/re_query2/src/latest_at/to_archetype/view_coordinates.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs b/crates/re_query2/src/latest_at/to_archetype/viewport_blueprint.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs rename to crates/re_query2/src/latest_at/to_archetype/viewport_blueprint.rs index 3ba2039dcc99..f4ba63de006a 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs +++ b/crates/re_query2/src/latest_at/to_archetype/viewport_blueprint.rs @@ -6,7 +6,7 @@ #![allow(clippy::cloned_instead_of_copied)] use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query2/src/lib.rs b/crates/re_query2/src/lib.rs index 94e94a06f803..6113316f522e 100644 --- a/crates/re_query2/src/lib.rs +++ b/crates/re_query2/src/lib.rs @@ -1,5 +1,8 @@ -//! Provide query-centric access to the [`re_data_store`]. +//! Caching datastructures for `re_query`. +mod cache; +mod cache_stats; +mod flat_vec_deque; mod latest_at; mod promise; mod range; @@ -8,13 +11,26 @@ mod visible_history; pub mod clamped_zip; pub mod range_zip; +pub use self::cache::{CacheKey, Caches}; +pub use self::cache_stats::{CachedComponentStats, CachesStats}; pub use self::clamped_zip::*; -pub use self::latest_at::{latest_at, LatestAtComponentResults, LatestAtResults}; +pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; +pub use self::latest_at::{ + CachedLatestAtComponentResults, CachedLatestAtMonoResult, CachedLatestAtResults, +}; pub use self::promise::{Promise, PromiseId, PromiseResolver, PromiseResult}; -pub use self::range::{range, RangeComponentResults, RangeResults}; +pub use self::range::{CachedRangeComponentResults, CachedRangeData, CachedRangeResults}; pub use self::range_zip::*; pub use self::visible_history::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +pub(crate) use self::latest_at::LatestAtCache; +pub(crate) use self::range::{CachedRangeComponentResultsInner, RangeCache}; + +pub mod external { + pub use paste; + pub use seq_macro; +} + // --- #[derive(Debug, Clone, Copy)] @@ -79,3 +95,27 @@ pub trait ToArchetype { resolver: &crate::PromiseResolver, ) -> crate::PromiseResult>; } + +// --- + +use re_data_store::{LatestAtQuery, RangeQuery}; + +#[derive(Debug)] +pub enum CachedResults { + LatestAt(LatestAtQuery, CachedLatestAtResults), + Range(RangeQuery, CachedRangeResults), +} + +impl From<(LatestAtQuery, CachedLatestAtResults)> for CachedResults { + #[inline] + fn from((query, results): (LatestAtQuery, CachedLatestAtResults)) -> Self { + Self::LatestAt(query, results) + } +} + +impl From<(RangeQuery, CachedRangeResults)> for CachedResults { + #[inline] + fn from((query, results): (RangeQuery, CachedRangeResults)) -> Self { + Self::Range(query, results) + } +} diff --git a/crates/re_query2/src/range/mod.rs b/crates/re_query2/src/range/mod.rs index e4068c918b48..ffb93dd2f720 100644 --- a/crates/re_query2/src/range/mod.rs +++ b/crates/re_query2/src/range/mod.rs @@ -1,5 +1,8 @@ mod query; mod results; -pub use self::query::range; -pub use self::results::{RangeComponentResults, RangeResults}; +pub use self::query::RangeCache; +pub use self::results::{ + CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeData, + CachedRangeResults, +}; diff --git a/crates/re_query2/src/range/query.rs b/crates/re_query2/src/range/query.rs index 5c2c821bd846..f04664b96c25 100644 --- a/crates/re_query2/src/range/query.rs +++ b/crates/re_query2/src/range/query.rs @@ -1,38 +1,393 @@ -use re_data_store::{DataStore, RangeQuery}; -use re_log_types::EntityPath; +use std::sync::Arc; + +use parking_lot::RwLock; + +use re_data_store::{DataStore, RangeQuery, TimeInt}; +use re_log_types::{EntityPath, TimeRange}; use re_types_core::ComponentName; +use re_types_core::SizeBytes; -use crate::RangeResults; +use crate::{ + CacheKey, CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeResults, + Caches, Promise, +}; // --- -/// Queries for the given `component_names` using range semantics. -/// -/// See [`RangeResults`] for more information about how to handle the results. -pub fn range( - store: &DataStore, - query: &RangeQuery, - entity_path: &EntityPath, - component_names: impl IntoIterator, -) -> RangeResults { - re_tracing::profile_function!(entity_path.to_string()); - - let mut results = RangeResults::default(); - - for component_name in component_names { - let data = store.range(query, entity_path, [component_name]).map( - |(data_time, row_id, mut cells)| { - // Unwrap: +impl Caches { + /// Queries for the given `component_names` using range semantics. + /// + /// See [`CachedRangeResults`] for more information about how to handle the results. + /// + /// This is a cached API -- data will be lazily cached upon access. + pub fn range( + &self, + store: &DataStore, + query: &RangeQuery, + entity_path: &EntityPath, + component_names: impl IntoIterator, + ) -> CachedRangeResults { + re_tracing::profile_function!(entity_path.to_string()); + + let mut results = CachedRangeResults::new(query.clone()); + + for component_name in component_names { + let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); + + let cache = Arc::clone( + self.range_per_cache_key + .write() + .entry(key.clone()) + .or_insert_with(|| Arc::new(RwLock::new(RangeCache::new(key.clone())))), + ); + + let mut cache = cache.write(); + cache.handle_pending_invalidation(); + let cached = cache.range(store, query, entity_path, component_name); + results.add(component_name, cached); + } + + results + } +} + +// --- + +/// Caches the results of `Range` queries for a given [`CacheKey`]. +pub struct RangeCache { + /// For debugging purposes. + pub cache_key: CacheKey, + + /// All temporal data, organized by _data_ time. + /// + /// Query time is irrelevant for range queries. + pub per_data_time: CachedRangeComponentResults, + + /// Everything greater than or equal to this timestamp has been asynchronously invalidated. + /// + /// The next time this cache gets queried, it must remove any entry matching this criteria. + /// `None` indicates that there's no pending invalidation. + /// + /// Invalidation is deferred to query time because it is far more efficient that way: the frame + /// time effectively behaves as a natural micro-batching mechanism. + pub pending_invalidation: Option, +} + +impl RangeCache { + #[inline] + pub fn new(cache_key: CacheKey) -> Self { + Self { + cache_key, + per_data_time: CachedRangeComponentResults::default(), + pending_invalidation: None, + } + } +} + +impl std::fmt::Debug for RangeCache { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + cache_key, + per_data_time, + pending_invalidation: _, + } = self; + + let mut strings = Vec::new(); + + let mut data_time_min = TimeInt::MAX; + let mut data_time_max = TimeInt::MIN; + + { + let per_data_time = per_data_time.read(); + + let per_data_time_indices = &per_data_time.indices; + if let Some(time_front) = per_data_time_indices.front().map(|(t, _)| *t) { + data_time_min = TimeInt::min(data_time_min, time_front); + } + if let Some(time_back) = per_data_time_indices.back().map(|(t, _)| *t) { + data_time_max = TimeInt::max(data_time_max, time_back); + } + } + + strings.push(format!( + "{} ({})", + cache_key + .timeline + .typ() + .format_range_utc(TimeRange::new(data_time_min, data_time_max)), + re_format::format_bytes(per_data_time.total_size_bytes() as _), + )); + + if strings.is_empty() { + return f.write_str(""); + } + + f.write_str(&strings.join("\n").replace("\n\n", "\n")) + } +} + +impl SizeBytes for RangeCache { + #[inline] + fn heap_size_bytes(&self) -> u64 { + let Self { + cache_key, + per_data_time, + pending_invalidation, + } = self; + + cache_key.heap_size_bytes() + + per_data_time.heap_size_bytes() + + pending_invalidation.heap_size_bytes() + } +} + +impl RangeCache { + /// Queries cached range data for a single component. + pub fn range( + &mut self, + store: &DataStore, + query: &RangeQuery, + entity_path: &EntityPath, + component_name: ComponentName, + ) -> CachedRangeComponentResults { + re_tracing::profile_scope!("range", format!("{query:?}")); + + let RangeCache { + cache_key: _, + per_data_time, + pending_invalidation: _, + } = self; + + let mut per_data_time = per_data_time.write(); + + let query_front = per_data_time.compute_front_query(query); + if let Some(query_front) = query_front.as_ref() { + re_tracing::profile_scope!("front"); + + for (data_time, row_id, mut cells) in + store.range(query_front, entity_path, [component_name]) + { + // Soundness: // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null - let cell = cells[0].take().unwrap(); + let Some(cell) = cells[0].take() else { + debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); + continue; + }; + + per_data_time + .promises_front + .push(((data_time, row_id), Promise::new(cell))); + per_data_time + .promises_front + .sort_by_key(|(index, _)| *index); + } + } - ((data_time, row_id), cell) - }, - ); + if let Some(query_back) = per_data_time.compute_back_query(query, query_front.as_ref()) { + re_tracing::profile_scope!("back"); - results.add(component_name, data); + for (data_time, row_id, mut cells) in store + .range(&query_back, entity_path, [component_name]) + // If there's static data to be found, the front query will take care of it already. + .filter(|(data_time, _, _)| !data_time.is_static()) + { + // Soundness: + // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` + // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null + let Some(cell) = cells[0].take() else { + debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); + continue; + }; + + per_data_time + .promises_back + .push(((data_time, row_id), Promise::new(cell))); + per_data_time.promises_back.sort_by_key(|(index, _)| *index); + } + } + + per_data_time.sanity_check(); + drop(per_data_time); + + self.per_data_time.clone_at(query.range()) + } + + pub fn handle_pending_invalidation(&mut self) { + re_tracing::profile_function!(); + + let Self { + cache_key: _, + per_data_time, + pending_invalidation, + } = self; + + let Some(pending_invalidation) = pending_invalidation.take() else { + return; + }; + + per_data_time.write().truncate_at_time(pending_invalidation); + } +} + +// --- + +impl CachedRangeComponentResultsInner { + /// How many _indices_ across this entire cache? + #[inline] + pub fn num_indices(&self) -> u64 { + self.indices.len() as _ + } + + /// How many _instances_ across this entire cache? + #[inline] + pub fn num_instances(&self) -> u64 { + self.cached_dense + .as_ref() + .map_or(0u64, |cached| cached.dyn_num_values() as _) + } + + /// Given a `query`, returns N reduced queries that are sufficient to fill the missing data + /// on both the front & back sides of the cache. + #[inline] + pub fn compute_queries(&self, query: &RangeQuery) -> impl Iterator { + let front = self.compute_front_query(query); + let back = self.compute_back_query(query, front.as_ref()); + front.into_iter().chain(back) } - results + /// Given a `query`, returns a reduced query that is sufficient to fill the missing data + /// on the front side of the cache, or `None` if all the necessary data is already + /// cached. + pub fn compute_front_query(&self, query: &RangeQuery) -> Option { + let mut reduced_query = query.clone(); + + // If nothing has been cached already, then we just want to query everything. + if self.indices.is_empty() + && self.promises_front.is_empty() + && self.promises_back.is_empty() + { + return Some(reduced_query); + } + + // If the cache contains static data, then there's no point in querying anything else since + // static data overrides everything anyway. + if self + .indices + .front() + .map_or(false, |(data_time, _)| data_time.is_static()) + { + return None; + } + + // Otherwise, query for what's missing on the front-side of the cache, while making sure to + // take pending promises into account! + // + // Keep in mind: it is not possible for the cache to contain only part of a given + // timestamp. All entries for a given timestamp are loaded and invalidated atomically, + // whether it's promises or already resolved entries. + + let pending_front_min = self + .promises_front + .first() + .map_or(TimeInt::MAX.as_i64(), |((t, _), _)| { + t.as_i64().saturating_sub(1) + }); + + if let Some(time_range) = self.time_range() { + let time_range_min = i64::min( + time_range.min().as_i64().saturating_sub(1), + pending_front_min, + ); + reduced_query + .range + .set_max(i64::min(reduced_query.range.max().as_i64(), time_range_min)); + } else { + reduced_query.range.set_max(i64::min( + reduced_query.range.max().as_i64(), + pending_front_min, + )); + } + + if reduced_query.range.max() < reduced_query.range.min() { + return None; + } + + Some(reduced_query) + } + + /// Given a `query`, returns a reduced query that is sufficient to fill the missing data + /// on the back side of the cache, or `None` if all the necessary data is already + /// cached. + pub fn compute_back_query( + &self, + query: &RangeQuery, + query_front: Option<&RangeQuery>, + ) -> Option { + let mut reduced_query = query.clone(); + + // If nothing has been cached already, then the front query is already going to take care + // of everything. + if self.indices.is_empty() + && self.promises_front.is_empty() + && self.promises_back.is_empty() + { + return None; + } + + // If the cache contains static data, then there's no point in querying anything else since + // static data overrides everything anyway. + if self + .indices + .front() + .map_or(false, |(data_time, _)| data_time.is_static()) + { + return None; + } + + // Otherwise, query for what's missing on the back-side of the cache, while making sure to + // take pending promises into account! + // + // Keep in mind: it is not possible for the cache to contain only part of a given + // timestamp. All entries for a given timestamp are loaded and invalidated atomically, + // whether it's promises or already resolved entries. + + let pending_back_max = self + .promises_back + .last() + .map_or(TimeInt::MIN.as_i64(), |((t, _), _)| { + t.as_i64().saturating_add(1) + }); + + if let Some(time_range) = self.time_range() { + let time_range_max = i64::max( + time_range.max().as_i64().saturating_add(1), + pending_back_max, + ); + reduced_query + .range + .set_min(i64::max(reduced_query.range.min().as_i64(), time_range_max)); + } else { + reduced_query.range.set_min(i64::max( + reduced_query.range.min().as_i64(), + pending_back_max, + )); + } + + // Back query should never overlap with the front query. + // Reminder: time ranges are all inclusive. + if let Some(query_front) = query_front { + let front_max_plus_one = query_front.range().max().as_i64().saturating_add(1); + let back_min = reduced_query.range().min().as_i64(); + reduced_query + .range + .set_min(i64::max(back_min, front_max_plus_one)); + } + + if reduced_query.range.max() < reduced_query.range.min() { + return None; + } + + Some(reduced_query) + } } diff --git a/crates/re_query2/src/range/results.rs b/crates/re_query2/src/range/results.rs index 2cfe48751a7d..5f9bc83e6255 100644 --- a/crates/re_query2/src/range/results.rs +++ b/crates/re_query2/src/range/results.rs @@ -1,45 +1,67 @@ +use std::{ + cell::RefCell, + collections::VecDeque, + ops::Range, + sync::{Arc, OnceLock}, +}; + use nohash_hasher::IntMap; -use re_log_types::{DataCell, RowId, TimeInt}; -use re_types_core::ComponentName; -use re_types_core::{Component, DeserializationError, DeserializationResult}; -use crate::{Promise, PromiseResolver, PromiseResult}; +use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use re_data_store::RangeQuery; +use re_log_types::{RowId, TimeInt, TimeRange}; +use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes}; + +use crate::{ + CachedLatestAtComponentResults, ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, + PromiseResult, +}; // --- -/// Raw results for a range query. +/// Cached results for a range query. /// -/// The data is neither deserialized, nor resolved/converted. -/// It it the raw [`DataCell`]s, straight from our datastore. +/// The data is both deserialized and resolved/converted. /// -/// Use [`RangeResults::get`], [`RangeResults::get_required`] and [`RangeResults::get_or_empty`] -/// in order to access the raw results for each individual component. -#[derive(Default, Debug, Clone)] -pub struct RangeResults { - /// Raw results for each individual component. - pub components: IntMap, +/// Use [`CachedRangeResults::get`], [`CachedRangeResults::get_required`] and +/// [`CachedRangeResults::get_or_empty`] in order to access the results for each individual component. +#[derive(Debug)] +pub struct CachedRangeResults { + pub query: RangeQuery, + pub components: IntMap, } -impl RangeResults { +impl CachedRangeResults { + #[inline] + pub(crate) fn new(query: RangeQuery) -> Self { + Self { + query, + components: Default::default(), + } + } + #[inline] pub fn contains(&self, component_name: impl Into) -> bool { self.components.contains_key(&component_name.into()) } - /// Returns the [`RangeComponentResults`] for the specified `component_name`. + /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. #[inline] - pub fn get(&self, component_name: impl Into) -> Option<&RangeComponentResults> { + pub fn get( + &self, + component_name: impl Into, + ) -> Option<&CachedRangeComponentResults> { self.components.get(&component_name.into()) } - /// Returns the [`RangeComponentResults`] for the specified `component_name`. + /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. /// /// Returns an error if the component is not present. #[inline] pub fn get_required( &self, component_name: impl Into, - ) -> crate::Result<&RangeComponentResults> { + ) -> crate::Result<&CachedRangeComponentResults> { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { Ok(component) @@ -52,153 +74,746 @@ impl RangeResults { } } - /// Returns the [`RangeComponentResults`] for the specified `component_name`. + /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. /// /// Returns empty results if the component is not present. #[inline] - pub fn get_or_empty(&self, component_name: impl Into) -> &RangeComponentResults { + pub fn get_or_empty( + &self, + component_name: impl Into, + ) -> &CachedRangeComponentResults { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { component } else { - static DEFAULT: RangeComponentResults = RangeComponentResults::empty(); - &DEFAULT + CachedRangeComponentResults::empty() } } } -impl RangeResults { +impl CachedRangeResults { #[doc(hidden)] #[inline] - pub fn add( - &mut self, - component_name: ComponentName, - data: impl Iterator, - ) { - let (indices, cells): (Vec<_>, Vec<_>) = data - .map(|(index, cell)| (index, Promise::new(cell))) - .unzip(); + pub fn add(&mut self, component_name: ComponentName, cached: CachedRangeComponentResults) { + self.components.insert(component_name, cached); + } +} - let results = RangeComponentResults { - indices, - promises: cells, - }; - results.sanity_check(); +// --- + +thread_local! { + /// Keeps track of reentrancy counts for the current thread. + /// + /// Used to detect and prevent potential deadlocks when using the cached APIs in work-stealing + /// environments such as Rayon. + static REENTERING: RefCell = const { RefCell::new(0) }; +} + +/// Lazily cached results for a particular component when using a cached range query. +#[derive(Debug)] +pub struct CachedRangeComponentResults { + /// The [`TimeRange`] of the query that was used in order to retrieve these results in the + /// first place. + /// + /// The "original" copy in the cache just stores [`TimeRange::EMPTY`]. It's meaningless. + pub(crate) time_range: TimeRange, - self.components.insert(component_name, results); + pub(crate) inner: Arc>, +} + +impl CachedRangeComponentResults { + /// Clones the results while making sure to stamp them with the [`TimeRange`] of the associated query. + #[inline] + pub(crate) fn clone_at(&self, time_range: TimeRange) -> Self { + Self { + time_range, + inner: self.inner.clone(), + } } } -// --- +impl CachedRangeComponentResults { + #[inline] + pub fn empty() -> &'static Self { + static EMPTY: OnceLock = OnceLock::new(); + EMPTY.get_or_init(CachedRangeComponentResults::default) + } +} -/// Uncached results for a particular component when using a range query. -#[derive(Debug, Clone)] -pub struct RangeComponentResults { - pub indices: Vec<(TimeInt, RowId)>, - pub promises: Vec, +impl re_types_core::SizeBytes for CachedRangeComponentResults { + #[inline] + fn heap_size_bytes(&self) -> u64 { + // NOTE: it's all on the heap past this point. + self.inner.read_recursive().total_size_bytes() + } } -impl Default for RangeComponentResults { +impl Default for CachedRangeComponentResults { #[inline] fn default() -> Self { - Self::empty() + Self { + time_range: TimeRange::EMPTY, + inner: Arc::new(RwLock::new(CachedRangeComponentResultsInner::empty())), + } } } -impl RangeComponentResults { +impl std::ops::Deref for CachedRangeComponentResults { + type Target = RwLock; + #[inline] - pub const fn empty() -> Self { - Self { - indices: Vec::new(), - promises: Vec::new(), + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +/// Helper datastructure to make it possible to convert latest-at results into ranged results. +#[derive(Debug)] +enum Indices<'a> { + Owned(VecDeque<(TimeInt, RowId)>), + Cached(MappedRwLockReadGuard<'a, VecDeque<(TimeInt, RowId)>>), +} + +impl<'a> std::ops::Deref for Indices<'a> { + type Target = VecDeque<(TimeInt, RowId)>; + + #[inline] + fn deref(&self) -> &Self::Target { + match self { + Indices::Owned(data) => data, + Indices::Cached(data) => data, } } +} + +/// Helper datastructure to make it possible to convert latest-at results into ranged results. +enum Data<'a, T> { + Owned(Arc), + Cached(MappedRwLockReadGuard<'a, FlatVecDeque>), +} + +impl<'a, T: 'static> std::ops::Deref for Data<'a, T> { + type Target = FlatVecDeque; - /// No-op in release. #[inline] - pub fn sanity_check(&self) { - let Self { - indices, - promises: cells, - } = self; - if cfg!(debug_assertions) { - assert_eq!(indices.len(), cells.len()); + fn deref(&self) -> &Self::Target { + match self { + Data::Owned(data) => { + // Unwrap: only way to instantiate a `Data` is via the `From` impl below which we + // fully control. + data.as_any().downcast_ref().unwrap() + } + Data::Cached(data) => data, } } } -impl RangeComponentResults { +pub struct CachedRangeData<'a, T> { + // NOTE: Options so we can represent an empty result without having to somehow conjure a mutex + // guard out of thin air. + // + // TODO(Amanieu/parking_lot#289): we need two distinct mapped guards because it's + // impossible to return an owned type in a `parking_lot` guard. + // See . + // indices: Option>>, + indices: Option>, + data: Option>, + + time_range: TimeRange, + front_status: PromiseResult<()>, + back_status: PromiseResult<()>, + + /// Keeps track of reentrancy counts for the current thread. + /// + /// Used to detect and prevent potential deadlocks when using the cached APIs in work-stealing + /// environments such as Rayon. + reentering: &'static std::thread::LocalKey>, +} + +impl<'a, C: Component> CachedRangeData<'a, C> { + /// Useful to abstract over latest-at and ranged results. #[inline] - pub fn indices(&self) -> &[(TimeInt, RowId)] { - &self.indices + pub fn from_latest_at( + resolver: &PromiseResolver, + results: &'a CachedLatestAtComponentResults, + ) -> Self { + let CachedLatestAtComponentResults { + index, + promise: _, + cached_dense, + } = results; + + let status = results.to_dense::(resolver).map(|_| ()); + + Self { + indices: Some(Indices::Owned(vec![*index].into())), + data: cached_dense.get().map(|data| Data::Owned(Arc::clone(data))), + time_range: TimeRange::new(index.0, index.0), + front_status: status.clone(), + back_status: status, + reentering: &REENTERING, + } } +} +impl<'a, T> Drop for CachedRangeData<'a, T> { #[inline] - pub fn iter_indices(&self) -> impl ExactSizeIterator + '_ { - self.indices.iter().copied() + fn drop(&mut self) { + self.reentering + .with_borrow_mut(|reentering| *reentering = reentering.saturating_sub(1)); } +} - /// Returns the component data as a vector of dense vectors. +impl<'a, T: 'static> CachedRangeData<'a, T> { + /// Returns the current status on both ends of the range. /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. + /// E.g. it is possible that the front-side of the range is still waiting for pending data while + /// the back-side has been fully loaded. + #[inline] + pub fn status(&self) -> (PromiseResult<()>, PromiseResult<()>) { + (self.front_status.clone(), self.back_status.clone()) + } + #[inline] - pub fn to_dense( + pub fn range_indices( &self, - resolver: &PromiseResolver, - ) -> Vec>>> { - self.promises - .iter() - .map(|cell| { - resolver.resolve(cell).map(|cell| { - cell.try_to_native() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) - }) - .collect() + entry_range: Range, + ) -> impl Iterator { + let indices = match self.indices.as_ref() { + Some(indices) => itertools::Either::Left(indices.range(entry_range)), + None => itertools::Either::Right(std::iter::empty()), + }; + indices + } + + #[inline] + pub fn range_data(&self, entry_range: Range) -> impl Iterator { + match self.data.as_ref() { + Some(indices) => itertools::Either::Left(indices.range(entry_range)), + None => itertools::Either::Right(std::iter::empty()), + } } - /// Returns the component data as an iterator of dense vectors. + /// Range both the indices and data by zipping them together. /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. + /// Useful for time-based joins (`range_zip`). #[inline] - pub fn iter_dense( - &self, - resolver: &PromiseResolver, - ) -> impl ExactSizeIterator>>> { - self.to_dense(resolver).into_iter() + pub fn range_indexed(&self) -> impl Iterator { + let entry_range = self.entry_range(); + itertools::izip!( + self.range_indices(entry_range.clone()), + self.range_data(entry_range) + ) } - /// Returns the component data as a vector of sparse vectors. + /// Returns the index range that corresponds to the specified `time_range`. + /// + /// Use the returned range with one of the range iteration methods: + /// - [`Self::range_indices`] + /// - [`Self::range_data`] + /// - [`Self::range_indexed`] + /// + /// Make sure that the bucket hasn't been modified in-between! + /// + /// This is `O(2*log(n))`, so make sure to clone the returned range rather than calling this + /// multiple times. + #[inline] + pub fn entry_range(&self) -> Range { + let Some(indices) = self.indices.as_ref() else { + return 0..0; + }; + + // If there's any static data cached, make sure to look for it explicitly. + // + // Remember: `TimeRange`s can never contain `TimeInt::STATIC`. + let static_override = if matches!(indices.front(), Some((TimeInt::STATIC, _))) { + TimeInt::STATIC + } else { + TimeInt::MAX + }; + + let start_index = indices.partition_point(|(data_time, _)| { + *data_time < TimeInt::min(self.time_range.min(), static_override) + }); + let end_index = indices.partition_point(|(data_time, _)| { + *data_time <= TimeInt::min(self.time_range.max(), static_override) + }); + + start_index..end_index + } +} + +impl CachedRangeComponentResults { + /// Returns the component data as a dense vector. + /// + /// Returns an error if the component is missing or cannot be deserialized. /// /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of /// deserializing the data into a single one, if you don't need the extra flexibility. #[inline] - pub fn to_sparse( - &self, - resolver: &PromiseResolver, - ) -> Vec>>>> { - self.promises - .iter() - .map(|cell| { - resolver.resolve(cell).map(|cell| { - cell.try_to_native_opt() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) + pub fn to_dense(&self, resolver: &PromiseResolver) -> CachedRangeData<'_, C> { + // It's tracing the deserialization of an entire range query at once -- it's fine. + re_tracing::profile_function!(); + + // --- Step 1: try and upsert pending data (write lock) --- + + REENTERING.with_borrow_mut(|reentering| *reentering = reentering.saturating_add(1)); + + // Manufactured empty result. + if self.time_range == TimeRange::EMPTY { + return CachedRangeData { + indices: None, + data: None, + time_range: TimeRange::EMPTY, + front_status: PromiseResult::Ready(()), + back_status: PromiseResult::Ready(()), + reentering: &REENTERING, + }; + } + + let mut results = if let Some(results) = self.inner.try_write() { + // The lock was free to grab, nothing else to worry about. + Some(results) + } else { + REENTERING.with_borrow_mut(|reentering| { + if *reentering > 1 { + // The lock is busy, and at least one of the lock holders is the current thread from a + // previous stack frame. + // + // Return `None` so that we skip straight to the read-only part of the operation. + // All the data will be there already, since the previous stack frame already + // took care of upserting it. + None + } else { + // The lock is busy, but it is not held by the current thread. + // Just block until it gets released. + Some(self.inner.write()) + } }) - .collect() + }; + + if let Some(results) = &mut results { + // NOTE: This is just a lazy initialization of the underlying deque, because we + // just now finally know the expected type! + if results.cached_dense.is_none() { + results.cached_dense = Some(Box::new(FlatVecDeque::::new())); + } + + if !results.promises_front.is_empty() { + re_tracing::profile_scope!("front"); + + let mut resolved_indices = Vec::with_capacity(results.promises_front.len()); + let mut resolved_data = Vec::with_capacity(results.promises_front.len()); + + // Pop the promises from the end so that if we encounter one that has yet to be + // resolved, we can stop right there and know we have a contiguous range of data + // available up to that point in time. + // + // Reminder: promises are sorted in ascending index order. + while let Some(((data_time, row_id), promise)) = results.promises_front.pop() { + let data = match resolver.resolve(&promise) { + PromiseResult::Pending => { + results.front_status = (data_time, PromiseResult::Pending); + break; + } + PromiseResult::Error(err) => { + results.front_status = (data_time, PromiseResult::Error(err)); + break; + } + PromiseResult::Ready(cell) => { + results.front_status = (data_time, PromiseResult::Ready(())); + match cell + .try_to_native::() + .map_err(|err| DeserializationError::DataCellError(err.to_string())) + { + Ok(data) => data, + Err(err) => { + re_log::error!(%err, component=%C::name(), "data deserialization failed -- skipping"); + continue; + } + } + } + }; + + resolved_indices.push((data_time, row_id)); + resolved_data.push(data); + } + + // We resolved the promises in reversed order, so reverse the results back. + resolved_indices.reverse(); + resolved_data.reverse(); + + let results_indices = std::mem::take(&mut results.indices); + results.indices = resolved_indices + .into_iter() + .chain(results_indices) + .collect(); + + let resolved_data = FlatVecDeque::from_vecs(resolved_data); + // Unwraps: the deque is created when entering this function -- we know it's there + // and we know its type. + let cached_dense = results + .cached_dense + .as_mut() + .unwrap() + .as_any_mut() + .downcast_mut::>() + .unwrap(); + cached_dense.push_front_deque(resolved_data); + } + + if !results.promises_back.is_empty() { + re_tracing::profile_scope!("back"); + + let mut resolved_indices = Vec::with_capacity(results.promises_back.len()); + let mut resolved_data = Vec::with_capacity(results.promises_back.len()); + + // Reverse the promises first so we can pop() from the back. + // It's fine, this is a one-time operation in the successful case, and it's extremely fast to do. + // See below why. + // + // Reminder: promises are sorted in ascending index order. + results.promises_back.reverse(); + + // Pop the promises from the end so that if we encounter one that has yet to be + // resolved, we can stop right there and know we have a contiguous range of data + // available up to that point in time. + while let Some(((data_time, index), promise)) = results.promises_back.pop() { + let data = match resolver.resolve(&promise) { + PromiseResult::Pending => { + results.back_status = (data_time, PromiseResult::Pending); + break; + } + PromiseResult::Error(err) => { + results.back_status = (data_time, PromiseResult::Error(err)); + break; + } + PromiseResult::Ready(cell) => { + results.front_status = (data_time, PromiseResult::Ready(())); + match cell + .try_to_native::() + .map_err(|err| DeserializationError::DataCellError(err.to_string())) + { + Ok(data) => data, + Err(err) => { + re_log::error!(%err, "data deserialization failed -- skipping"); + continue; + } + } + } + }; + + resolved_indices.push((data_time, index)); + resolved_data.push(data); + } + + // Reverse our reversal. + results.promises_back.reverse(); + + results.indices.extend(resolved_indices); + + let resolved_data = FlatVecDeque::from_vecs(resolved_data); + // Unwraps: the deque is created when entering this function -- we know it's there + // and we know its type. + let cached_dense = results + .cached_dense + .as_mut() + .unwrap() + .as_any_mut() + .downcast_mut::>() + .unwrap(); + cached_dense.push_back_deque(resolved_data); + } + + results.sanity_check(); + } + + // --- Step 2: fetch cached data (read lock) --- + + let results = if let Some(results) = results { + RwLockWriteGuard::downgrade(results) + } else { + // # Multithreading semantics + // + // We need the reentrant lock because query contexts (i.e. space views) generally run on a + // work-stealing thread-pool and might swap a task on one thread with another task on the + // same thread, where both tasks happen to query the same exact data (e.g. cloned space views). + // + // See `REENTERING` comments above for more details. + self.read_recursive() + }; + + let front_status = { + let (results_front_time, results_front_status) = &results.front_status; + let query_front_time = self.time_range.min(); + if query_front_time < *results_front_time { + // If the query covers a larger time span on its front-side than the resulting data, then + // we should forward the status of the resulting data so the caller can know why it's + // been cropped off. + results_front_status.clone() + } else { + PromiseResult::Ready(()) + } + }; + let back_status = { + let (results_back_time, results_back_status) = &results.back_status; + let query_back_time = self.time_range.max(); + if query_back_time > *results_back_time { + // If the query covers a larger time span on its back-side than the resulting data, then + // we should forward the status of the resulting data so the caller can know why it's + // been cropped off. + results_back_status.clone() + } else { + PromiseResult::Ready(()) + } + }; + + // TODO(Amanieu/parking_lot#289): we need two distinct mapped guards because it's + // impossible to return an owned type in a `parking_lot` guard. + // See . + let indices = RwLockReadGuard::map(results, |results| &results.indices); + let data = RwLockReadGuard::map(self.inner.read_recursive(), |results| { + // Unwraps: the data is created when entering this function -- we know it's there + // and we know its type. + results + .cached_dense + .as_ref() + .unwrap() + .as_any() + .downcast_ref::>() + .unwrap() + }); + + CachedRangeData { + indices: Some(Indices::Cached(indices)), + data: Some(Data::Cached(data)), + time_range: self.time_range, + front_status, + back_status, + reentering: &REENTERING, + } } +} + +// --- + +/// Lazily cached results for a particular component when using a cached range query. +pub struct CachedRangeComponentResultsInner { + pub(crate) indices: VecDeque<(TimeInt, RowId)>, - /// Returns the component data as an iterator of sparse vectors. + /// All the pending promises that must resolved in order to fill the missing data on the + /// front-side of the ringbuffer (i.e. further back in time). /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. + /// Always sorted in ascending index order ([`TimeInt`] + [`RowId`] pair). + pub(crate) promises_front: Vec<((TimeInt, RowId), Promise)>, + + /// All the pending promises that must resolved in order to fill the missing data on the + /// back-side of the ringbuffer (i.e. the most recent data). + /// + /// Always sorted in ascending index order ([`TimeInt`] + [`RowId`] pair). + pub(crate) promises_back: Vec<((TimeInt, RowId), Promise)>, + + /// Keeps track of the status of the data on the front-side of the cache. + pub(crate) front_status: (TimeInt, PromiseResult<()>), + + /// Keeps track of the status of the data on the back-side of the cache. + pub(crate) back_status: (TimeInt, PromiseResult<()>), + + /// The resolved, converted, deserialized dense data. + /// + /// This has to be option because we have no way of initializing the underlying trait object + /// until we know what the actual native type that the caller expects is. + pub(crate) cached_dense: Option>, +} + +impl SizeBytes for CachedRangeComponentResultsInner { #[inline] - pub fn iter_sparse( - &self, - resolver: &PromiseResolver, - ) -> impl ExactSizeIterator>>>> { - self.to_sparse(resolver).into_iter() + fn heap_size_bytes(&self) -> u64 { + let Self { + indices, + promises_front, + promises_back, + front_status: _, + back_status: _, + cached_dense, + } = self; + + indices.total_size_bytes() + + promises_front.total_size_bytes() + + promises_back.total_size_bytes() + + cached_dense + .as_ref() + .map_or(0, |data| data.dyn_total_size_bytes()) + } +} + +impl std::fmt::Debug for CachedRangeComponentResultsInner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + indices, + promises_front: _, + promises_back: _, + front_status: _, + back_status: _, + cached_dense: _, // we can't, we don't know the type + } = self; + + if indices.is_empty() { + f.write_str("") + } else { + // Unwrap: checked above. + let index_start = indices.front().unwrap(); + let index_end = indices.back().unwrap(); + f.write_fmt(format_args!( + "[{:?}#{} .. {:?}#{}] {}", + index_start.0, + index_start.1, + index_end.0, + index_end.1, + re_format::format_bytes(self.total_size_bytes() as _) + )) + } + } +} + +impl CachedRangeComponentResultsInner { + #[inline] + pub const fn empty() -> Self { + Self { + indices: VecDeque::new(), + promises_front: Vec::new(), + promises_back: Vec::new(), + front_status: (TimeInt::MIN, PromiseResult::Ready(())), + back_status: (TimeInt::MAX, PromiseResult::Ready(())), + cached_dense: None, + } + } + + /// No-op in release. + #[inline] + pub fn sanity_check(&self) { + if !cfg!(debug_assertions) { + return; + } + + let Self { + indices, + promises_front, + promises_back, + front_status: _, + back_status: _, + cached_dense, + } = self; + + assert!( + promises_front.windows(2).all(|promises| { + let index_left = promises[0].0; + let index_right = promises[1].0; + index_left <= index_right + }), + "front promises must always be sorted in ascending index order" + ); + if let (Some(p_index), Some(i_index)) = ( + promises_front.last().map(|(index, _)| index), + indices.front(), + ) { + assert!( + p_index < i_index, + "the rightmost front promise must have an index smaller than the leftmost data index ({p_index:?} < {i_index:?})", + ); + } + + assert!( + promises_back.windows(2).all(|promises| { + let index_left = promises[0].0; + let index_right = promises[1].0; + index_left <= index_right + }), + "back promises must always be sorted in ascending index order" + ); + if let (Some(p_index), Some(i_index)) = + (promises_back.last().map(|(index, _)| index), indices.back()) + { + assert!( + i_index < p_index, + "the leftmost back promise must have an index larger than the rightmost data index ({i_index:?} < {p_index:?})", + ); + } + + if let Some(dense) = cached_dense.as_ref() { + assert_eq!(indices.len(), dense.dyn_num_entries()); + } + } + + /// Returns the time range covered by the cached data. + /// + /// Reminder: [`TimeInt::STATIC`] is never included in [`TimeRange`]s. + #[inline] + pub fn time_range(&self) -> Option { + let first_time = self.indices.front().map(|(t, _)| *t)?; + let last_time = self.indices.back().map(|(t, _)| *t)?; + Some(TimeRange::new(first_time, last_time)) + } + + #[inline] + pub fn contains_data_time(&self, data_time: TimeInt) -> bool { + let first_time = self.indices.front().map_or(&TimeInt::MAX, |(t, _)| t); + let last_time = self.indices.back().map_or(&TimeInt::MIN, |(t, _)| t); + *first_time <= data_time && data_time <= *last_time + } + + /// Removes everything from the bucket that corresponds to a time equal or greater than the + /// specified `threshold`. + /// + /// Returns the number of bytes removed. + #[inline] + pub fn truncate_at_time(&mut self, threshold: TimeInt) { + re_tracing::profile_function!(); + + let time_range = self.time_range(); + + let Self { + indices, + promises_front, + promises_back, + front_status, + back_status, + cached_dense, + } = self; + + if front_status.0 >= threshold { + let time_min = time_range.map_or(TimeInt::MIN, |range| range.min()); + *front_status = (time_min, PromiseResult::Ready(())); + } + if back_status.0 >= threshold { + let time_max = time_range.map_or(TimeInt::MAX, |range| range.max()); + *back_status = (time_max, PromiseResult::Ready(())); + } + + // NOTE: promises are kept ascendingly sorted by index + { + let threshold_idx = + promises_front.partition_point(|((data_time, _), _)| *data_time < threshold); + promises_front.truncate(threshold_idx); + + let threshold_idx = + promises_back.partition_point(|((data_time, _), _)| *data_time < threshold); + promises_back.truncate(threshold_idx); + } + + let threshold_idx = indices.partition_point(|(data_time, _)| data_time < &threshold); + { + indices.truncate(threshold_idx); + if let Some(data) = cached_dense { + data.dyn_truncate(threshold_idx); + } + } + + self.sanity_check(); + } + + #[inline] + pub fn clear(&mut self) { + *self = Self::empty(); } } diff --git a/crates/re_query2/src/range_zip/generated.rs b/crates/re_query2/src/range_zip/generated.rs index c916479d39f2..2b575176b198 100644 --- a/crates/re_query2/src/range_zip/generated.rs +++ b/crates/re_query2/src/range_zip/generated.rs @@ -1,4 +1,4 @@ -// This file was generated using `cargo r -p re_query2 --all-features --bin range_zip`. +// This file was generated using `cargo r -p crate --all-features --bin range_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query2/tests/latest_at.rs b/crates/re_query2/tests/latest_at.rs index c5c4effde420..c91dc3edeeb2 100644 --- a/crates/re_query2/tests/latest_at.rs +++ b/crates/re_query2/tests/latest_at.rs @@ -1,217 +1,528 @@ -use re_data_store::DataStore; -use re_log_types::example_components::{MyColor, MyPoint, MyPoints}; -use re_log_types::{build_frame_nr, DataRow, RowId, TimePoint}; +//! Contains: +//! - A 1:1 port of the tests in `crates/re_query/tests/archetype_query_tests.rs`, with caching enabled. +//! - Invalidation tests. + +use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; +use re_log_types::{ + build_frame_nr, + example_components::{MyColor, MyPoint, MyPoints}, + DataRow, EntityPath, RowId, TimePoint, +}; +use re_query2::Caches; use re_query2::PromiseResolver; -use re_types::components::InstanceKey; -use re_types::{Archetype as _, ComponentNameSet}; -use re_types_core::Loggable as _; +use re_types::Archetype as _; +use re_types_core::{components::InstanceKey, Loggable as _}; // --- -#[test] -fn simple_query() -> anyhow::Result<()> { - let resolver = PromiseResolver::default(); - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - let results = re_query2::latest_at( - &store, - &timeline_query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), - ); - - // We expect this to generate the following `DataFrame` - // ┌─────────────┬────────────┐ - // │ point ┆ color │ - // │ --- ┆ --- │ - // │ struct[2] ┆ u32 │ - // ╞═════════════╪════════════╡ - // │ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ 4278190080 │ - // └─────────────┴────────────┘ - - { - let expected_components: ComponentNameSet = - [MyPoint::name(), MyColor::name()].into_iter().collect(); - let got_components: ComponentNameSet = results.components.keys().copied().collect(); - similar_asserts::assert_eq!(expected_components, got_components); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = results.get_required(MyPoint::name())?; - let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - - let colors = results.get_or_empty(MyColor::name()); - let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} - -#[test] -fn static_query() -> anyhow::Result<()> { - let resolver = PromiseResolver::default(); - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, TimePoint::default(), 2, colors)?; - store.insert_row(&row)?; - - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - let results = re_query2::latest_at( - &store, - &timeline_query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), - ); - - // We expect this to generate the following `DataFrame` - // ┌───────────┬────────────┐ - // │ point ┆ color │ - // │ --- ┆ --- │ - // │ struct[2] ┆ u32 │ - // ╞═══════════╪════════════╡ - // │ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ 4278190080 │ - // └───────────┴────────────┘ - - { - let expected_components: ComponentNameSet = - [MyPoint::name(), MyColor::name()].into_iter().collect(); - let got_components: ComponentNameSet = results.components.keys().copied().collect(); - similar_asserts::assert_eq!(expected_components, got_components); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = results.get_required(MyPoint::name())?; - let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - - let colors = results.get_or_empty(MyColor::name()); - let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} - -#[test] -fn no_instance_join_query() -> anyhow::Result<()> { - let resolver = PromiseResolver::default(); - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors)?; - store.insert_row(&row)?; - - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - let results = re_query2::latest_at( - &store, - &timeline_query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), - ); - - // We expect this to generate the following `DataFrame` - // ┌───────────┬────────────┐ - // │ point ┆ color │ - // │ --- ┆ --- │ - // │ struct[2] ┆ u32 │ - // ╞═══════════╪════════════╡ - // │ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ 16711680 │ - // └───────────┴────────────┘ - - { - let expected_components: ComponentNameSet = - [MyPoint::name(), MyColor::name()].into_iter().collect(); - let got_components: ComponentNameSet = results.components.keys().copied().collect(); - similar_asserts::assert_eq!(expected_components, got_components); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(0, 255, 0)), - ]; - - let points = results.get_required(MyPoint::name())?; - let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - - let colors = results.get_or_empty(MyColor::name()); - let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} +// TODO + +// #[test] +// fn simple_query() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path = "point"; +// let timepoint = [build_frame_nr(123)]; +// +// // Create some positions with implicit instances +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// // Assign one of them a color with an explicit instance +// let color_instances = vec![InstanceKey(1)]; +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = DataRow::from_cells2_sized( +// RowId::new(), +// entity_path, +// timepoint, +// 1, +// (color_instances, colors), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// } +// +// #[test] +// fn static_query() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path = "point"; +// let timepoint = [build_frame_nr(123)]; +// +// // Create some positions with implicit instances +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// // Assign one of them a color with an explicit instance.. statically! +// let color_instances = vec![InstanceKey(1)]; +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = DataRow::from_cells2_sized( +// RowId::new(), +// entity_path, +// TimePoint::default(), +// 1, +// (color_instances, colors), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// } +// +// #[test] +// fn no_instance_join_query() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path = "point"; +// let timepoint = [build_frame_nr(123)]; +// +// // Create some positions with an implicit instance +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// // Assign them colors with explicit instances +// let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; +// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// } +// +// #[test] +// fn missing_column_join_query() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path = "point"; +// let timepoint = [build_frame_nr(123)]; +// +// // Create some positions with an implicit instance +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// } +// +// #[test] +// fn splatted_query() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path = "point"; +// let timepoint = [build_frame_nr(123)]; +// +// // Create some positions with implicit instances +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// // Assign all of them a color via splat +// let color_instances = vec![InstanceKey::SPLAT]; +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = DataRow::from_cells2_sized( +// RowId::new(), +// entity_path, +// timepoint, +// 1, +// (color_instances, colors), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// } +// +// #[test] +// fn invalidation() { +// let entity_path = "point"; +// +// let test_invalidation = |query: LatestAtQuery, +// present_data_timepoint: TimePoint, +// past_data_timepoint: TimePoint, +// future_data_timepoint: TimePoint| { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// // Create some positions with implicit instances +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// present_data_timepoint.clone(), +// 2, +// positions, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// // Assign one of them a color with an explicit instance +// let color_instances = vec![InstanceKey(1)]; +// let colors = vec![MyColor::from_rgb(1, 2, 3)]; +// let row = DataRow::from_cells2_sized( +// RowId::new(), +// entity_path, +// present_data_timepoint.clone(), +// 1, +// (color_instances, colors), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // --- Modify present --- +// +// // Modify the PoV component +// let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// present_data_timepoint.clone(), +// 2, +// positions, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // Modify the optional component +// let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// present_data_timepoint, +// 2, +// colors, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // --- Modify past --- +// +// // Modify the PoV component +// let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// past_data_timepoint.clone(), +// 2, +// positions, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // Modify the optional component +// let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, past_data_timepoint, 2, colors) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // --- Modify future --- +// +// // Modify the PoV component +// let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// future_data_timepoint.clone(), +// 2, +// positions, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // Modify the optional component +// let colors = vec![MyColor::from_rgb(16, 17, 18)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// }; +// +// let timeless = TimePoint::default(); +// let frame_122 = build_frame_nr(122); +// let frame_123 = build_frame_nr(123); +// let frame_124 = build_frame_nr(124); +// +// test_invalidation( +// LatestAtQuery::new(frame_123.0, frame_123.1), +// [frame_123].into(), +// [frame_122].into(), +// [frame_124].into(), +// ); +// +// test_invalidation( +// LatestAtQuery::new(frame_123.0, frame_123.1), +// [frame_123].into(), +// timeless, +// [frame_124].into(), +// ); +// } +// +// // Test the following scenario: +// // ```py +// // rr.log("points", rr.Points3D([1, 2, 3]), static=True) +// // +// // # Do first query here: LatestAt(+inf) +// // # Expected: points=[[1,2,3]] colors=[] +// // +// // rr.set_time(2) +// // rr.log_components("points", rr.components.MyColor(0xFF0000)) +// // +// // # Do second query here: LatestAt(+inf) +// // # Expected: points=[[1,2,3]] colors=[0xFF0000] +// // +// // rr.set_time(3) +// // rr.log_components("points", rr.components.MyColor(0x0000FF)) +// // +// // # Do third query here: LatestAt(+inf) +// // # Expected: points=[[1,2,3]] colors=[0x0000FF] +// // +// // rr.set_time(3) +// // rr.log_components("points", rr.components.MyColor(0x00FF00)) +// // +// // # Do fourth query here: LatestAt(+inf) +// // # Expected: points=[[1,2,3]] colors=[0x00FF00] +// // ``` +// #[test] +// fn invalidation_of_future_optionals() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path = "points"; +// +// let timeless = TimePoint::default(); +// let frame2 = [build_frame_nr(2)]; +// let frame3 = [build_frame_nr(3)]; +// +// let query_time = [build_frame_nr(9999)]; +// +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// let color_instances = vec![InstanceKey::SPLAT]; +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = DataRow::from_cells2_sized( +// RowId::new(), +// entity_path, +// frame2, +// 1, +// (color_instances, colors), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// let color_instances = vec![InstanceKey::SPLAT]; +// let colors = vec![MyColor::from_rgb(0, 0, 255)]; +// let row = DataRow::from_cells2_sized( +// RowId::new(), +// entity_path, +// frame3, +// 1, +// (color_instances, colors), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// let color_instances = vec![InstanceKey::SPLAT]; +// let colors = vec![MyColor::from_rgb(0, 255, 0)]; +// let row = DataRow::from_cells2_sized( +// RowId::new(), +// entity_path, +// frame3, +// 1, +// (color_instances, colors), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// } +// +// #[test] +// fn static_invalidation() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path = "points"; +// +// let timeless = TimePoint::default(); +// +// let query_time = [build_frame_nr(9999)]; +// +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// let color_instances = vec![InstanceKey::SPLAT]; +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = DataRow::from_cells2_sized( +// RowId::new(), +// entity_path, +// timeless.clone(), +// 1, +// (color_instances, colors), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// let color_instances = vec![InstanceKey::SPLAT]; +// let colors = vec![MyColor::from_rgb(0, 0, 255)]; +// let row = DataRow::from_cells2_sized( +// RowId::new(), +// entity_path, +// timeless, +// 1, +// (color_instances, colors), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// } +// +// // --- +// +// fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { +// caches.on_events(&[store.insert_row(row).unwrap()]); +// } +// +// fn query_and_compare( +// caches: &Caches, +// store: &DataStore, +// query: &LatestAtQuery, +// entity_path: &EntityPath, +// ) { +// re_log::setup_logging(); +// +// let resolver = PromiseResolver::default(); +// +// for _ in 0..3 { +// let cached = caches.latest_at( +// store, +// query, +// entity_path, +// MyPoints::all_components().iter().copied(), +// ); +// +// let cached_points = cached.get_required(MyPoint::name()).unwrap(); +// let cached_point_data = cached_points +// .to_dense::(&resolver) +// .flatten() +// .unwrap(); +// +// let cached_colors = cached.get_or_empty(MyColor::name()); +// let cached_color_data = cached_colors +// .to_dense::(&resolver) +// .flatten() +// .unwrap(); +// +// let expected = re_query2::latest_at( +// store, +// query, +// entity_path, +// MyPoints::all_components().iter().copied(), +// ); +// +// let expected_points = expected.get_required(MyPoint::name()).unwrap(); +// let expected_point_data = expected_points +// .to_dense::(&resolver) +// .flatten() +// .unwrap(); +// +// let expected_colors = expected.get_or_empty(MyColor::name()); +// let expected_color_data = expected_colors +// .to_dense::(&resolver) +// .flatten() +// .unwrap(); +// +// // eprintln!("{}", store.to_data_table().unwrap()); +// +// similar_asserts::assert_eq!(expected.compound_index, cached.compound_index); +// similar_asserts::assert_eq!(expected_point_data, cached_point_data); +// similar_asserts::assert_eq!(expected_color_data, cached_color_data); +// } +// } diff --git a/crates/re_query2/tests/range.rs b/crates/re_query2/tests/range.rs index a000f588b311..3a7f6de0ab7e 100644 --- a/crates/re_query2/tests/range.rs +++ b/crates/re_query2/tests/range.rs @@ -1,496 +1,588 @@ -use itertools::izip; -use re_query2::PromiseResolver; -use re_types::{components::InstanceKey, Archetype}; +use itertools::{izip, Itertools as _}; -use re_data_store::{DataStore, TimeInt, TimeRange}; +use re_data_store::{DataStore, RangeQuery, StoreSubscriber as _, TimeInt, TimeRange}; use re_log_types::{ build_frame_nr, example_components::{MyColor, MyPoint, MyPoints}, DataRow, EntityPath, RowId, TimePoint, }; +use re_query2::{Caches, PromiseResolver, PromiseResult}; +use re_types::{components::InstanceKey, Archetype}; use re_types_core::Loggable as _; // --- -#[test] -fn simple_range() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let resolver = PromiseResolver::default(); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; - store.insert_row(&row)?; - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; - store.insert_row(&row)?; - } - - let timepoint3 = [build_frame_nr(323)]; - { - let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; - store.insert_row(&row)?; - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #323: - // ┌──────────────┬─────────────────┐ - // │ MyPoint ┆ MyColor │ - // ╞══════════════╪═════════════════╡ - // │ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {30.0,40.0} ┆ 4278190080 │ - // └──────────────┴─────────────────┘ - - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - assert!(results.next().is_none()); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #123: - // ┌───────────────┬─────────────────┐ - // │ MyPoint ┆ MyColor │ - // ╞═══════════════╪═════════════════╡ - // │ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ null │ - // └───────────────┴─────────────────┘ - // - // Frame #323: - // ┌───────────────┬─────────────────┐ - // │ MyPoint ┆ MyColor │ - // ╞═══════════════╪═════════════════╡ - // │ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {30.0,40.0} ┆ 4278190080 │ - // └───────────────┴─────────────────┘ - - { - // Frame #123 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(123), data_time); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![None, None]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - assert!(results.next().is_none()); - - Ok(()) -} - -#[test] -fn static_range() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let resolver = PromiseResolver::default(); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let mut row = - DataRow::from_cells1(RowId::new(), entity_path.clone(), timepoint1, 2, positions)?; - row.compute_all_size_bytes(); - store.insert_row(&row)?; - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances.clone(), colors.clone()), - )?; - store.insert_row(&row)?; - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances.clone(), colors.clone()), - )?; - store.insert_row(&row)?; - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - )?; - store.insert_row(&row)?; - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint3, - 2, - positions, - )?; - store.insert_row(&row)?; - } - - // ┌──────────┬───────────────┬────────────────────────────┐ - // │ frame_nr ┆ MyColor ┆ MyColor │ - // ╞══════════╪═══════════════╪════════════════════════════╡ - // │ null ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 123 ┆ null ┆ [{1.0,2.0}, {3.0,4.0}] │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 123 ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 223 ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 223 ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 323 ┆ null ┆ [{10.0,20.0}, {30.0,40.0}] │ - // └──────────┴───────────────┴────────────────────────────┘ - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - { - // Frame #123 (partially static) - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(123), data_time); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - // --- Third test: `[-inf, +inf]` --- - - let query = - re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - { - // Frame #123 (partially static) - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(123), data_time); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} +// TODO + +// #[test] +// fn simple_range() -> anyhow::Result<()> { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path: EntityPath = "point".into(); +// +// let timepoint1 = [build_frame_nr(123)]; +// { +// let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; +// insert_and_react(&mut store, &mut caches, &row); +// +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; +// insert_and_react(&mut store, &mut caches, &row); +// } +// +// let timepoint2 = [build_frame_nr(223)]; +// { +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; +// insert_and_react(&mut store, &mut caches, &row); +// } +// +// let timepoint3 = [build_frame_nr(323)]; +// { +// let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; +// insert_and_react(&mut store, &mut caches, &row); +// } +// +// // --- First test: `(timepoint1, timepoint3]` --- +// +// let query = re_data_store::RangeQuery::new( +// timepoint1[0].0, +// TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), +// ); +// +// query_and_compare(&caches, &store, &query, &entity_path); +// +// // --- Second test: `[timepoint1, timepoint3]` --- +// +// let query = re_data_store::RangeQuery::new( +// timepoint1[0].0, +// TimeRange::new(timepoint1[0].1, timepoint3[0].1), +// ); +// +// query_and_compare(&caches, &store, &query, &entity_path); +// +// Ok(()) +// } +// +// #[test] +// fn static_range() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path: EntityPath = "point".into(); +// +// let timepoint1 = [build_frame_nr(123)]; +// { +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path.clone(), +// timepoint1, +// 1, +// colors.clone(), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// // Insert statically too! +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path.clone(), +// TimePoint::default(), +// 1, +// colors, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// } +// +// let timepoint2 = [build_frame_nr(223)]; +// { +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path.clone(), +// timepoint2, +// 1, +// colors.clone(), +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// // Insert statically too! +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path.clone(), +// TimePoint::default(), +// 1, +// colors, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// } +// +// let timepoint3 = [build_frame_nr(323)]; +// { +// // Create some Positions with implicit instances +// let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// } +// +// // --- First test: `(timepoint1, timepoint3]` --- +// +// let query = re_data_store::RangeQuery::new( +// timepoint1[0].0, +// TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), +// ); +// +// query_and_compare(&caches, &store, &query, &entity_path); +// +// // --- Second test: `[timepoint1, timepoint3]` --- +// +// // The inclusion of `timepoint1` means latest-at semantics will fall back to timeless data! +// +// let query = re_data_store::RangeQuery::new( +// timepoint1[0].0, +// TimeRange::new(timepoint1[0].1, timepoint3[0].1), +// ); +// +// query_and_compare(&caches, &store, &query, &entity_path); +// +// // --- Third test: `[-inf, +inf]` --- +// +// let query = +// re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); +// +// query_and_compare(&caches, &store, &query, &entity_path); +// } +// +// #[test] +// fn simple_splatted_range() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path: EntityPath = "point".into(); +// +// let timepoint1 = [build_frame_nr(123)]; +// { +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// // Assign one of them a color with an explicit instance +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// } +// +// let timepoint2 = [build_frame_nr(223)]; +// { +// let colors = vec![MyColor::from_rgb(0, 255, 0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// } +// +// let timepoint3 = [build_frame_nr(323)]; +// { +// let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// } +// +// // --- First test: `(timepoint1, timepoint3]` --- +// +// let query = re_data_store::RangeQuery::new( +// timepoint1[0].0, +// TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), +// ); +// +// query_and_compare(&caches, &store, &query, &entity_path); +// +// // --- Second test: `[timepoint1, timepoint3]` --- +// +// let query = re_data_store::RangeQuery::new( +// timepoint1[0].0, +// TimeRange::new(timepoint1[0].1, timepoint3[0].1), +// ); +// +// query_and_compare(&caches, &store, &query, &entity_path); +// } +// +// #[test] +// fn invalidation() { +// let entity_path = "point"; +// +// let test_invalidation = |query: RangeQuery, +// present_data_timepoint: TimePoint, +// past_data_timepoint: TimePoint, +// future_data_timepoint: TimePoint| { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// present_data_timepoint.clone(), +// 2, +// positions, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// let colors = vec![MyColor::from_rgb(1, 2, 3)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// present_data_timepoint.clone(), +// 1, +// colors, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // --- Modify present --- +// +// // Modify the PoV component +// let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// present_data_timepoint.clone(), +// 2, +// positions, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // Modify the optional component +// let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// present_data_timepoint, +// 2, +// colors, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // --- Modify past --- +// +// // Modify the PoV component +// let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// past_data_timepoint.clone(), +// 2, +// positions, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // Modify the optional component +// let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// past_data_timepoint.clone(), +// 2, +// colors, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // --- Modify future --- +// +// // Modify the PoV component +// let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; +// let row = DataRow::from_cells1_sized( +// RowId::new(), +// entity_path, +// future_data_timepoint.clone(), +// 2, +// positions, +// ) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// // Modify the optional component +// let colors = vec![MyColor::from_rgb(16, 17, 18)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// }; +// +// let timeless = TimePoint::default(); +// let frame_122 = build_frame_nr(122); +// let frame_123 = build_frame_nr(123); +// let frame_124 = build_frame_nr(124); +// +// test_invalidation( +// RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), +// [frame_123].into(), +// [frame_122].into(), +// [frame_124].into(), +// ); +// +// test_invalidation( +// RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), +// [frame_123].into(), +// timeless, +// [frame_124].into(), +// ); +// } +// +// // Test the following scenario: +// // ```py +// // rr.log("points", rr.Points3D([1, 2, 3]), static=True) +// // +// // # Do first query here: LatestAt(+inf) +// // # Expected: points=[[1,2,3]] colors=[] +// // +// // rr.set_time(2) +// // rr.log_components("points", rr.components.MyColor(0xFF0000)) +// // +// // # Do second query here: LatestAt(+inf) +// // # Expected: points=[[1,2,3]] colors=[0xFF0000] +// // +// // rr.set_time(3) +// // rr.log_components("points", rr.components.MyColor(0x0000FF)) +// // +// // # Do third query here: LatestAt(+inf) +// // # Expected: points=[[1,2,3]] colors=[0x0000FF] +// // +// // rr.set_time(3) +// // rr.log_components("points", rr.components.MyColor(0x00FF00)) +// // +// // # Do fourth query here: LatestAt(+inf) +// // # Expected: points=[[1,2,3]] colors=[0x00FF00] +// // ``` +// #[test] +// fn invalidation_of_future_optionals() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path = "points"; +// +// let timeless = TimePoint::default(); +// let frame2 = [build_frame_nr(2)]; +// let frame3 = [build_frame_nr(3)]; +// +// let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); +// +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// let colors = vec![MyColor::from_rgb(0, 0, 255)]; +// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// let colors = vec![MyColor::from_rgb(0, 255, 0)]; +// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// } +// +// #[test] +// fn invalidation_static() { +// let mut store = DataStore::new( +// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), +// InstanceKey::name(), +// Default::default(), +// ); +// let mut caches = Caches::new(&store); +// +// let entity_path = "points"; +// +// let timeless = TimePoint::default(); +// +// let frame0 = [build_frame_nr(TimeInt::ZERO)]; +// let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); +// +// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; +// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) +// .unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// let colors = vec![MyColor::from_rgb(255, 0, 0)]; +// let row = +// DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 1, colors).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// +// let colors = vec![MyColor::from_rgb(0, 0, 255)]; +// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors).unwrap(); +// insert_and_react(&mut store, &mut caches, &row); +// +// query_and_compare(&caches, &store, &query, &entity_path.into()); +// } +// +// // --- +// +// fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { +// caches.on_events(&[store.insert_row(row).unwrap()]); +// } +// +// fn query_and_compare( +// caches: &Caches, +// store: &DataStore, +// query: &RangeQuery, +// entity_path: &EntityPath, +// ) { +// re_log::setup_logging(); +// +// let resolver = PromiseResolver::default(); +// +// for _ in 0..3 { +// let cached = caches.range( +// store, +// query, +// entity_path, +// MyPoints::all_components().iter().copied(), +// ); +// +// let cached_all_points = cached +// .get_required(MyPoint::name()) +// .unwrap() +// .to_dense::(&resolver); +// assert!(matches!( +// cached_all_points.status(), +// (PromiseResult::Ready(()), PromiseResult::Ready(())), +// )); +// let cached_all_points_indexed = cached_all_points.range_indexed(); +// +// let cached_all_colors = cached +// .get_or_empty(MyColor::name()) +// .to_dense::(&resolver); +// assert!(matches!( +// cached_all_colors.status(), +// (PromiseResult::Ready(()), PromiseResult::Ready(())), +// )); +// let cached_all_colors_indexed = cached_all_colors.range_indexed(); +// +// let expected = re_query2::range( +// store, +// query, +// entity_path, +// MyPoints::all_components().iter().copied(), +// ); +// +// let expected_all_points = expected.get_required(MyPoint::name()).unwrap(); +// let expected_all_points_indices = expected_all_points.indices(); +// let expected_all_points_data = expected_all_points +// .to_dense::(&resolver) +// .into_iter() +// .map(|batch| batch.flatten().unwrap()) +// .collect_vec(); +// let expected_all_points_indexed = +// izip!(expected_all_points_indices, expected_all_points_data); +// +// let expected_all_colors = expected.get_or_empty(MyColor::name()); +// let expected_all_colors_indices = expected_all_colors.indices(); +// let expected_all_colors_data = expected_all_colors +// .to_dense::(&resolver) +// .into_iter() +// .map(|batch| batch.flatten().unwrap()) +// .collect_vec(); +// let expected_all_colors_indexed = +// izip!(expected_all_colors_indices, expected_all_colors_data); +// +// eprintln!("{query:?}"); +// eprintln!("{}", store.to_data_table().unwrap()); +// +// similar_asserts::assert_eq!( +// expected_all_points_indexed +// .map(|(index, data)| (*index, data)) +// .collect_vec(), +// cached_all_points_indexed +// .map(|(index, data)| (*index, data.to_vec())) +// .collect_vec(), +// ); +// +// similar_asserts::assert_eq!( +// expected_all_colors_indexed +// .map(|(index, data)| (*index, data)) +// .collect_vec(), +// cached_all_colors_indexed +// .map(|(index, data)| (*index, data.to_vec())) +// .collect_vec(), +// ); +// } +// } diff --git a/crates/re_query_cache/Cargo.toml b/crates/re_query_cache/Cargo.toml deleted file mode 100644 index 71a9dfbe35ef..000000000000 --- a/crates/re_query_cache/Cargo.toml +++ /dev/null @@ -1,81 +0,0 @@ -[package] -name = "re_query_cache" -authors.workspace = true -description = "Caching datastructures for re_query" -edition.workspace = true -homepage.workspace = true -include.workspace = true -license.workspace = true -publish = true -readme = "README.md" -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[lints] -workspace = true - -[package.metadata.docs.rs] -all-features = true - - -[features] -default = ["to_archetype"] - -## Implements `ToArchetype` for all builtin archetypes on `CachedLatestAtResults`. -to_archetype = ["dep:re_types", "dep:re_types_blueprint"] - -[dependencies] -# Rerun dependencies: -re_data_store.workspace = true -re_error.workspace = true -re_format.workspace = true -re_log.workspace = true -re_log_types.workspace = true -re_query2.workspace = true -re_tracing.workspace = true -re_types_core.workspace = true - -# Rerun dependencies (optional): -re_types = { workspace = true, optional = true } -re_types_blueprint = { workspace = true, optional = true } - -# External dependencies: -ahash.workspace = true -anyhow.workspace = true -backtrace.workspace = true -indent.workspace = true -indexmap.workspace = true -itertools.workspace = true -nohash-hasher.workspace = true -parking_lot.workspace = true -paste.workspace = true -seq-macro.workspace = true -web-time.workspace = true - - -[dev-dependencies] -re_types = { workspace = true, features = ["datagen"] } - -criterion.workspace = true -mimalloc.workspace = true -rand = { workspace = true, features = ["std", "std_rng"] } -similar-asserts.workspace = true - - -[lib] -bench = false - - -[[example]] -name = "latest_at_archetype" -required-features = ["to_archetype"] - - -[[bench]] -name = "flat_vec_deque" -harness = false - -[[bench]] -name = "latest_at" -harness = false diff --git a/crates/re_query_cache/README.md b/crates/re_query_cache/README.md deleted file mode 100644 index 70613732471d..000000000000 --- a/crates/re_query_cache/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# re_query_cache - -Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. - -[![Latest version](https://img.shields.io/crates/v/re_query_cache.svg)](https://crates.io/crates/re_query_cache) -[![Documentation](https://docs.rs/re_query/badge.svg)](https://docs.rs/re_query) -![MIT](https://img.shields.io/badge/license-MIT-blue.svg) -![Apache](https://img.shields.io/badge/license-Apache-blue.svg) - -Caching datastructures for `re_query`. diff --git a/crates/re_query_cache/benches/latest_at.rs b/crates/re_query_cache/benches/latest_at.rs deleted file mode 100644 index 599c73726ef9..000000000000 --- a/crates/re_query_cache/benches/latest_at.rs +++ /dev/null @@ -1,374 +0,0 @@ -//! Contains: -//! - A 1:1 port of the benchmarks in `crates/re_query/benches/query_benchmarks.rs`, with caching enabled. - -use criterion::{criterion_group, criterion_main, Criterion}; - -use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; -use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query2::{clamped_zip_1x1, PromiseResolver}; -use re_query_cache::{CachedLatestAtResults, Caches}; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D, Text}, - Archetype as _, -}; -use re_types_core::Loggable as _; - -// --- - -// `cargo test` also runs the benchmark setup code, so make sure they run quickly: -#[cfg(debug_assertions)] -mod constants { - pub const NUM_FRAMES_POINTS: u32 = 1; - pub const NUM_POINTS: u32 = 1; - pub const NUM_FRAMES_STRINGS: u32 = 1; - pub const NUM_STRINGS: u32 = 1; -} - -#[cfg(not(debug_assertions))] -mod constants { - pub const NUM_FRAMES_POINTS: u32 = 1_000; - pub const NUM_POINTS: u32 = 1_000; - pub const NUM_FRAMES_STRINGS: u32 = 1_000; - pub const NUM_STRINGS: u32 = 1_000; -} - -#[allow(clippy::wildcard_imports)] -use self::constants::*; - -// --- - -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -criterion_group!( - benches, - mono_points, - mono_strings, - batch_points, - batch_strings -); -criterion_main!(benches); - -// --- - -fn mono_points(c: &mut Criterion) { - // Each mono point gets logged at a different path - let paths = (0..NUM_POINTS) - .map(move |point_idx| entity_path!("points", point_idx)) - .collect_vec(); - let msgs = build_points_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - // Mono-insert is slow -- decrease the sample size - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let (caches, store) = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&caches, &store, &paths)); - }); - } -} - -fn mono_strings(c: &mut Criterion) { - // Each mono string gets logged at a different path - let paths = (0..NUM_STRINGS) - .map(move |string_idx| entity_path!("strings", string_idx)) - .collect_vec(); - let msgs = build_strings_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let (caches, store) = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&caches, &store, &paths)); - }); - } -} - -fn batch_points(c: &mut Criterion) { - // Batch points are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_points_rows(&paths, NUM_POINTS as _); - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let (caches, store) = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&caches, &store, &paths)); - }); - } -} - -fn batch_strings(c: &mut Criterion) { - // Batch strings are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_strings_rows(&paths, NUM_STRINGS as _); - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let (caches, store) = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&caches, &store, &paths)); - }); - } -} - -// --- Helpers --- - -pub fn build_some_point2d(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) - .collect() -} - -/// Create `len` dummy colors -pub fn build_some_colors(len: usize) -> Vec { - (0..len).map(|i| Color::from(i as u32)).collect() -} - -/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. -pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { - (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) -} - -pub fn build_some_strings(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| { - let ilen: usize = rng.gen_range(0..10000); - let s: String = rand::thread_rng() - .sample_iter(&rand::distributions::Alphanumeric) - .take(ilen) - .map(char::from) - .collect(); - Text::from(s) - }) - .collect() -} - -fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { - (0..NUM_FRAMES_POINTS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_points as _, - ( - build_some_point2d(num_points), - build_some_colors(num_points), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec { - (0..NUM_FRAMES_STRINGS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_strings as _, - // We still need to create points because they are the primary for the - // archetype query we want to do. We won't actually deserialize the points - // during the query -- we just need it for the primary keys. - // TODO(jleibs): switch this to use `TextEntry` once the new type has - // landed. - ( - build_some_point2d(num_strings), - build_some_strings(num_strings), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn insert_rows<'a>(msgs: impl Iterator) -> (Caches, DataStore) { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - msgs.for_each(|row| { - caches.on_events(&[store.insert_row(row).unwrap()]); - }); - - (caches, store) -} - -struct SavePoint { - _pos: Position2D, - _color: Option, -} - -fn query_and_visit_points( - caches: &Caches, - store: &DataStore, - paths: &[EntityPath], -) -> Vec { - let resolver = PromiseResolver::default(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_POINTS as i64 / 2); - - let mut ret = Vec::with_capacity(NUM_POINTS as _); - - // TODO(jleibs): Add Radius once we have support for it in field_types - for entity_path in paths { - let results: CachedLatestAtResults = caches.latest_at( - store, - &query, - entity_path, - Points2D::all_components().iter().copied(), // no generics! - ); - - let points = results.get_required(Position2D::name()).unwrap(); - let colors = results.get_or_empty(Color::name()); - - let points = points - .iter_dense::(&resolver) - .flatten() - .unwrap() - .copied(); - - let colors = colors - .iter_dense::(&resolver) - .flatten() - .unwrap() - .copied(); - let color_default_fn = || Color::from(0xFF00FFFF); - - for (point, color) in clamped_zip_1x1(points, colors, color_default_fn) { - ret.push(SavePoint { - _pos: point, - _color: Some(color), - }); - } - } - assert_eq!(NUM_POINTS as usize, ret.len()); - ret -} - -struct SaveString { - _label: Option, -} - -fn query_and_visit_strings( - caches: &Caches, - store: &DataStore, - paths: &[EntityPath], -) -> Vec { - let resolver = PromiseResolver::default(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_STRINGS as i64 / 2); - - let mut strings = Vec::with_capacity(NUM_STRINGS as _); - - for entity_path in paths { - let results: CachedLatestAtResults = caches.latest_at( - store, - &query, - entity_path, - Points2D::all_components().iter().copied(), // no generics! - ); - - let points = results.get_required(Position2D::name()).unwrap(); - let colors = results.get_or_empty(Text::name()); - - let points = points - .iter_dense::(&resolver) - .flatten() - .unwrap() - .copied(); - - let labels = colors - .iter_dense::(&resolver) - .flatten() - .unwrap() - .cloned(); - let label_default_fn = || Text(String::new().into()); - - for (_point, label) in clamped_zip_1x1(points, labels, label_default_fn) { - strings.push(SaveString { - _label: Some(label), - }); - } - } - assert_eq!(NUM_STRINGS as usize, strings.len()); - criterion::black_box(strings) -} diff --git a/crates/re_query_cache/examples/latest_at.rs b/crates/re_query_cache/examples/latest_at.rs deleted file mode 100644 index e894e10b63a1..000000000000 --- a/crates/re_query_cache/examples/latest_at.rs +++ /dev/null @@ -1,133 +0,0 @@ -use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; -use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; -use re_types_core::{Archetype as _, Loggable as _}; - -use re_query_cache::{ - clamped_zip_1x2, CachedLatestAtComponentResults, CachedLatestAtResults, PromiseResolver, - PromiseResult, -}; - -// --- - -fn main() -> anyhow::Result<()> { - let store = store()?; - eprintln!("store:\n{}", store.to_data_table()?); - - let resolver = PromiseResolver::default(); - - let entity_path = "points"; - let timeline = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::latest(timeline); - eprintln!("query:{query:?}"); - - let caches = re_query_cache::Caches::new(&store); - - // First, get the results for this query. - // - // They might or might not already be cached. We won't know for sure until we try to access - // each individual component's data below. - let results: CachedLatestAtResults = caches.latest_at( - &store, - &query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), // no generics! - ); - - // Then, grab the results for each individual components. - // * `get_required` returns an error if the component batch is missing - // * `get_or_empty` returns an empty set of results if the component if missing - // * `get` returns an option - // - // At this point we still don't know whether they are cached or not. That's the next step. - let points: &CachedLatestAtComponentResults = results.get_required(MyPoint::name())?; - let colors: &CachedLatestAtComponentResults = results.get_or_empty(MyColor::name()); - let labels: &CachedLatestAtComponentResults = results.get_or_empty(MyLabel::name()); - - // Then comes the time to resolve/convert and deserialize the data. - // These steps have to be done together for efficiency reasons. - // - // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. - // Use `PromiseResult::flatten` to simplify it down to a single result. - // - // This is the step at which caching comes into play. - // If the data has already been accessed in the past, then this will just grab the pre-deserialized, - // pre-resolved/pre-converted result from the cache. - // Otherwise, this will trigger a deserialization and cache the result for next time. - - let points = match points.iter_dense::(&resolver).flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - return Ok(()); - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - }; - - let colors = match colors.iter_dense::(&resolver).flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - return Ok(()); - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - }; - - let labels = match labels.iter_dense::(&resolver).flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - return Ok(()); - } - PromiseResult::Ready(data) => data.map(Some), - PromiseResult::Error(err) => return Err(err.into()), - }; - - // With the data now fully resolved/converted and deserialized, the joining logic can be - // applied. - // - // In most cases this will be either a clamped zip, or no joining at all. - - let color_default_fn = || { - static DEFAULT: MyColor = MyColor(0xFF00FFFF); - &DEFAULT - }; - let label_default_fn = || None; - - let results = - clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn).collect_vec(); - - eprintln!("results:\n{results:#?}"); - - Ok(()) -} - -// --- - -fn store() -> anyhow::Result { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - re_types::components::InstanceKey::name(), - Default::default(), - ); - - let entity_path = "points"; - - { - let timepoint = [build_frame_nr(123)]; - - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; - store.insert_row(&row)?; - } - - Ok(store) -} diff --git a/crates/re_query_cache/examples/range.rs b/crates/re_query_cache/examples/range.rs deleted file mode 100644 index e9bef34822eb..000000000000 --- a/crates/re_query_cache/examples/range.rs +++ /dev/null @@ -1,151 +0,0 @@ -use itertools::Itertools; -use re_data_store::{DataStore, RangeQuery}; -use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; -use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline}; -use re_types_core::{Archetype as _, Loggable as _}; - -use re_query_cache::{ - clamped_zip_1x2, range_zip_1x2, CachedRangeComponentResults, CachedRangeResults, - PromiseResolver, PromiseResult, -}; - -// --- - -fn main() -> anyhow::Result<()> { - let store = store()?; - eprintln!("store:\n{}", store.to_data_table()?); - - let resolver = PromiseResolver::default(); - - let entity_path = "points"; - let timeline = Timeline::new("frame_nr", TimeType::Sequence); - let query = RangeQuery::new(timeline, TimeRange::EVERYTHING); - eprintln!("query:{query:?}"); - - let caches = re_query_cache::Caches::new(&store); - - // First, get the raw results for this query. - // - // They might or might not already be cached. We won't know for sure until we try to access - // each individual component's data below. - let results: CachedRangeResults = caches.range( - &store, - &query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), // no generics! - ); - - // Then, grab the results for each individual components. - // * `get_required` returns an error if the component batch is missing - // * `get_or_empty` returns an empty set of results if the component if missing - // * `get` returns an option - // - // At this point we still don't know whether they are cached or not. That's the next step. - let all_points: &CachedRangeComponentResults = results.get_required(MyPoint::name())?; - let all_colors: &CachedRangeComponentResults = results.get_or_empty(MyColor::name()); - let all_labels: &CachedRangeComponentResults = results.get_or_empty(MyLabel::name()); - - // Then comes the time to resolve/convert and deserialize the data. - // These steps have to be done together for efficiency reasons. - // - // That's when caching comes into play. - // If the data has already been accessed in the past, then this will just grab the - // pre-deserialized, pre-resolved/pre-converted result from the cache. - // Otherwise, this will trigger a deserialization and cache the result for next time. - let all_points = all_points.to_dense::(&resolver); - let all_colors = all_colors.to_dense::(&resolver); - let all_labels = all_labels.to_dense::(&resolver); - - // The cache might not have been able to resolve and deserialize the entire dataset across all - // available timestamps. - // - // We can use the following APIs to check the status of the front and back sides of the data range. - // - // E.g. it is possible that the front-side of the range is still waiting for pending data while - // the back-side has been fully loaded. - assert!(matches!( - all_points.status(), - (PromiseResult::Ready(()), PromiseResult::Ready(())) - )); - - // Zip the results together using a stateful time-based join. - let all_frames = range_zip_1x2( - all_points.range_indexed(), - all_colors.range_indexed(), - all_labels.range_indexed(), - ); - - // Then comes the time to resolve/convert and deserialize the data, _for each timestamp_. - // These steps have to be done together for efficiency reasons. - // - // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. - // Use `PromiseResult::flatten` to simplify it down to a single result. - eprintln!("results:"); - for ((data_time, row_id), points, colors, labels) in all_frames { - let colors = colors.unwrap_or(&[]); - let color_default_fn = || { - static DEFAULT: MyColor = MyColor(0xFF00FFFF); - &DEFAULT - }; - - let labels = labels.unwrap_or(&[]).iter().cloned().map(Some); - let label_default_fn = || None; - - // With the data now fully resolved/converted and deserialized, the joining logic can be - // applied. - // - // In most cases this will be either a clamped zip, or no joining at all. - - let results = clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn) - .collect_vec(); - eprintln!("{data_time:?} @ {row_id}:\n {results:?}"); - } - - Ok(()) -} - -// --- - -fn store() -> anyhow::Result { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - re_types::components::InstanceKey::name(), - Default::default(), - ); - - let entity_path = "points"; - - { - let timepoint = [build_frame_nr(123)]; - - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; - store.insert_row(&row)?; - } - - { - let timepoint = [build_frame_nr(456)]; - - let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let points = vec![ - MyPoint::new(10.0, 20.0), - MyPoint::new(30.0, 40.0), - MyPoint::new(50.0, 60.0), - ]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - } - - Ok(store) -} diff --git a/crates/re_query_cache/src/latest_at/mod.rs b/crates/re_query_cache/src/latest_at/mod.rs deleted file mode 100644 index 82fd889bce0b..000000000000 --- a/crates/re_query_cache/src/latest_at/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -mod helpers; -mod query; -mod results; - -#[cfg(feature = "to_archetype")] -mod to_archetype; - -pub use self::helpers::CachedLatestAtMonoResult; -pub use self::query::LatestAtCache; -pub use self::results::{CachedLatestAtComponentResults, CachedLatestAtResults}; diff --git a/crates/re_query_cache/src/latest_at/query.rs b/crates/re_query_cache/src/latest_at/query.rs deleted file mode 100644 index 825830e9a731..000000000000 --- a/crates/re_query_cache/src/latest_at/query.rs +++ /dev/null @@ -1,315 +0,0 @@ -use std::collections::BTreeSet; -use std::{collections::BTreeMap, sync::Arc}; - -use indexmap::IndexMap; -use itertools::Itertools; -use parking_lot::RwLock; - -use re_data_store::{DataStore, LatestAtQuery, TimeInt}; -use re_log_types::EntityPath; -use re_query2::Promise; -use re_types_core::ComponentName; -use re_types_core::SizeBytes; - -use crate::{CacheKey, CachedLatestAtComponentResults, CachedLatestAtResults, Caches}; - -// --- - -impl Caches { - /// Queries for the given `component_names` using latest-at semantics. - /// - /// See [`CachedLatestAtResults`] for more information about how to handle the results. - /// - /// This is a cached API -- data will be lazily cached upon access. - pub fn latest_at( - &self, - store: &DataStore, - query: &LatestAtQuery, - entity_path: &EntityPath, - component_names: impl IntoIterator, - ) -> CachedLatestAtResults { - re_tracing::profile_function!(entity_path.to_string()); - - let mut results = CachedLatestAtResults::default(); - - for component_name in component_names { - let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); - let cache = Arc::clone( - self.latest_at_per_cache_key - .write() - .entry(key.clone()) - .or_insert_with(|| Arc::new(RwLock::new(LatestAtCache::new(key.clone())))), - ); - - let mut cache = cache.write(); - cache.handle_pending_invalidation(); - if let Some(cached) = cache.latest_at(store, query, entity_path, component_name) { - results.add(component_name, cached); - } - } - - results - } -} - -// --- - -/// Caches the results of `LatestAt` queries for a given [`CacheKey`]. -pub struct LatestAtCache { - /// For debugging purposes. - pub cache_key: CacheKey, - - /// Organized by _query_ time. - /// - /// If the data you're looking for isn't in here, try partially running the query and check - /// if there is any data available for the resulting _data_ time in [`Self::per_data_time`]. - // - // NOTE: `Arc` so we can share buckets across query time & data time. - pub per_query_time: BTreeMap>, - - /// Organized by _data_ time. - /// - /// Due to how our latest-at semantics work, any number of queries at time `T+n` where `n >= 0` - /// can result in a data time of `T`. - // - // NOTE: `Arc` so we can share buckets across query time & data time. - pub per_data_time: BTreeMap>, - - /// These timestamps have been invalidated asynchronously. - /// - /// The next time this cache gets queried, it must remove any invalidated entries accordingly. - /// - /// Invalidation is deferred to query time because it is far more efficient that way: the frame - /// time effectively behaves as a natural micro-batching mechanism. - pub pending_invalidations: BTreeSet, -} - -impl LatestAtCache { - #[inline] - pub fn new(cache_key: CacheKey) -> Self { - Self { - cache_key, - per_query_time: Default::default(), - per_data_time: Default::default(), - pending_invalidations: Default::default(), - } - } -} - -impl std::fmt::Debug for LatestAtCache { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - cache_key, - per_query_time, - per_data_time, - pending_invalidations: _, - } = self; - - let mut strings = Vec::new(); - - struct StatsPerBucket { - query_times: BTreeSet, - data_time: TimeInt, - total_size_bytes: u64, - } - - let mut buckets: IndexMap<_, _> = per_data_time - .iter() - .map(|(&data_time, bucket)| { - ( - Arc::as_ptr(bucket), - StatsPerBucket { - query_times: Default::default(), - data_time, - total_size_bytes: bucket.total_size_bytes(), - }, - ) - }) - .collect(); - - for (&query_time, bucket) in per_query_time { - if let Some(bucket) = buckets.get_mut(&Arc::as_ptr(bucket)) { - bucket.query_times.insert(query_time); - } - } - - for bucket in buckets.values() { - strings.push(format!( - "query_times=[{}] -> data_time={:?} ({})", - bucket - .query_times - .iter() - .map(|t| cache_key.timeline.typ().format_utc(*t)) - .collect_vec() - .join(", "), - bucket.data_time.as_i64(), - re_format::format_bytes(bucket.total_size_bytes as _), - )); - } - - if strings.is_empty() { - return f.write_str(""); - } - - f.write_str(&strings.join("\n").replace("\n\n", "\n")) - } -} - -impl SizeBytes for LatestAtCache { - #[inline] - fn heap_size_bytes(&self) -> u64 { - let Self { - cache_key: _, - per_query_time, - per_data_time, - pending_invalidations, - } = self; - - let per_query_time = per_query_time - .keys() - .map(|k| k.total_size_bytes()) - .sum::(); - // NOTE: per query time buckets are just pointers, don't count them. - - let per_data_time_keys = per_data_time - .keys() - .map(|k| k.total_size_bytes()) - .sum::(); - let per_data_time_values = per_data_time - .values() - // NOTE: make sure to dereference the Arc, else this will account for zero (assumed amortized!) - .map(|arc| (**arc).total_size_bytes()) - .sum::(); - - let per_data_time = per_data_time_keys + per_data_time_values; - let pending_invalidations = pending_invalidations.total_size_bytes(); - - per_query_time + per_data_time + pending_invalidations - } -} - -impl LatestAtCache { - /// Queries cached latest-at data for a single component. - pub fn latest_at( - &mut self, - store: &DataStore, - query: &LatestAtQuery, - entity_path: &EntityPath, - component_name: ComponentName, - ) -> Option> { - re_tracing::profile_scope!("latest_at", format!("{query:?}")); - - let LatestAtCache { - cache_key: _, - per_query_time, - per_data_time, - pending_invalidations: _, - } = self; - - let query_time_bucket_at_query_time = match per_query_time.entry(query.at()) { - std::collections::btree_map::Entry::Occupied(entry) => { - // Fastest path: we have an entry for this exact query time, no need to look any - // further. - re_log::trace!(query_time=?query.at(), "cache hit (query time)"); - return Some(Arc::clone(entry.get())); - } - std::collections::btree_map::Entry::Vacant(entry) => entry, - }; - - let result = store.latest_at(query, entity_path, component_name, &[component_name]); - - // NOTE: cannot `result.and_then(...)` or borrowck gets lost. - if let Some((data_time, row_id, mut cells)) = result { - // Fast path: we've run the query and realized that we already have the data for the resulting - // _data_ time, so let's use that to avoid join & deserialization costs. - if let Some(data_time_bucket_at_data_time) = per_data_time.get(&data_time) { - re_log::trace!(query_time=?query.at(), ?data_time, "cache hit (data time)"); - - query_time_bucket_at_query_time.insert(Arc::clone(data_time_bucket_at_data_time)); - - // We now know for a fact that a query at that data time would yield the same - // results: copy the bucket accordingly so that the next cache hit for that query - // time ends up taking the fastest path. - let query_time_bucket_at_data_time = per_query_time.entry(data_time); - query_time_bucket_at_data_time - .and_modify(|v| *v = Arc::clone(data_time_bucket_at_data_time)) - .or_insert(Arc::clone(data_time_bucket_at_data_time)); - - return Some(Arc::clone(data_time_bucket_at_data_time)); - } - - // Soundness: - // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` - // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null - let Some(cell) = cells[0].take() else { - debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); - return None; - }; - - let bucket = Arc::new(CachedLatestAtComponentResults { - index: (data_time, row_id), - promise: Some(Promise::new(cell)), - cached_dense: Default::default(), - }); - - // Slowest path: this is a complete cache miss. - { - re_log::trace!(query_time=?query.at(), ?data_time, "cache miss"); - - let query_time_bucket_at_query_time = - query_time_bucket_at_query_time.insert(Arc::clone(&bucket)); - - let data_time_bucket_at_data_time = per_data_time.entry(data_time); - data_time_bucket_at_data_time - .and_modify(|v| *v = Arc::clone(query_time_bucket_at_query_time)) - .or_insert(Arc::clone(query_time_bucket_at_query_time)); - } - - Some(bucket) - } else { - None - } - } - - pub fn handle_pending_invalidation(&mut self) { - let Self { - cache_key: _, - per_query_time, - per_data_time, - pending_invalidations, - } = self; - - // First, remove any data indexed by a _query time_ that's more recent than the oldest - // _data time_ that's been invalidated. - // - // Note that this data time might very well be `TimeInt::STATIC`, in which case the entire - // query-time-based index will be dropped. - if let Some(&oldest_data_time) = pending_invalidations.first() { - per_query_time.retain(|&query_time, _| query_time < oldest_data_time); - } - - // Second, remove any data indexed by _data time_, if it's been invalidated. - let mut dropped_data_times = Vec::new(); - per_data_time.retain(|data_time, _| { - if pending_invalidations.contains(data_time) { - dropped_data_times.push(*data_time); - false - } else { - true - } - }); - - // TODO(#5974): Because of non-deterministic ordering and parallelism and all things of that - // nature, it can happen that we try to handle pending invalidations before we even cached - // the associated data. - // - // If that happens, the data will be cached after we've invalidated *nothing*, and will stay - // there indefinitely since the cache doesn't have a dedicated GC yet. - // - // TL;DR: make sure to keep track of pending invalidations indefinitely as long as we - // haven't had the opportunity to actually invalidate the associated data. - for data_time in dropped_data_times { - pending_invalidations.remove(&data_time); - } - } -} diff --git a/crates/re_query_cache/src/latest_at/results.rs b/crates/re_query_cache/src/latest_at/results.rs deleted file mode 100644 index 44691217ac9d..000000000000 --- a/crates/re_query_cache/src/latest_at/results.rs +++ /dev/null @@ -1,299 +0,0 @@ -use std::sync::{Arc, OnceLock}; - -use nohash_hasher::IntMap; - -use re_log_types::{DataCell, RowId, TimeInt}; -use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes}; - -use crate::{ - ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, PromiseResult, QueryError, -}; - -// --- - -/// Cached results for a latest-at query. -/// -/// The data is both deserialized and resolved/converted. -/// -/// Use [`CachedLatestAtResults::get`], [`CachedLatestAtResults::get_required`] and -/// [`CachedLatestAtResults::get_or_empty`] in order to access the results for each individual component. -#[derive(Debug)] -pub struct CachedLatestAtResults { - /// The compound index of this query result. - /// - /// A latest-at query is a compound operation that gathers data from many different rows. - /// The index of that compound result corresponds to the index of most the recent row in all the - /// sub-results, as defined by time and row-id order. - pub compound_index: (TimeInt, RowId), - - /// Results for each individual component. - pub components: IntMap>, -} - -impl Default for CachedLatestAtResults { - #[inline] - fn default() -> Self { - Self { - compound_index: (TimeInt::STATIC, RowId::ZERO), - components: Default::default(), - } - } -} - -impl CachedLatestAtResults { - #[inline] - pub fn contains(&self, component_name: impl Into) -> bool { - self.components.contains_key(&component_name.into()) - } - - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. - #[inline] - pub fn get( - &self, - component_name: impl Into, - ) -> Option<&CachedLatestAtComponentResults> { - self.components - .get(&component_name.into()) - .map(|arc| &**arc) - } - - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. - /// - /// Returns an error if the component is not present. - #[inline] - pub fn get_required( - &self, - component_name: impl Into, - ) -> crate::Result<&CachedLatestAtComponentResults> { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - Ok(component) - } else { - Err(QueryError::PrimaryNotFound(component_name)) - } - } - - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. - /// - /// Returns empty results if the component is not present. - #[inline] - pub fn get_or_empty( - &self, - component_name: impl Into, - ) -> &CachedLatestAtComponentResults { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - component - } else { - static EMPTY: CachedLatestAtComponentResults = CachedLatestAtComponentResults::empty(); - &EMPTY - } - } -} - -impl CachedLatestAtResults { - #[doc(hidden)] - #[inline] - pub fn add( - &mut self, - component_name: ComponentName, - cached: Arc, - ) { - // NOTE: Since this is a compound API that actually emits multiple queries, the index of the - // final result is the most recent index among all of its components, as defined by time - // and row-id order. - // - // TODO(#5303): We have to ignore the cluster key in this piece of logic for backwards compatibility - // reasons with the legacy instance-key model. This will go away next. - use re_types_core::Loggable as _; - if component_name != re_types_core::components::InstanceKey::name() - && cached.index > self.compound_index - { - self.compound_index = cached.index; - } - - self.components.insert(component_name, cached); - } -} - -// --- - -/// Lazily cached results for a particular component when using a cached latest-at query. -pub struct CachedLatestAtComponentResults { - pub(crate) index: (TimeInt, RowId), - - // Option so we can have a constant default value for `Self`. - pub(crate) promise: Option, - - /// The resolved, converted, deserialized dense data. - pub(crate) cached_dense: OnceLock>, -} - -impl CachedLatestAtComponentResults { - #[inline] - pub const fn empty() -> Self { - Self { - index: (TimeInt::STATIC, RowId::ZERO), - promise: None, - cached_dense: OnceLock::new(), - } - } - - /// Returns the [`ComponentName`] of the resolved data, if available. - #[inline] - pub fn component_name(&self, resolver: &PromiseResolver) -> Option { - match self.resolved(resolver) { - PromiseResult::Ready(cell) => Some(cell.component_name()), - _ => None, - } - } - - /// Returns whether the resolved data is static. - #[inline] - pub fn is_static(&self) -> bool { - self.index.0 == TimeInt::STATIC - } - - /// How many _indices_ across this entire cache? - #[inline] - pub fn num_indices(&self) -> u64 { - _ = self; - 1 - } - - /// How many _instances_ across this entire cache? - #[inline] - pub fn num_instances(&self) -> u64 { - self.cached_dense - .get() - .map_or(0u64, |cached| cached.dyn_num_values() as _) - } -} - -impl SizeBytes for CachedLatestAtComponentResults { - #[inline] - fn heap_size_bytes(&self) -> u64 { - let Self { - index, - promise, - cached_dense, - } = self; - - index.total_size_bytes() - + promise.total_size_bytes() - + cached_dense - .get() - .map_or(0, |data| data.dyn_total_size_bytes()) - } -} - -impl std::fmt::Debug for CachedLatestAtComponentResults { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - index, - promise: _, - cached_dense: _, // we can't, we don't know the type - } = self; - - f.write_fmt(format_args!( - "[{:?}#{}] {}", - index.0, - index.1, - re_format::format_bytes(self.total_size_bytes() as _) - )) - } -} - -impl CachedLatestAtComponentResults { - #[inline] - pub fn index(&self) -> &(TimeInt, RowId) { - &self.index - } - - /// Returns the raw resolved data, if it's ready. - #[inline] - pub fn resolved(&self, resolver: &PromiseResolver) -> PromiseResult { - if let Some(cell) = self.promise.as_ref() { - resolver.resolve(cell) - } else { - PromiseResult::Pending - } - } - - /// Returns the component data as a dense vector. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_dense( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult> { - if let Some(cell) = self.promise.as_ref() { - resolver - .resolve(cell) - .map(|cell| self.downcast_dense::(&cell)) - } else { - // Manufactured empty result. - PromiseResult::Ready(Ok(&[])) - } - } - - /// Iterates over the component data, assuming it is dense. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_dense( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>> { - self.to_dense(resolver) - .map(|data| data.map(|data| data.iter())) - } -} - -impl CachedLatestAtComponentResults { - fn downcast_dense(&self, cell: &DataCell) -> crate::Result<&[C]> { - // `OnceLock::get` is non-blocking -- this is a best-effort fast path in case the - // data has already been computed. - // - // See next comment as to why we need this. - if let Some(cached) = self.cached_dense.get() { - return downcast(&**cached); - } - - // We have to do this outside of the callback in order to propagate errors. - // Hence the early exit check above. - let data = cell - .try_to_native::() - .map_err(|err| DeserializationError::DataCellError(err.to_string()))?; - - #[allow(clippy::borrowed_box)] - let cached: &Arc = self - .cached_dense - .get_or_init(move || Arc::new(FlatVecDeque::from(data))); - - downcast(&**cached) - } -} - -fn downcast(cached: &(dyn ErasedFlatVecDeque + Send + Sync)) -> crate::Result<&[C]> { - let cached = cached - .as_any() - .downcast_ref::>() - .ok_or_else(|| QueryError::TypeMismatch { - actual: "".into(), - requested: C::name(), - })?; - - if cached.num_entries() != 1 { - return Err(anyhow::anyhow!("latest_at deque must be single entry").into()); - } - // unwrap checked just above ^^^ - Ok(cached.iter().next().unwrap()) -} diff --git a/crates/re_query_cache/src/latest_at/to_archetype/background.rs b/crates/re_query_cache/src/latest_at/to_archetype/background.rs deleted file mode 100644 index 2494ac25b0e9..000000000000 --- a/crates/re_query_cache/src/latest_at/to_archetype/background.rs +++ /dev/null @@ -1,66 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs - -#![allow(unused_imports)] -#![allow(unused_parens)] -#![allow(clippy::clone_on_copy)] -#![allow(clippy::cloned_instead_of_copied)] - -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; -use re_types_core::{Archetype, Loggable as _}; -use std::sync::Arc; - -impl crate::ToArchetype for CachedLatestAtResults { - #[inline] - fn to_archetype( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult> { - re_tracing::profile_function!(::name()); - - // --- Required --- - - use re_types::blueprint::components::BackgroundKind; - let kind = match self.get_required(::name()) { - Ok(kind) => kind, - Err(query_err) => return PromiseResult::Ready(Err(query_err)), - }; - let kind = match kind.to_dense::(resolver) { - PromiseResult::Pending => return PromiseResult::Pending, - PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), - PromiseResult::Ready(query_res) => match query_res { - Ok(data) => { - let Some(first) = data.first().cloned() else { - return PromiseResult::Error(std::sync::Arc::new( - re_types_core::DeserializationError::missing_data(), - )); - }; - first - } - Err(query_err) => return PromiseResult::Ready(Err(query_err)), - }, - }; - - // --- Recommended/Optional --- - - use re_types::components::Color; - let color = if let Some(color) = self.get(::name()) { - match color.to_dense::(resolver) { - PromiseResult::Pending => return PromiseResult::Pending, - PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), - PromiseResult::Ready(query_res) => match query_res { - Ok(data) => data.first().cloned(), - Err(query_err) => return PromiseResult::Ready(Err(query_err)), - }, - } - } else { - None - }; - - // --- - - let arch = re_types::blueprint::archetypes::Background { kind, color }; - - PromiseResult::Ready(Ok(arch)) - } -} diff --git a/crates/re_query_cache/src/lib.rs b/crates/re_query_cache/src/lib.rs deleted file mode 100644 index cb995ab447aa..000000000000 --- a/crates/re_query_cache/src/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Caching datastructures for `re_query`. - -mod cache; -mod cache_stats; -mod flat_vec_deque; -mod latest_at; -mod range; - -pub use self::cache::{CacheKey, Caches}; -pub use self::cache_stats::{CachedComponentStats, CachesStats}; -pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; -pub use self::latest_at::{ - CachedLatestAtComponentResults, CachedLatestAtMonoResult, CachedLatestAtResults, -}; -pub use self::range::{CachedRangeComponentResults, CachedRangeData, CachedRangeResults}; - -pub(crate) use self::latest_at::LatestAtCache; -pub(crate) use self::range::{CachedRangeComponentResultsInner, RangeCache}; - -pub use re_query2::{ - clamped_zip::*, range_zip::*, ExtraQueryHistory, Promise, PromiseId, PromiseResolver, - PromiseResult, QueryError, Result, ToArchetype, VisibleHistory, VisibleHistoryBoundary, -}; - -pub mod external { - pub use re_query2; - - pub use paste; - pub use seq_macro; -} - -// --- - -use re_data_store::{LatestAtQuery, RangeQuery}; - -#[derive(Debug)] -pub enum CachedResults { - LatestAt(LatestAtQuery, CachedLatestAtResults), - Range(RangeQuery, CachedRangeResults), -} - -impl From<(LatestAtQuery, CachedLatestAtResults)> for CachedResults { - #[inline] - fn from((query, results): (LatestAtQuery, CachedLatestAtResults)) -> Self { - Self::LatestAt(query, results) - } -} - -impl From<(RangeQuery, CachedRangeResults)> for CachedResults { - #[inline] - fn from((query, results): (RangeQuery, CachedRangeResults)) -> Self { - Self::Range(query, results) - } -} diff --git a/crates/re_query_cache/src/range/mod.rs b/crates/re_query_cache/src/range/mod.rs deleted file mode 100644 index ffb93dd2f720..000000000000 --- a/crates/re_query_cache/src/range/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod query; -mod results; - -pub use self::query::RangeCache; -pub use self::results::{ - CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeData, - CachedRangeResults, -}; diff --git a/crates/re_query_cache/src/range/query.rs b/crates/re_query_cache/src/range/query.rs deleted file mode 100644 index f04664b96c25..000000000000 --- a/crates/re_query_cache/src/range/query.rs +++ /dev/null @@ -1,393 +0,0 @@ -use std::sync::Arc; - -use parking_lot::RwLock; - -use re_data_store::{DataStore, RangeQuery, TimeInt}; -use re_log_types::{EntityPath, TimeRange}; -use re_types_core::ComponentName; -use re_types_core::SizeBytes; - -use crate::{ - CacheKey, CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeResults, - Caches, Promise, -}; - -// --- - -impl Caches { - /// Queries for the given `component_names` using range semantics. - /// - /// See [`CachedRangeResults`] for more information about how to handle the results. - /// - /// This is a cached API -- data will be lazily cached upon access. - pub fn range( - &self, - store: &DataStore, - query: &RangeQuery, - entity_path: &EntityPath, - component_names: impl IntoIterator, - ) -> CachedRangeResults { - re_tracing::profile_function!(entity_path.to_string()); - - let mut results = CachedRangeResults::new(query.clone()); - - for component_name in component_names { - let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); - - let cache = Arc::clone( - self.range_per_cache_key - .write() - .entry(key.clone()) - .or_insert_with(|| Arc::new(RwLock::new(RangeCache::new(key.clone())))), - ); - - let mut cache = cache.write(); - cache.handle_pending_invalidation(); - let cached = cache.range(store, query, entity_path, component_name); - results.add(component_name, cached); - } - - results - } -} - -// --- - -/// Caches the results of `Range` queries for a given [`CacheKey`]. -pub struct RangeCache { - /// For debugging purposes. - pub cache_key: CacheKey, - - /// All temporal data, organized by _data_ time. - /// - /// Query time is irrelevant for range queries. - pub per_data_time: CachedRangeComponentResults, - - /// Everything greater than or equal to this timestamp has been asynchronously invalidated. - /// - /// The next time this cache gets queried, it must remove any entry matching this criteria. - /// `None` indicates that there's no pending invalidation. - /// - /// Invalidation is deferred to query time because it is far more efficient that way: the frame - /// time effectively behaves as a natural micro-batching mechanism. - pub pending_invalidation: Option, -} - -impl RangeCache { - #[inline] - pub fn new(cache_key: CacheKey) -> Self { - Self { - cache_key, - per_data_time: CachedRangeComponentResults::default(), - pending_invalidation: None, - } - } -} - -impl std::fmt::Debug for RangeCache { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - cache_key, - per_data_time, - pending_invalidation: _, - } = self; - - let mut strings = Vec::new(); - - let mut data_time_min = TimeInt::MAX; - let mut data_time_max = TimeInt::MIN; - - { - let per_data_time = per_data_time.read(); - - let per_data_time_indices = &per_data_time.indices; - if let Some(time_front) = per_data_time_indices.front().map(|(t, _)| *t) { - data_time_min = TimeInt::min(data_time_min, time_front); - } - if let Some(time_back) = per_data_time_indices.back().map(|(t, _)| *t) { - data_time_max = TimeInt::max(data_time_max, time_back); - } - } - - strings.push(format!( - "{} ({})", - cache_key - .timeline - .typ() - .format_range_utc(TimeRange::new(data_time_min, data_time_max)), - re_format::format_bytes(per_data_time.total_size_bytes() as _), - )); - - if strings.is_empty() { - return f.write_str(""); - } - - f.write_str(&strings.join("\n").replace("\n\n", "\n")) - } -} - -impl SizeBytes for RangeCache { - #[inline] - fn heap_size_bytes(&self) -> u64 { - let Self { - cache_key, - per_data_time, - pending_invalidation, - } = self; - - cache_key.heap_size_bytes() - + per_data_time.heap_size_bytes() - + pending_invalidation.heap_size_bytes() - } -} - -impl RangeCache { - /// Queries cached range data for a single component. - pub fn range( - &mut self, - store: &DataStore, - query: &RangeQuery, - entity_path: &EntityPath, - component_name: ComponentName, - ) -> CachedRangeComponentResults { - re_tracing::profile_scope!("range", format!("{query:?}")); - - let RangeCache { - cache_key: _, - per_data_time, - pending_invalidation: _, - } = self; - - let mut per_data_time = per_data_time.write(); - - let query_front = per_data_time.compute_front_query(query); - if let Some(query_front) = query_front.as_ref() { - re_tracing::profile_scope!("front"); - - for (data_time, row_id, mut cells) in - store.range(query_front, entity_path, [component_name]) - { - // Soundness: - // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` - // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null - let Some(cell) = cells[0].take() else { - debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); - continue; - }; - - per_data_time - .promises_front - .push(((data_time, row_id), Promise::new(cell))); - per_data_time - .promises_front - .sort_by_key(|(index, _)| *index); - } - } - - if let Some(query_back) = per_data_time.compute_back_query(query, query_front.as_ref()) { - re_tracing::profile_scope!("back"); - - for (data_time, row_id, mut cells) in store - .range(&query_back, entity_path, [component_name]) - // If there's static data to be found, the front query will take care of it already. - .filter(|(data_time, _, _)| !data_time.is_static()) - { - // Soundness: - // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` - // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null - let Some(cell) = cells[0].take() else { - debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); - continue; - }; - - per_data_time - .promises_back - .push(((data_time, row_id), Promise::new(cell))); - per_data_time.promises_back.sort_by_key(|(index, _)| *index); - } - } - - per_data_time.sanity_check(); - drop(per_data_time); - - self.per_data_time.clone_at(query.range()) - } - - pub fn handle_pending_invalidation(&mut self) { - re_tracing::profile_function!(); - - let Self { - cache_key: _, - per_data_time, - pending_invalidation, - } = self; - - let Some(pending_invalidation) = pending_invalidation.take() else { - return; - }; - - per_data_time.write().truncate_at_time(pending_invalidation); - } -} - -// --- - -impl CachedRangeComponentResultsInner { - /// How many _indices_ across this entire cache? - #[inline] - pub fn num_indices(&self) -> u64 { - self.indices.len() as _ - } - - /// How many _instances_ across this entire cache? - #[inline] - pub fn num_instances(&self) -> u64 { - self.cached_dense - .as_ref() - .map_or(0u64, |cached| cached.dyn_num_values() as _) - } - - /// Given a `query`, returns N reduced queries that are sufficient to fill the missing data - /// on both the front & back sides of the cache. - #[inline] - pub fn compute_queries(&self, query: &RangeQuery) -> impl Iterator { - let front = self.compute_front_query(query); - let back = self.compute_back_query(query, front.as_ref()); - front.into_iter().chain(back) - } - - /// Given a `query`, returns a reduced query that is sufficient to fill the missing data - /// on the front side of the cache, or `None` if all the necessary data is already - /// cached. - pub fn compute_front_query(&self, query: &RangeQuery) -> Option { - let mut reduced_query = query.clone(); - - // If nothing has been cached already, then we just want to query everything. - if self.indices.is_empty() - && self.promises_front.is_empty() - && self.promises_back.is_empty() - { - return Some(reduced_query); - } - - // If the cache contains static data, then there's no point in querying anything else since - // static data overrides everything anyway. - if self - .indices - .front() - .map_or(false, |(data_time, _)| data_time.is_static()) - { - return None; - } - - // Otherwise, query for what's missing on the front-side of the cache, while making sure to - // take pending promises into account! - // - // Keep in mind: it is not possible for the cache to contain only part of a given - // timestamp. All entries for a given timestamp are loaded and invalidated atomically, - // whether it's promises or already resolved entries. - - let pending_front_min = self - .promises_front - .first() - .map_or(TimeInt::MAX.as_i64(), |((t, _), _)| { - t.as_i64().saturating_sub(1) - }); - - if let Some(time_range) = self.time_range() { - let time_range_min = i64::min( - time_range.min().as_i64().saturating_sub(1), - pending_front_min, - ); - reduced_query - .range - .set_max(i64::min(reduced_query.range.max().as_i64(), time_range_min)); - } else { - reduced_query.range.set_max(i64::min( - reduced_query.range.max().as_i64(), - pending_front_min, - )); - } - - if reduced_query.range.max() < reduced_query.range.min() { - return None; - } - - Some(reduced_query) - } - - /// Given a `query`, returns a reduced query that is sufficient to fill the missing data - /// on the back side of the cache, or `None` if all the necessary data is already - /// cached. - pub fn compute_back_query( - &self, - query: &RangeQuery, - query_front: Option<&RangeQuery>, - ) -> Option { - let mut reduced_query = query.clone(); - - // If nothing has been cached already, then the front query is already going to take care - // of everything. - if self.indices.is_empty() - && self.promises_front.is_empty() - && self.promises_back.is_empty() - { - return None; - } - - // If the cache contains static data, then there's no point in querying anything else since - // static data overrides everything anyway. - if self - .indices - .front() - .map_or(false, |(data_time, _)| data_time.is_static()) - { - return None; - } - - // Otherwise, query for what's missing on the back-side of the cache, while making sure to - // take pending promises into account! - // - // Keep in mind: it is not possible for the cache to contain only part of a given - // timestamp. All entries for a given timestamp are loaded and invalidated atomically, - // whether it's promises or already resolved entries. - - let pending_back_max = self - .promises_back - .last() - .map_or(TimeInt::MIN.as_i64(), |((t, _), _)| { - t.as_i64().saturating_add(1) - }); - - if let Some(time_range) = self.time_range() { - let time_range_max = i64::max( - time_range.max().as_i64().saturating_add(1), - pending_back_max, - ); - reduced_query - .range - .set_min(i64::max(reduced_query.range.min().as_i64(), time_range_max)); - } else { - reduced_query.range.set_min(i64::max( - reduced_query.range.min().as_i64(), - pending_back_max, - )); - } - - // Back query should never overlap with the front query. - // Reminder: time ranges are all inclusive. - if let Some(query_front) = query_front { - let front_max_plus_one = query_front.range().max().as_i64().saturating_add(1); - let back_min = reduced_query.range().min().as_i64(); - reduced_query - .range - .set_min(i64::max(back_min, front_max_plus_one)); - } - - if reduced_query.range.max() < reduced_query.range.min() { - return None; - } - - Some(reduced_query) - } -} diff --git a/crates/re_query_cache/src/range/results.rs b/crates/re_query_cache/src/range/results.rs deleted file mode 100644 index 5f9bc83e6255..000000000000 --- a/crates/re_query_cache/src/range/results.rs +++ /dev/null @@ -1,819 +0,0 @@ -use std::{ - cell::RefCell, - collections::VecDeque, - ops::Range, - sync::{Arc, OnceLock}, -}; - -use nohash_hasher::IntMap; - -use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use re_data_store::RangeQuery; -use re_log_types::{RowId, TimeInt, TimeRange}; -use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes}; - -use crate::{ - CachedLatestAtComponentResults, ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, - PromiseResult, -}; - -// --- - -/// Cached results for a range query. -/// -/// The data is both deserialized and resolved/converted. -/// -/// Use [`CachedRangeResults::get`], [`CachedRangeResults::get_required`] and -/// [`CachedRangeResults::get_or_empty`] in order to access the results for each individual component. -#[derive(Debug)] -pub struct CachedRangeResults { - pub query: RangeQuery, - pub components: IntMap, -} - -impl CachedRangeResults { - #[inline] - pub(crate) fn new(query: RangeQuery) -> Self { - Self { - query, - components: Default::default(), - } - } - - #[inline] - pub fn contains(&self, component_name: impl Into) -> bool { - self.components.contains_key(&component_name.into()) - } - - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. - #[inline] - pub fn get( - &self, - component_name: impl Into, - ) -> Option<&CachedRangeComponentResults> { - self.components.get(&component_name.into()) - } - - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. - /// - /// Returns an error if the component is not present. - #[inline] - pub fn get_required( - &self, - component_name: impl Into, - ) -> crate::Result<&CachedRangeComponentResults> { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - Ok(component) - } else { - Err(DeserializationError::MissingComponent { - component: component_name, - backtrace: ::backtrace::Backtrace::new_unresolved(), - } - .into()) - } - } - - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. - /// - /// Returns empty results if the component is not present. - #[inline] - pub fn get_or_empty( - &self, - component_name: impl Into, - ) -> &CachedRangeComponentResults { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - component - } else { - CachedRangeComponentResults::empty() - } - } -} - -impl CachedRangeResults { - #[doc(hidden)] - #[inline] - pub fn add(&mut self, component_name: ComponentName, cached: CachedRangeComponentResults) { - self.components.insert(component_name, cached); - } -} - -// --- - -thread_local! { - /// Keeps track of reentrancy counts for the current thread. - /// - /// Used to detect and prevent potential deadlocks when using the cached APIs in work-stealing - /// environments such as Rayon. - static REENTERING: RefCell = const { RefCell::new(0) }; -} - -/// Lazily cached results for a particular component when using a cached range query. -#[derive(Debug)] -pub struct CachedRangeComponentResults { - /// The [`TimeRange`] of the query that was used in order to retrieve these results in the - /// first place. - /// - /// The "original" copy in the cache just stores [`TimeRange::EMPTY`]. It's meaningless. - pub(crate) time_range: TimeRange, - - pub(crate) inner: Arc>, -} - -impl CachedRangeComponentResults { - /// Clones the results while making sure to stamp them with the [`TimeRange`] of the associated query. - #[inline] - pub(crate) fn clone_at(&self, time_range: TimeRange) -> Self { - Self { - time_range, - inner: self.inner.clone(), - } - } -} - -impl CachedRangeComponentResults { - #[inline] - pub fn empty() -> &'static Self { - static EMPTY: OnceLock = OnceLock::new(); - EMPTY.get_or_init(CachedRangeComponentResults::default) - } -} - -impl re_types_core::SizeBytes for CachedRangeComponentResults { - #[inline] - fn heap_size_bytes(&self) -> u64 { - // NOTE: it's all on the heap past this point. - self.inner.read_recursive().total_size_bytes() - } -} - -impl Default for CachedRangeComponentResults { - #[inline] - fn default() -> Self { - Self { - time_range: TimeRange::EMPTY, - inner: Arc::new(RwLock::new(CachedRangeComponentResultsInner::empty())), - } - } -} - -impl std::ops::Deref for CachedRangeComponentResults { - type Target = RwLock; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -/// Helper datastructure to make it possible to convert latest-at results into ranged results. -#[derive(Debug)] -enum Indices<'a> { - Owned(VecDeque<(TimeInt, RowId)>), - Cached(MappedRwLockReadGuard<'a, VecDeque<(TimeInt, RowId)>>), -} - -impl<'a> std::ops::Deref for Indices<'a> { - type Target = VecDeque<(TimeInt, RowId)>; - - #[inline] - fn deref(&self) -> &Self::Target { - match self { - Indices::Owned(data) => data, - Indices::Cached(data) => data, - } - } -} - -/// Helper datastructure to make it possible to convert latest-at results into ranged results. -enum Data<'a, T> { - Owned(Arc), - Cached(MappedRwLockReadGuard<'a, FlatVecDeque>), -} - -impl<'a, T: 'static> std::ops::Deref for Data<'a, T> { - type Target = FlatVecDeque; - - #[inline] - fn deref(&self) -> &Self::Target { - match self { - Data::Owned(data) => { - // Unwrap: only way to instantiate a `Data` is via the `From` impl below which we - // fully control. - data.as_any().downcast_ref().unwrap() - } - Data::Cached(data) => data, - } - } -} - -pub struct CachedRangeData<'a, T> { - // NOTE: Options so we can represent an empty result without having to somehow conjure a mutex - // guard out of thin air. - // - // TODO(Amanieu/parking_lot#289): we need two distinct mapped guards because it's - // impossible to return an owned type in a `parking_lot` guard. - // See . - // indices: Option>>, - indices: Option>, - data: Option>, - - time_range: TimeRange, - front_status: PromiseResult<()>, - back_status: PromiseResult<()>, - - /// Keeps track of reentrancy counts for the current thread. - /// - /// Used to detect and prevent potential deadlocks when using the cached APIs in work-stealing - /// environments such as Rayon. - reentering: &'static std::thread::LocalKey>, -} - -impl<'a, C: Component> CachedRangeData<'a, C> { - /// Useful to abstract over latest-at and ranged results. - #[inline] - pub fn from_latest_at( - resolver: &PromiseResolver, - results: &'a CachedLatestAtComponentResults, - ) -> Self { - let CachedLatestAtComponentResults { - index, - promise: _, - cached_dense, - } = results; - - let status = results.to_dense::(resolver).map(|_| ()); - - Self { - indices: Some(Indices::Owned(vec![*index].into())), - data: cached_dense.get().map(|data| Data::Owned(Arc::clone(data))), - time_range: TimeRange::new(index.0, index.0), - front_status: status.clone(), - back_status: status, - reentering: &REENTERING, - } - } -} - -impl<'a, T> Drop for CachedRangeData<'a, T> { - #[inline] - fn drop(&mut self) { - self.reentering - .with_borrow_mut(|reentering| *reentering = reentering.saturating_sub(1)); - } -} - -impl<'a, T: 'static> CachedRangeData<'a, T> { - /// Returns the current status on both ends of the range. - /// - /// E.g. it is possible that the front-side of the range is still waiting for pending data while - /// the back-side has been fully loaded. - #[inline] - pub fn status(&self) -> (PromiseResult<()>, PromiseResult<()>) { - (self.front_status.clone(), self.back_status.clone()) - } - - #[inline] - pub fn range_indices( - &self, - entry_range: Range, - ) -> impl Iterator { - let indices = match self.indices.as_ref() { - Some(indices) => itertools::Either::Left(indices.range(entry_range)), - None => itertools::Either::Right(std::iter::empty()), - }; - indices - } - - #[inline] - pub fn range_data(&self, entry_range: Range) -> impl Iterator { - match self.data.as_ref() { - Some(indices) => itertools::Either::Left(indices.range(entry_range)), - None => itertools::Either::Right(std::iter::empty()), - } - } - - /// Range both the indices and data by zipping them together. - /// - /// Useful for time-based joins (`range_zip`). - #[inline] - pub fn range_indexed(&self) -> impl Iterator { - let entry_range = self.entry_range(); - itertools::izip!( - self.range_indices(entry_range.clone()), - self.range_data(entry_range) - ) - } - - /// Returns the index range that corresponds to the specified `time_range`. - /// - /// Use the returned range with one of the range iteration methods: - /// - [`Self::range_indices`] - /// - [`Self::range_data`] - /// - [`Self::range_indexed`] - /// - /// Make sure that the bucket hasn't been modified in-between! - /// - /// This is `O(2*log(n))`, so make sure to clone the returned range rather than calling this - /// multiple times. - #[inline] - pub fn entry_range(&self) -> Range { - let Some(indices) = self.indices.as_ref() else { - return 0..0; - }; - - // If there's any static data cached, make sure to look for it explicitly. - // - // Remember: `TimeRange`s can never contain `TimeInt::STATIC`. - let static_override = if matches!(indices.front(), Some((TimeInt::STATIC, _))) { - TimeInt::STATIC - } else { - TimeInt::MAX - }; - - let start_index = indices.partition_point(|(data_time, _)| { - *data_time < TimeInt::min(self.time_range.min(), static_override) - }); - let end_index = indices.partition_point(|(data_time, _)| { - *data_time <= TimeInt::min(self.time_range.max(), static_override) - }); - - start_index..end_index - } -} - -impl CachedRangeComponentResults { - /// Returns the component data as a dense vector. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_dense(&self, resolver: &PromiseResolver) -> CachedRangeData<'_, C> { - // It's tracing the deserialization of an entire range query at once -- it's fine. - re_tracing::profile_function!(); - - // --- Step 1: try and upsert pending data (write lock) --- - - REENTERING.with_borrow_mut(|reentering| *reentering = reentering.saturating_add(1)); - - // Manufactured empty result. - if self.time_range == TimeRange::EMPTY { - return CachedRangeData { - indices: None, - data: None, - time_range: TimeRange::EMPTY, - front_status: PromiseResult::Ready(()), - back_status: PromiseResult::Ready(()), - reentering: &REENTERING, - }; - } - - let mut results = if let Some(results) = self.inner.try_write() { - // The lock was free to grab, nothing else to worry about. - Some(results) - } else { - REENTERING.with_borrow_mut(|reentering| { - if *reentering > 1 { - // The lock is busy, and at least one of the lock holders is the current thread from a - // previous stack frame. - // - // Return `None` so that we skip straight to the read-only part of the operation. - // All the data will be there already, since the previous stack frame already - // took care of upserting it. - None - } else { - // The lock is busy, but it is not held by the current thread. - // Just block until it gets released. - Some(self.inner.write()) - } - }) - }; - - if let Some(results) = &mut results { - // NOTE: This is just a lazy initialization of the underlying deque, because we - // just now finally know the expected type! - if results.cached_dense.is_none() { - results.cached_dense = Some(Box::new(FlatVecDeque::::new())); - } - - if !results.promises_front.is_empty() { - re_tracing::profile_scope!("front"); - - let mut resolved_indices = Vec::with_capacity(results.promises_front.len()); - let mut resolved_data = Vec::with_capacity(results.promises_front.len()); - - // Pop the promises from the end so that if we encounter one that has yet to be - // resolved, we can stop right there and know we have a contiguous range of data - // available up to that point in time. - // - // Reminder: promises are sorted in ascending index order. - while let Some(((data_time, row_id), promise)) = results.promises_front.pop() { - let data = match resolver.resolve(&promise) { - PromiseResult::Pending => { - results.front_status = (data_time, PromiseResult::Pending); - break; - } - PromiseResult::Error(err) => { - results.front_status = (data_time, PromiseResult::Error(err)); - break; - } - PromiseResult::Ready(cell) => { - results.front_status = (data_time, PromiseResult::Ready(())); - match cell - .try_to_native::() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - { - Ok(data) => data, - Err(err) => { - re_log::error!(%err, component=%C::name(), "data deserialization failed -- skipping"); - continue; - } - } - } - }; - - resolved_indices.push((data_time, row_id)); - resolved_data.push(data); - } - - // We resolved the promises in reversed order, so reverse the results back. - resolved_indices.reverse(); - resolved_data.reverse(); - - let results_indices = std::mem::take(&mut results.indices); - results.indices = resolved_indices - .into_iter() - .chain(results_indices) - .collect(); - - let resolved_data = FlatVecDeque::from_vecs(resolved_data); - // Unwraps: the deque is created when entering this function -- we know it's there - // and we know its type. - let cached_dense = results - .cached_dense - .as_mut() - .unwrap() - .as_any_mut() - .downcast_mut::>() - .unwrap(); - cached_dense.push_front_deque(resolved_data); - } - - if !results.promises_back.is_empty() { - re_tracing::profile_scope!("back"); - - let mut resolved_indices = Vec::with_capacity(results.promises_back.len()); - let mut resolved_data = Vec::with_capacity(results.promises_back.len()); - - // Reverse the promises first so we can pop() from the back. - // It's fine, this is a one-time operation in the successful case, and it's extremely fast to do. - // See below why. - // - // Reminder: promises are sorted in ascending index order. - results.promises_back.reverse(); - - // Pop the promises from the end so that if we encounter one that has yet to be - // resolved, we can stop right there and know we have a contiguous range of data - // available up to that point in time. - while let Some(((data_time, index), promise)) = results.promises_back.pop() { - let data = match resolver.resolve(&promise) { - PromiseResult::Pending => { - results.back_status = (data_time, PromiseResult::Pending); - break; - } - PromiseResult::Error(err) => { - results.back_status = (data_time, PromiseResult::Error(err)); - break; - } - PromiseResult::Ready(cell) => { - results.front_status = (data_time, PromiseResult::Ready(())); - match cell - .try_to_native::() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - { - Ok(data) => data, - Err(err) => { - re_log::error!(%err, "data deserialization failed -- skipping"); - continue; - } - } - } - }; - - resolved_indices.push((data_time, index)); - resolved_data.push(data); - } - - // Reverse our reversal. - results.promises_back.reverse(); - - results.indices.extend(resolved_indices); - - let resolved_data = FlatVecDeque::from_vecs(resolved_data); - // Unwraps: the deque is created when entering this function -- we know it's there - // and we know its type. - let cached_dense = results - .cached_dense - .as_mut() - .unwrap() - .as_any_mut() - .downcast_mut::>() - .unwrap(); - cached_dense.push_back_deque(resolved_data); - } - - results.sanity_check(); - } - - // --- Step 2: fetch cached data (read lock) --- - - let results = if let Some(results) = results { - RwLockWriteGuard::downgrade(results) - } else { - // # Multithreading semantics - // - // We need the reentrant lock because query contexts (i.e. space views) generally run on a - // work-stealing thread-pool and might swap a task on one thread with another task on the - // same thread, where both tasks happen to query the same exact data (e.g. cloned space views). - // - // See `REENTERING` comments above for more details. - self.read_recursive() - }; - - let front_status = { - let (results_front_time, results_front_status) = &results.front_status; - let query_front_time = self.time_range.min(); - if query_front_time < *results_front_time { - // If the query covers a larger time span on its front-side than the resulting data, then - // we should forward the status of the resulting data so the caller can know why it's - // been cropped off. - results_front_status.clone() - } else { - PromiseResult::Ready(()) - } - }; - let back_status = { - let (results_back_time, results_back_status) = &results.back_status; - let query_back_time = self.time_range.max(); - if query_back_time > *results_back_time { - // If the query covers a larger time span on its back-side than the resulting data, then - // we should forward the status of the resulting data so the caller can know why it's - // been cropped off. - results_back_status.clone() - } else { - PromiseResult::Ready(()) - } - }; - - // TODO(Amanieu/parking_lot#289): we need two distinct mapped guards because it's - // impossible to return an owned type in a `parking_lot` guard. - // See . - let indices = RwLockReadGuard::map(results, |results| &results.indices); - let data = RwLockReadGuard::map(self.inner.read_recursive(), |results| { - // Unwraps: the data is created when entering this function -- we know it's there - // and we know its type. - results - .cached_dense - .as_ref() - .unwrap() - .as_any() - .downcast_ref::>() - .unwrap() - }); - - CachedRangeData { - indices: Some(Indices::Cached(indices)), - data: Some(Data::Cached(data)), - time_range: self.time_range, - front_status, - back_status, - reentering: &REENTERING, - } - } -} - -// --- - -/// Lazily cached results for a particular component when using a cached range query. -pub struct CachedRangeComponentResultsInner { - pub(crate) indices: VecDeque<(TimeInt, RowId)>, - - /// All the pending promises that must resolved in order to fill the missing data on the - /// front-side of the ringbuffer (i.e. further back in time). - /// - /// Always sorted in ascending index order ([`TimeInt`] + [`RowId`] pair). - pub(crate) promises_front: Vec<((TimeInt, RowId), Promise)>, - - /// All the pending promises that must resolved in order to fill the missing data on the - /// back-side of the ringbuffer (i.e. the most recent data). - /// - /// Always sorted in ascending index order ([`TimeInt`] + [`RowId`] pair). - pub(crate) promises_back: Vec<((TimeInt, RowId), Promise)>, - - /// Keeps track of the status of the data on the front-side of the cache. - pub(crate) front_status: (TimeInt, PromiseResult<()>), - - /// Keeps track of the status of the data on the back-side of the cache. - pub(crate) back_status: (TimeInt, PromiseResult<()>), - - /// The resolved, converted, deserialized dense data. - /// - /// This has to be option because we have no way of initializing the underlying trait object - /// until we know what the actual native type that the caller expects is. - pub(crate) cached_dense: Option>, -} - -impl SizeBytes for CachedRangeComponentResultsInner { - #[inline] - fn heap_size_bytes(&self) -> u64 { - let Self { - indices, - promises_front, - promises_back, - front_status: _, - back_status: _, - cached_dense, - } = self; - - indices.total_size_bytes() - + promises_front.total_size_bytes() - + promises_back.total_size_bytes() - + cached_dense - .as_ref() - .map_or(0, |data| data.dyn_total_size_bytes()) - } -} - -impl std::fmt::Debug for CachedRangeComponentResultsInner { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - indices, - promises_front: _, - promises_back: _, - front_status: _, - back_status: _, - cached_dense: _, // we can't, we don't know the type - } = self; - - if indices.is_empty() { - f.write_str("") - } else { - // Unwrap: checked above. - let index_start = indices.front().unwrap(); - let index_end = indices.back().unwrap(); - f.write_fmt(format_args!( - "[{:?}#{} .. {:?}#{}] {}", - index_start.0, - index_start.1, - index_end.0, - index_end.1, - re_format::format_bytes(self.total_size_bytes() as _) - )) - } - } -} - -impl CachedRangeComponentResultsInner { - #[inline] - pub const fn empty() -> Self { - Self { - indices: VecDeque::new(), - promises_front: Vec::new(), - promises_back: Vec::new(), - front_status: (TimeInt::MIN, PromiseResult::Ready(())), - back_status: (TimeInt::MAX, PromiseResult::Ready(())), - cached_dense: None, - } - } - - /// No-op in release. - #[inline] - pub fn sanity_check(&self) { - if !cfg!(debug_assertions) { - return; - } - - let Self { - indices, - promises_front, - promises_back, - front_status: _, - back_status: _, - cached_dense, - } = self; - - assert!( - promises_front.windows(2).all(|promises| { - let index_left = promises[0].0; - let index_right = promises[1].0; - index_left <= index_right - }), - "front promises must always be sorted in ascending index order" - ); - if let (Some(p_index), Some(i_index)) = ( - promises_front.last().map(|(index, _)| index), - indices.front(), - ) { - assert!( - p_index < i_index, - "the rightmost front promise must have an index smaller than the leftmost data index ({p_index:?} < {i_index:?})", - ); - } - - assert!( - promises_back.windows(2).all(|promises| { - let index_left = promises[0].0; - let index_right = promises[1].0; - index_left <= index_right - }), - "back promises must always be sorted in ascending index order" - ); - if let (Some(p_index), Some(i_index)) = - (promises_back.last().map(|(index, _)| index), indices.back()) - { - assert!( - i_index < p_index, - "the leftmost back promise must have an index larger than the rightmost data index ({i_index:?} < {p_index:?})", - ); - } - - if let Some(dense) = cached_dense.as_ref() { - assert_eq!(indices.len(), dense.dyn_num_entries()); - } - } - - /// Returns the time range covered by the cached data. - /// - /// Reminder: [`TimeInt::STATIC`] is never included in [`TimeRange`]s. - #[inline] - pub fn time_range(&self) -> Option { - let first_time = self.indices.front().map(|(t, _)| *t)?; - let last_time = self.indices.back().map(|(t, _)| *t)?; - Some(TimeRange::new(first_time, last_time)) - } - - #[inline] - pub fn contains_data_time(&self, data_time: TimeInt) -> bool { - let first_time = self.indices.front().map_or(&TimeInt::MAX, |(t, _)| t); - let last_time = self.indices.back().map_or(&TimeInt::MIN, |(t, _)| t); - *first_time <= data_time && data_time <= *last_time - } - - /// Removes everything from the bucket that corresponds to a time equal or greater than the - /// specified `threshold`. - /// - /// Returns the number of bytes removed. - #[inline] - pub fn truncate_at_time(&mut self, threshold: TimeInt) { - re_tracing::profile_function!(); - - let time_range = self.time_range(); - - let Self { - indices, - promises_front, - promises_back, - front_status, - back_status, - cached_dense, - } = self; - - if front_status.0 >= threshold { - let time_min = time_range.map_or(TimeInt::MIN, |range| range.min()); - *front_status = (time_min, PromiseResult::Ready(())); - } - if back_status.0 >= threshold { - let time_max = time_range.map_or(TimeInt::MAX, |range| range.max()); - *back_status = (time_max, PromiseResult::Ready(())); - } - - // NOTE: promises are kept ascendingly sorted by index - { - let threshold_idx = - promises_front.partition_point(|((data_time, _), _)| *data_time < threshold); - promises_front.truncate(threshold_idx); - - let threshold_idx = - promises_back.partition_point(|((data_time, _), _)| *data_time < threshold); - promises_back.truncate(threshold_idx); - } - - let threshold_idx = indices.partition_point(|(data_time, _)| data_time < &threshold); - { - indices.truncate(threshold_idx); - if let Some(data) = cached_dense { - data.dyn_truncate(threshold_idx); - } - } - - self.sanity_check(); - } - - #[inline] - pub fn clear(&mut self) { - *self = Self::empty(); - } -} diff --git a/crates/re_query_cache/tests/latest_at.rs b/crates/re_query_cache/tests/latest_at.rs deleted file mode 100644 index 4073c5ec7e53..000000000000 --- a/crates/re_query_cache/tests/latest_at.rs +++ /dev/null @@ -1,526 +0,0 @@ -//! Contains: -//! - A 1:1 port of the tests in `crates/re_query/tests/archetype_query_tests.rs`, with caching enabled. -//! - Invalidation tests. - -use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; -use re_log_types::{ - build_frame_nr, - example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, -}; -use re_query2::PromiseResolver; -use re_query_cache::Caches; -use re_types::Archetype as _; -use re_types_core::{components::InstanceKey, Loggable as _}; - -// --- - -#[test] -fn simple_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn static_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance.. statically! - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - TimePoint::default(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn no_instance_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign them colors with explicit instances - let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn missing_column_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn splatted_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign all of them a color via splat - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn invalidation() { - let entity_path = "point"; - - let test_invalidation = |query: LatestAtQuery, - present_data_timepoint: TimePoint, - past_data_timepoint: TimePoint, - future_data_timepoint: TimePoint| { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(1, 2, 3)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify present --- - - // Modify the PoV component - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint, - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify past --- - - // Modify the PoV component - let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, past_data_timepoint, 2, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify future --- - - // Modify the PoV component - let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - future_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(16, 17, 18)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - }; - - let timeless = TimePoint::default(); - let frame_122 = build_frame_nr(122); - let frame_123 = build_frame_nr(123); - let frame_124 = build_frame_nr(124); - - test_invalidation( - LatestAtQuery::new(frame_123.0, frame_123.1), - [frame_123].into(), - [frame_122].into(), - [frame_124].into(), - ); - - test_invalidation( - LatestAtQuery::new(frame_123.0, frame_123.1), - [frame_123].into(), - timeless, - [frame_124].into(), - ); -} - -// Test the following scenario: -// ```py -// rr.log("points", rr.Points3D([1, 2, 3]), static=True) -// -// # Do first query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[] -// -// rr.set_time(2) -// rr.log_components("points", rr.components.MyColor(0xFF0000)) -// -// # Do second query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0xFF0000] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x0000FF)) -// -// # Do third query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x0000FF] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x00FF00)) -// -// # Do fourth query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x00FF00] -// ``` -#[test] -fn invalidation_of_future_optionals() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - let frame2 = [build_frame_nr(2)]; - let frame3 = [build_frame_nr(3)]; - - let query_time = [build_frame_nr(9999)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame2, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame3, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame3, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn static_invalidation() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - - let query_time = [build_frame_nr(9999)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timeless.clone(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timeless, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -// --- - -fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { - caches.on_events(&[store.insert_row(row).unwrap()]); -} - -fn query_and_compare( - caches: &Caches, - store: &DataStore, - query: &LatestAtQuery, - entity_path: &EntityPath, -) { - re_log::setup_logging(); - - let resolver = PromiseResolver::default(); - - for _ in 0..3 { - let cached = caches.latest_at( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let cached_points = cached.get_required(MyPoint::name()).unwrap(); - let cached_point_data = cached_points - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let cached_colors = cached.get_or_empty(MyColor::name()); - let cached_color_data = cached_colors - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let expected = re_query2::latest_at( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let expected_points = expected.get_required(MyPoint::name()).unwrap(); - let expected_point_data = expected_points - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let expected_colors = expected.get_or_empty(MyColor::name()); - let expected_color_data = expected_colors - .to_dense::(&resolver) - .flatten() - .unwrap(); - - // eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!(expected.compound_index, cached.compound_index); - similar_asserts::assert_eq!(expected_point_data, cached_point_data); - similar_asserts::assert_eq!(expected_color_data, cached_color_data); - } -} diff --git a/crates/re_query_cache/tests/range.rs b/crates/re_query_cache/tests/range.rs deleted file mode 100644 index eb7380c8a1d0..000000000000 --- a/crates/re_query_cache/tests/range.rs +++ /dev/null @@ -1,586 +0,0 @@ -use itertools::{izip, Itertools as _}; - -use re_data_store::{DataStore, RangeQuery, StoreSubscriber as _, TimeInt, TimeRange}; -use re_log_types::{ - build_frame_nr, - example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, -}; -use re_query_cache::{Caches, PromiseResolver, PromiseResult}; -use re_types::{components::InstanceKey, Archetype}; -use re_types_core::Loggable as _; - -// --- - -#[test] -fn simple_range() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - Ok(()) -} - -#[test] -fn static_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - colors.clone(), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - colors.clone(), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - // The inclusion of `timepoint1` means latest-at semantics will fall back to timeless data! - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Third test: `[-inf, +inf]` --- - - let query = - re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); - - query_and_compare(&caches, &store, &query, &entity_path); -} - -#[test] -fn simple_splatted_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); -} - -#[test] -fn invalidation() { - let entity_path = "point"; - - let test_invalidation = |query: RangeQuery, - present_data_timepoint: TimePoint, - past_data_timepoint: TimePoint, - future_data_timepoint: TimePoint| { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(1, 2, 3)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify present --- - - // Modify the PoV component - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint, - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify past --- - - // Modify the PoV component - let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify future --- - - // Modify the PoV component - let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - future_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(16, 17, 18)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - }; - - let timeless = TimePoint::default(); - let frame_122 = build_frame_nr(122); - let frame_123 = build_frame_nr(123); - let frame_124 = build_frame_nr(124); - - test_invalidation( - RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), - [frame_123].into(), - [frame_122].into(), - [frame_124].into(), - ); - - test_invalidation( - RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), - [frame_123].into(), - timeless, - [frame_124].into(), - ); -} - -// Test the following scenario: -// ```py -// rr.log("points", rr.Points3D([1, 2, 3]), static=True) -// -// # Do first query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[] -// -// rr.set_time(2) -// rr.log_components("points", rr.components.MyColor(0xFF0000)) -// -// # Do second query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0xFF0000] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x0000FF)) -// -// # Do third query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x0000FF] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x00FF00)) -// -// # Do fourth query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x00FF00] -// ``` -#[test] -fn invalidation_of_future_optionals() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - let frame2 = [build_frame_nr(2)]; - let frame3 = [build_frame_nr(3)]; - - let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn invalidation_static() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - - let frame0 = [build_frame_nr(TimeInt::ZERO)]; - let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -// --- - -fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { - caches.on_events(&[store.insert_row(row).unwrap()]); -} - -fn query_and_compare( - caches: &Caches, - store: &DataStore, - query: &RangeQuery, - entity_path: &EntityPath, -) { - re_log::setup_logging(); - - let resolver = PromiseResolver::default(); - - for _ in 0..3 { - let cached = caches.range( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let cached_all_points = cached - .get_required(MyPoint::name()) - .unwrap() - .to_dense::(&resolver); - assert!(matches!( - cached_all_points.status(), - (PromiseResult::Ready(()), PromiseResult::Ready(())), - )); - let cached_all_points_indexed = cached_all_points.range_indexed(); - - let cached_all_colors = cached - .get_or_empty(MyColor::name()) - .to_dense::(&resolver); - assert!(matches!( - cached_all_colors.status(), - (PromiseResult::Ready(()), PromiseResult::Ready(())), - )); - let cached_all_colors_indexed = cached_all_colors.range_indexed(); - - let expected = re_query2::range( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let expected_all_points = expected.get_required(MyPoint::name()).unwrap(); - let expected_all_points_indices = expected_all_points.indices(); - let expected_all_points_data = expected_all_points - .to_dense::(&resolver) - .into_iter() - .map(|batch| batch.flatten().unwrap()) - .collect_vec(); - let expected_all_points_indexed = - izip!(expected_all_points_indices, expected_all_points_data); - - let expected_all_colors = expected.get_or_empty(MyColor::name()); - let expected_all_colors_indices = expected_all_colors.indices(); - let expected_all_colors_data = expected_all_colors - .to_dense::(&resolver) - .into_iter() - .map(|batch| batch.flatten().unwrap()) - .collect_vec(); - let expected_all_colors_indexed = - izip!(expected_all_colors_indices, expected_all_colors_data); - - eprintln!("{query:?}"); - eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!( - expected_all_points_indexed - .map(|(index, data)| (*index, data)) - .collect_vec(), - cached_all_points_indexed - .map(|(index, data)| (*index, data.to_vec())) - .collect_vec(), - ); - - similar_asserts::assert_eq!( - expected_all_colors_indexed - .map(|(index, data)| (*index, data)) - .collect_vec(), - cached_all_colors_indexed - .map(|(index, data)| (*index, data.to_vec())) - .collect_vec(), - ); - } -} diff --git a/crates/re_space_view/Cargo.toml b/crates/re_space_view/Cargo.toml index 441e96bc95ea..cc5bab4a1c02 100644 --- a/crates/re_space_view/Cargo.toml +++ b/crates/re_space_view/Cargo.toml @@ -27,7 +27,7 @@ re_log_types.workspace = true re_data_store.workspace = true re_entity_db.workspace = true re_query.workspace = true -re_query_cache.workspace = true +re_query2.workspace = true re_tracing.workspace = true re_types_core.workspace = true re_types.workspace = true diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index cd9b86fa22d7..bcf94714852f 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -1,6 +1,6 @@ use itertools::{FoldWhile, Itertools}; use nohash_hasher::IntMap; -use re_entity_db::external::re_query_cache::PromiseResult; +use re_entity_db::external::re_query2::PromiseResult; use crate::SpaceViewContents; use re_data_store::LatestAtQuery; diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 2b4e94cd853e..4ed247703593 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -3,7 +3,7 @@ use slotmap::SlotMap; use smallvec::SmallVec; use re_entity_db::{ - external::{re_data_store::LatestAtQuery, re_query_cache::PromiseResult}, + external::{re_data_store::LatestAtQuery, re_query2::PromiseResult}, EntityDb, EntityProperties, EntityPropertiesComponent, EntityPropertyMap, EntityTree, }; use re_log_types::{ diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 198f150f1430..961fb8659aad 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -1,6 +1,6 @@ use re_data_store::LatestAtQuery; use re_entity_db::{ - external::re_query_cache::{CachedLatestAtResults, PromiseResult, ToArchetype}, + external::re_query2::{CachedLatestAtResults, PromiseResult, ToArchetype}, EntityDb, }; use re_log_types::EntityPath; diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs index 2c2af59f7363..cfa4590fbd06 100644 --- a/crates/re_space_view/src/visual_time_range.rs +++ b/crates/re_space_view/src/visual_time_range.rs @@ -8,7 +8,7 @@ //! to reduce the amount of changes in code that is likely to be refactored soon anyways. use re_log_types::TimeRange; -use re_query_cache::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +use re_query2::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; use re_types::blueprint::{ components::VisibleTimeRange, datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}, diff --git a/crates/re_space_view_dataframe/Cargo.toml b/crates/re_space_view_dataframe/Cargo.toml index 7ba423482c19..969405f37a85 100644 --- a/crates/re_space_view_dataframe/Cargo.toml +++ b/crates/re_space_view_dataframe/Cargo.toml @@ -24,7 +24,7 @@ re_data_ui.workspace = true re_entity_db.workspace = true re_log_types.workspace = true re_query.workspace = true -re_query_cache.workspace = true +re_query2.workspace = true re_renderer.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_space_view_spatial/Cargo.toml b/crates/re_space_view_spatial/Cargo.toml index 2bf7b4745914..3ac935a86647 100644 --- a/crates/re_space_view_spatial/Cargo.toml +++ b/crates/re_space_view_spatial/Cargo.toml @@ -27,7 +27,7 @@ re_format.workspace = true re_log_types.workspace = true re_log.workspace = true re_query.workspace = true -re_query_cache.workspace = true +re_query2.workspace = true re_renderer = { workspace = true, features = [ "import-gltf", "import-obj", diff --git a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs index f7ed6472e5de..7f16b7516d3f 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x6; +use re_query2::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows2D, diff --git a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs index 05fdb1ef9764..465ad511cda1 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x6; +use re_query2::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows3D, diff --git a/crates/re_space_view_spatial/src/visualizers/assets3d.rs b/crates/re_space_view_spatial/src/visualizers/assets3d.rs index fd14f33490a1..195f03785d69 100644 --- a/crates/re_space_view_spatial/src/visualizers/assets3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/assets3d.rs @@ -1,6 +1,6 @@ use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query_cache::range_zip_1x2; +use re_query2::range_zip_1x2; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Asset3D, diff --git a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs index 07fb7d9b9acd..442b1007a43d 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x6; +use re_query2::range_zip_1x6; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes2D, diff --git a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs index 8819231a5aea..e4f1a552cbf3 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x7; +use re_query2::range_zip_1x7; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes3D, diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 7b341e5064a6..6db63aba7a39 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -2,7 +2,7 @@ use itertools::Either; use re_data_store::{LatestAtQuery, RangeQuery}; use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::{EntityPath, TimeInt, Timeline}; -use re_query_cache::{CachedResults, ExtraQueryHistory}; +use re_query2::{CachedResults, ExtraQueryHistory}; use re_renderer::DepthOffset; use re_space_view::query_visual_history; use re_types::Archetype; diff --git a/crates/re_space_view_spatial/src/visualizers/images.rs b/crates/re_space_view_spatial/src/visualizers/images.rs index 82ef54742c40..c638b3d03996 100644 --- a/crates/re_space_view_spatial/src/visualizers/images.rs +++ b/crates/re_space_view_spatial/src/visualizers/images.rs @@ -6,7 +6,7 @@ use nohash_hasher::IntSet; use re_entity_db::{EntityPath, EntityProperties}; use re_log_types::{EntityPathHash, RowId, TimeInt}; -use re_query_cache::range_zip_1x2; +use re_query2::range_zip_1x2; use re_renderer::{ renderer::{DepthCloud, DepthClouds, RectangleOptions, TexturedRect}, Colormap, diff --git a/crates/re_space_view_spatial/src/visualizers/lines2d.rs b/crates/re_space_view_spatial/src/visualizers/lines2d.rs index e7c688eab4a7..2e86c40a1c13 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query2::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::LineStrips2D, diff --git a/crates/re_space_view_spatial/src/visualizers/lines3d.rs b/crates/re_space_view_spatial/src/visualizers/lines3d.rs index 9bbb657425f9..6be3cc460879 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query2::range_zip_1x5; use re_renderer::PickingLayerInstanceId; use re_types::{ archetypes::LineStrips3D, diff --git a/crates/re_space_view_spatial/src/visualizers/meshes.rs b/crates/re_space_view_spatial/src/visualizers/meshes.rs index 89d28eadd512..651352f0efc7 100644 --- a/crates/re_space_view_spatial/src/visualizers/meshes.rs +++ b/crates/re_space_view_spatial/src/visualizers/meshes.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query_cache::range_zip_1x7; +use re_query2::range_zip_1x7; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Mesh3D, diff --git a/crates/re_space_view_spatial/src/visualizers/points2d.rs b/crates/re_space_view_spatial/src/visualizers/points2d.rs index 31bc5389316c..efc82d15b3c8 100644 --- a/crates/re_space_view_spatial/src/visualizers/points2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points2d.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query2::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points2D, diff --git a/crates/re_space_view_spatial/src/visualizers/points3d.rs b/crates/re_space_view_spatial/src/visualizers/points3d.rs index 2d70126c2c5b..a4d1f5376676 100644 --- a/crates/re_space_view_spatial/src/visualizers/points3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points3d.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query2::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points3D, diff --git a/crates/re_space_view_spatial/src/visualizers/results_ext.rs b/crates/re_space_view_spatial/src/visualizers/results_ext.rs index 27474a9cc886..7481f173e800 100644 --- a/crates/re_space_view_spatial/src/visualizers/results_ext.rs +++ b/crates/re_space_view_spatial/src/visualizers/results_ext.rs @@ -1,4 +1,4 @@ -use re_query_cache::{ +use re_query2::{ CachedLatestAtResults, CachedRangeData, CachedRangeResults, CachedResults, PromiseResolver, PromiseResult, }; @@ -14,19 +14,19 @@ pub trait CachedRangeResultsExt { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>>; + ) -> Option>>; fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result>; + ) -> re_query2::Result>; } impl CachedRangeResultsExt for CachedResults { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { match self { CachedResults::LatestAt(_, results) => results.get_dense(resolver), CachedResults::Range(_, results) => results.get_dense(resolver), @@ -36,7 +36,7 @@ impl CachedRangeResultsExt for CachedResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result> { + ) -> re_query2::Result> { match self { CachedResults::LatestAt(_, results) => results.get_or_empty_dense(resolver), CachedResults::Range(_, results) => results.get_or_empty_dense(resolver), @@ -49,20 +49,20 @@ impl CachedRangeResultsExt for CachedRangeResults { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?.to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) + return Some(Err(re_query2::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) + return Some(Err(re_query2::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -74,17 +74,17 @@ impl CachedRangeResultsExt for CachedRangeResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result> { + ) -> re_query2::Result> { let results = self.get_or_empty(C::name()).to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -97,7 +97,7 @@ impl CachedRangeResultsExt for CachedLatestAtResults { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?; let data = CachedRangeData::from_latest_at(resolver, results); @@ -105,13 +105,13 @@ impl CachedRangeResultsExt for CachedLatestAtResults { let (front_status, back_status) = data.status(); match front_status { PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) + return Some(Err(re_query2::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) + return Some(Err(re_query2::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -123,18 +123,18 @@ impl CachedRangeResultsExt for CachedLatestAtResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result> { + ) -> re_query2::Result> { let results = self.get_or_empty(C::name()); let data = CachedRangeData::from_latest_at(resolver, results); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); match front_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_tensor/src/visualizer_system.rs b/crates/re_space_view_tensor/src/visualizer_system.rs index b22578d5da31..7c4e4ec1faf6 100644 --- a/crates/re_space_view_tensor/src/visualizer_system.rs +++ b/crates/re_space_view_tensor/src/visualizer_system.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::CachedLatestAtMonoResult, EntityPath}; +use re_entity_db::{external::re_query2::CachedLatestAtMonoResult, EntityPath}; use re_log_types::RowId; use re_types::{archetypes::Tensor, components::TensorData, tensor_data::DecodedTensor}; use re_viewer_context::{ diff --git a/crates/re_space_view_text_document/src/visualizer_system.rs b/crates/re_space_view_text_document/src/visualizer_system.rs index 75e06692813c..01eb0207789a 100644 --- a/crates/re_space_view_text_document/src/visualizer_system.rs +++ b/crates/re_space_view_text_document/src/visualizer_system.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_space_view::external::re_query_cache::PromiseResult; +use re_space_view::external::re_query2::PromiseResult; use re_types::{archetypes::TextDocument, components}; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, diff --git a/crates/re_space_view_text_log/Cargo.toml b/crates/re_space_view_text_log/Cargo.toml index d1343494859e..7faaa5d68cf0 100644 --- a/crates/re_space_view_text_log/Cargo.toml +++ b/crates/re_space_view_text_log/Cargo.toml @@ -24,7 +24,7 @@ re_data_ui.workspace = true re_entity_db.workspace = true re_log_types.workspace = true re_log.workspace = true -re_query_cache.workspace = true +re_query2.workspace = true re_renderer.workspace = true re_tracing.workspace = true re_types.workspace = true diff --git a/crates/re_space_view_text_log/src/visualizer_system.rs b/crates/re_space_view_text_log/src/visualizer_system.rs index a06212b65488..ade23fb25dbc 100644 --- a/crates/re_space_view_text_log/src/visualizer_system.rs +++ b/crates/re_space_view_text_log/src/visualizer_system.rs @@ -1,7 +1,7 @@ use re_data_store::TimeRange; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query_cache::{clamped_zip_1x2, range_zip_1x2, CachedRangeData, PromiseResult}; +use re_query2::{clamped_zip_1x2, range_zip_1x2, CachedRangeData, PromiseResult}; use re_types::{ archetypes::TextLog, components::{Color, Text, TextLogLevel}, @@ -129,16 +129,16 @@ impl VisualizerSystem for TextLogSystem { #[inline] fn check_range<'a, C: Component>( results: &'a CachedRangeData<'a, C>, -) -> re_query_cache::Result<()> { +) -> re_query2::Result<()> { let (front_status, back_status) = results.status(); match front_status { PromiseResult::Pending => return Ok(()), - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Pending => return Ok(()), - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_time_series/Cargo.toml b/crates/re_space_view_time_series/Cargo.toml index 16faadc51266..8b0b69d7f89f 100644 --- a/crates/re_space_view_time_series/Cargo.toml +++ b/crates/re_space_view_time_series/Cargo.toml @@ -24,7 +24,7 @@ re_format.workspace = true re_log.workspace = true re_log_types.workspace = true re_query.workspace = true -re_query_cache.workspace = true +re_query2.workspace = true re_renderer.workspace = true re_space_view.workspace = true re_tracing.workspace = true diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 814f7369d249..91940b9c0f2d 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -1,5 +1,5 @@ use itertools::Itertools as _; -use re_query_cache::{PromiseResult, QueryError}; +use re_query2::{PromiseResult, QueryError}; use re_types::archetypes; use re_types::{ archetypes::SeriesLine, @@ -259,7 +259,7 @@ fn load_series( .map(|index| (index, ())); let all_frames = - re_query_cache::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) + re_query2::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) .enumerate(); for (i, (_index, _scalars, colors)) in all_frames { @@ -296,7 +296,7 @@ fn load_series( .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( + let all_frames = re_query2::range_zip_1x1( all_scalars_indexed, all_stroke_widths.range_indexed(), ) diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index 6b5b0c997ed7..2625f52dd368 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -1,6 +1,6 @@ use itertools::Itertools as _; -use re_query_cache::{PromiseResult, QueryError}; +use re_query2::{PromiseResult, QueryError}; use re_types::{ archetypes::{self, SeriesPoint}, components::{Color, MarkerShape, MarkerSize, Name, Scalar}, @@ -217,7 +217,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( + let all_frames = re_query2::range_zip_1x1( all_scalars_indexed, all_colors.range_indexed(), ) @@ -257,7 +257,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( + let all_frames = re_query2::range_zip_1x1( all_scalars_indexed, all_marker_sizes.range_indexed(), ) @@ -289,7 +289,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( + let all_frames = re_query2::range_zip_1x1( all_scalars_indexed, all_marker_shapes.range_indexed(), ) diff --git a/crates/re_types_builder/src/codegen/rust/to_archetype.rs b/crates/re_types_builder/src/codegen/rust/to_archetype.rs index fac93e1fed22..5f74b89901c6 100644 --- a/crates/re_types_builder/src/codegen/rust/to_archetype.rs +++ b/crates/re_types_builder/src/codegen/rust/to_archetype.rs @@ -1,4 +1,4 @@ -//! Generates code in `re_query_cache` so that cached results can easily be converted to +//! Generates code in `re_query2` so that cached results can easily be converted to //! ready-to-use archetypes. //! //! That code needs to be generated directly in the caching crates as it needs access to the cached @@ -35,7 +35,7 @@ fn generate_mod( files_to_write: &mut BTreeMap, ) { let generated_path = - Utf8PathBuf::from("crates/re_query_cache/src/latest_at/to_archetype/mod.rs"); + Utf8PathBuf::from("crates/re_query2/src/latest_at/to_archetype/mod.rs"); let mut code = String::new(); code.push_str(&format!("// {}\n\n", crate::codegen::autogen_warning!())); @@ -62,7 +62,7 @@ fn generate_impls( objects: &Objects, files_to_write: &mut BTreeMap, ) { - let generated_path = Utf8PathBuf::from("crates/re_query_cache/src/latest_at/to_archetype"); + let generated_path = Utf8PathBuf::from("crates/re_query2/src/latest_at/to_archetype"); let quoted_imports = quote! { use std::sync::Arc; diff --git a/crates/re_viewer/Cargo.toml b/crates/re_viewer/Cargo.toml index 2168bec9fe30..6cfdac38b458 100644 --- a/crates/re_viewer/Cargo.toml +++ b/crates/re_viewer/Cargo.toml @@ -53,7 +53,7 @@ re_log_encoding = { workspace = true, features = [ ] } re_log_types.workspace = true re_memory.workspace = true -re_query_cache.workspace = true +re_query2.workspace = true re_renderer = { workspace = true, default-features = false } re_smart_channel.workspace = true re_space_view.workspace = true diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs index 85b2747bf3e1..1df586ea3d14 100644 --- a/crates/re_viewer/src/lib.rs +++ b/crates/re_viewer/src/lib.rs @@ -34,7 +34,7 @@ pub mod external { pub use {eframe, egui}; pub use { re_data_store, re_data_store::external::*, re_entity_db, re_log, re_log_types, re_memory, - re_query_cache, re_renderer, re_types, re_ui, re_viewer_context, + re_query2, re_renderer, re_types, re_ui, re_viewer_context, re_viewer_context::external::*, re_viewport, re_viewport::external::*, }; } diff --git a/crates/re_viewer/src/ui/memory_panel.rs b/crates/re_viewer/src/ui/memory_panel.rs index d60b680732b3..c252eda89fe9 100644 --- a/crates/re_viewer/src/ui/memory_panel.rs +++ b/crates/re_viewer/src/ui/memory_panel.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use re_data_store::{DataStoreConfig, DataStoreRowStats, DataStoreStats}; use re_format::{format_bytes, format_uint}; use re_memory::{util::sec_since_start, MemoryHistory, MemoryLimit, MemoryUse}; -use re_query_cache::{CachedComponentStats, CachesStats}; +use re_query2::{CachedComponentStats, CachesStats}; use re_renderer::WgpuResourcePoolStatistics; use re_viewer_context::store_hub::StoreHubStats; diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 835b3c5aec4c..816b95a168ad 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -24,7 +24,7 @@ re_data_store.workspace = true re_entity_db = { workspace = true, features = ["serde"] } re_log_types.workspace = true re_log.workspace = true -re_query_cache.workspace = true +re_query2.workspace = true re_query.workspace = true re_renderer.workspace = true re_smart_channel.workspace = true diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index 85acff5c5f77..b98255c1874c 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use re_data_store::LatestAtQuery; use re_entity_db::{ - external::re_query_cache::CachedLatestAtComponentResults, EntityDb, EntityPath, + external::re_query2::CachedLatestAtComponentResults, EntityDb, EntityPath, }; use re_log_types::DataCell; use re_types::{components::InstanceKey, ComponentName, Loggable as _}; diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index 0d21d88d3dfd..3a78f8482d08 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -199,7 +199,7 @@ pub fn resolve_mono_instance_path( [component], ); if let Some(results) = results.get(component) { - if let re_query_cache::PromiseResult::Ready(cell) = + if let re_query2::PromiseResult::Ready(cell) = results.resolved(entity_db.resolver()) { if cell.num_instances() > 1 { diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 17632a2aa4ff..61c60dfadf77 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -49,7 +49,7 @@ pub enum SpaceViewSystemExecutionError { QueryError(#[from] re_query::QueryError), #[error(transparent)] - QueryError2(#[from] re_query_cache::QueryError), + QueryError2(#[from] re_query2::QueryError), #[error(transparent)] DeserializationError(#[from] re_types::DeserializationError), diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index f90c08ee3611..871c3d79b8d9 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -7,7 +7,7 @@ use re_data_store::StoreGeneration; use re_data_store::{DataStoreConfig, DataStoreStats}; use re_entity_db::{EntityDb, StoreBundle}; use re_log_types::{ApplicationId, StoreId, StoreKind}; -use re_query_cache::CachesStats; +use re_query2::CachesStats; use crate::StoreContext; diff --git a/crates/re_viewport/src/container.rs b/crates/re_viewport/src/container.rs index b5e2381ef41f..6a9c29da7a8e 100644 --- a/crates/re_viewport/src/container.rs +++ b/crates/re_viewport/src/container.rs @@ -2,7 +2,7 @@ use ahash::HashMap; use egui_tiles::TileId; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::PromiseResult, EntityDb}; +use re_entity_db::{external::re_query2::PromiseResult, EntityDb}; use re_log::ResultExt; use re_log_types::{DataRow, EntityPath, RowId}; use re_types::blueprint::components::Visible; diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index f0cb5f83d587..2a32a6799eba 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -7,7 +7,7 @@ use nohash_hasher::IntSet; use smallvec::SmallVec; use re_data_store::LatestAtQuery; -use re_entity_db::external::re_query_cache::PromiseResult; +use re_entity_db::external::re_query2::PromiseResult; use re_entity_db::EntityPath; use re_space_view::SpaceViewBlueprint; use re_types::blueprint::components::ViewerRecommendationHash; diff --git a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs index a90e12136fb1..25cd1ea0a939 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs @@ -1,7 +1,7 @@ use re_viewer::external::{ egui, re_log_types::EntityPath, - re_query_cache, re_renderer, + re_query2, re_renderer, re_types::{ self, components::{Color, InstanceKey}, @@ -38,7 +38,7 @@ impl re_types::Archetype for ColorArchetype { } } -impl re_query2::ToArchetype for re_query_cache::CachedLatestAtResults { +impl re_query2::ToArchetype for re_query2::CachedLatestAtResults { #[inline] fn to_archetype( &self, @@ -70,7 +70,7 @@ impl VisualizerSystem for InstanceColorSystem { for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { // …gather all colors and their instance ids. - let results = re_query2::latest_at( + let results = ctx.recording().query_caches().latest_at( ctx.recording_store(), &ctx.current_query(), &data_result.entity_path, From 3e8d7d45ee1d12122eb31a54c789acee63433413 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 24 Apr 2024 12:53:12 +0200 Subject: [PATCH 2/9] remove every last trace of re_query --- Cargo.lock | 32 - Cargo.toml | 1 - crates/re_entity_db/Cargo.toml | 3 +- crates/re_query/Cargo.toml | 65 -- crates/re_query/README.md | 10 - crates/re_query/benches/query_benchmark.rs | 313 -------- crates/re_query/src/archetype_view.rs | 669 ----------------- crates/re_query/src/lib.rs | 63 -- crates/re_query/src/query.rs | 269 ------- crates/re_query/src/range.rs | 170 ----- crates/re_query/src/util.rs | 143 ---- .../re_query/tests/archetype_query_tests.rs | 336 --------- .../re_query/tests/archetype_range_tests.rs | 675 ------------------ .../re_query/tests/archetype_visit_tests.rs | 392 ---------- crates/re_query/tests/store.rs | 73 -- crates/re_space_view/Cargo.toml | 1 - crates/re_space_view_dataframe/Cargo.toml | 1 - crates/re_space_view_spatial/Cargo.toml | 1 - crates/re_space_view_text_document/Cargo.toml | 1 - crates/re_space_view_time_series/Cargo.toml | 1 - crates/re_viewer_context/Cargo.toml | 1 - crates/re_viewer_context/src/lib.rs | 2 +- .../re_viewer_context/src/space_view/mod.rs | 5 +- 23 files changed, 3 insertions(+), 3224 deletions(-) delete mode 100644 crates/re_query/Cargo.toml delete mode 100644 crates/re_query/README.md delete mode 100644 crates/re_query/benches/query_benchmark.rs delete mode 100644 crates/re_query/src/archetype_view.rs delete mode 100644 crates/re_query/src/lib.rs delete mode 100644 crates/re_query/src/query.rs delete mode 100644 crates/re_query/src/range.rs delete mode 100644 crates/re_query/src/util.rs delete mode 100644 crates/re_query/tests/archetype_query_tests.rs delete mode 100644 crates/re_query/tests/archetype_range_tests.rs delete mode 100644 crates/re_query/tests/archetype_visit_tests.rs delete mode 100644 crates/re_query/tests/store.rs diff --git a/Cargo.lock b/Cargo.lock index f3a0b2e65728..5d6ea852edf8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4308,7 +4308,6 @@ dependencies = [ "re_log", "re_log_encoding", "re_log_types", - "re_query", "re_query2", "re_smart_channel", "re_tracing", @@ -4455,31 +4454,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "re_query" -version = "0.16.0-alpha.2" -dependencies = [ - "backtrace", - "criterion", - "document-features", - "itertools 0.12.0", - "mimalloc", - "rand", - "re_arrow2", - "re_data_store", - "re_format", - "re_format_arrow", - "re_log", - "re_log_types", - "re_tracing", - "re_types", - "re_types_core", - "serde", - "similar-asserts", - "smallvec", - "thiserror", -] - [[package]] name = "re_query2" version = "0.16.0-alpha.2" @@ -4655,7 +4629,6 @@ dependencies = [ "re_entity_db", "re_log", "re_log_types", - "re_query", "re_query2", "re_tracing", "re_types", @@ -4693,7 +4666,6 @@ dependencies = [ "re_data_ui", "re_entity_db", "re_log_types", - "re_query", "re_query2", "re_renderer", "re_tracing", @@ -4726,7 +4698,6 @@ dependencies = [ "re_format", "re_log", "re_log_types", - "re_query", "re_query2", "re_renderer", "re_space_view", @@ -4774,7 +4745,6 @@ dependencies = [ "itertools 0.12.0", "re_data_store", "re_log", - "re_query", "re_renderer", "re_space_view", "re_tracing", @@ -4815,7 +4785,6 @@ dependencies = [ "re_format", "re_log", "re_log_types", - "re_query", "re_query2", "re_renderer", "re_space_view", @@ -5091,7 +5060,6 @@ dependencies = [ "re_entity_db", "re_log", "re_log_types", - "re_query", "re_query2", "re_renderer", "re_smart_channel", diff --git a/Cargo.toml b/Cargo.toml index 47f2d1dff06e..e6c265343f8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,6 @@ re_log = { path = "crates/re_log", version = "=0.16.0-alpha.2", default-features re_log_encoding = { path = "crates/re_log_encoding", version = "=0.16.0-alpha.2", default-features = false } re_log_types = { path = "crates/re_log_types", version = "=0.16.0-alpha.2", default-features = false } re_memory = { path = "crates/re_memory", version = "=0.16.0-alpha.2", default-features = false } -re_query = { path = "crates/re_query", version = "=0.16.0-alpha.2", default-features = false } re_query2 = { path = "crates/re_query2", version = "=0.16.0-alpha.2", default-features = false } re_renderer = { path = "crates/re_renderer", version = "=0.16.0-alpha.2", default-features = false } re_sdk = { path = "crates/re_sdk", version = "=0.16.0-alpha.2", default-features = false } diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index 2bf8bed8d33e..202ad566d862 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -23,7 +23,7 @@ all-features = true default = [] ## Enable (de)serialization using serde. -serde = ["dep:serde", "dep:rmp-serde", "re_log_types/serde", "re_query/serde"] +serde = ["dep:serde", "dep:rmp-serde", "re_log_types/serde"] [dependencies] @@ -33,7 +33,6 @@ re_int_histogram.workspace = true re_log.workspace = true re_log_encoding = { workspace = true, features = ["decoder"] } re_log_types.workspace = true -re_query.workspace = true re_query2 = { workspace = true, features = ["to_archetype"] } re_smart_channel.workspace = true re_tracing.workspace = true diff --git a/crates/re_query/Cargo.toml b/crates/re_query/Cargo.toml deleted file mode 100644 index 66c9327a5b16..000000000000 --- a/crates/re_query/Cargo.toml +++ /dev/null @@ -1,65 +0,0 @@ -[package] -name = "re_query" -authors.workspace = true -description = "Querying data in the re_data_store" -edition.workspace = true -homepage.workspace = true -include.workspace = true -license.workspace = true -publish = true -readme = "README.md" -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[lints] -workspace = true - -[package.metadata.docs.rs] -all-features = true - - -[features] -default = [] - -## Enable (de)serialization using serde. -serde = ["dep:serde"] - - -[dependencies] -# Rerun dependencies: -re_data_store.workspace = true -re_format.workspace = true -re_format_arrow.workspace = true -re_log_types.workspace = true -re_types_core.workspace = true -re_log.workspace = true -re_tracing.workspace = true - -# External dependencies: -arrow2.workspace = true -backtrace.workspace = true -document-features.workspace = true -itertools = { workspace = true } -serde = { workspace = true, features = ["derive", "rc"], optional = true } -smallvec.workspace = true -thiserror.workspace = true - - -[dev-dependencies] -re_types = { workspace = true, features = ["datagen"] } - -criterion.workspace = true -itertools = { workspace = true } -mimalloc.workspace = true -rand = { workspace = true, features = ["std", "std_rng"] } -similar-asserts.workspace = true - - -[lib] -bench = false - - -[[bench]] -name = "query_benchmark" -harness = false diff --git a/crates/re_query/README.md b/crates/re_query/README.md deleted file mode 100644 index 79097b9e5cbe..000000000000 --- a/crates/re_query/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# re_query - -Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. - -[![Latest version](https://img.shields.io/crates/v/re_query.svg)](https://crates.io/crates/re_query) -[![Documentation](https://docs.rs/re_query/badge.svg)](https://docs.rs/re_query) -![MIT](https://img.shields.io/badge/license-MIT-blue.svg) -![Apache](https://img.shields.io/badge/license-Apache-blue.svg) - -Querying data in the `re_data_store`. diff --git a/crates/re_query/benches/query_benchmark.rs b/crates/re_query/benches/query_benchmark.rs deleted file mode 100644 index aa5af0efe07c..000000000000 --- a/crates/re_query/benches/query_benchmark.rs +++ /dev/null @@ -1,313 +0,0 @@ -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -use criterion::{criterion_group, criterion_main, Criterion}; - -use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query::query_archetype; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D, Text}, -}; -use re_types_core::Loggable as _; - -// --- - -#[cfg(not(debug_assertions))] -const NUM_FRAMES_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_FRAMES_STRINGS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_STRINGS: u32 = 1_000; - -// `cargo test` also runs the benchmark setup code, so make sure they run quickly: -#[cfg(debug_assertions)] -const NUM_FRAMES_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_FRAMES_STRINGS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_STRINGS: u32 = 1; - -criterion_group!( - benches, - mono_points, - mono_strings, - batch_points, - batch_strings -); -criterion_main!(benches); - -// --- Benchmarks --- - -pub fn build_some_point2d(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) - .collect() -} - -/// Create `len` dummy colors -pub fn build_some_colors(len: usize) -> Vec { - (0..len).map(|i| Color::from(i as u32)).collect() -} - -/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. -pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { - (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) -} - -pub fn build_some_strings(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| { - let ilen: usize = rng.gen_range(0..10000); - let s: String = rand::thread_rng() - .sample_iter(&rand::distributions::Alphanumeric) - .take(ilen) - .map(char::from) - .collect(); - Text::from(s) - }) - .collect() -} - -fn mono_points(c: &mut Criterion) { - // Each mono point gets logged at a different path - let paths = (0..NUM_POINTS) - .map(move |point_idx| entity_path!("points", point_idx.to_string())) - .collect_vec(); - let msgs = build_points_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - // Mono-insert is slow -- decrease the sample size - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); - }); - } -} - -fn mono_strings(c: &mut Criterion) { - // Each mono string gets logged at a different path - let paths = (0..NUM_STRINGS) - .map(move |string_idx| entity_path!("strings", string_idx.to_string())) - .collect_vec(); - let msgs = build_strings_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); - }); - } -} - -fn batch_points(c: &mut Criterion) { - // Batch points are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_points_rows(&paths, NUM_POINTS as _); - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); - }); - } -} - -fn batch_strings(c: &mut Criterion) { - // Batch strings are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_strings_rows(&paths, NUM_STRINGS as _); - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); - }); - } -} - -// --- Helpers --- - -fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { - (0..NUM_FRAMES_POINTS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_points as _, - ( - build_some_point2d(num_points), - build_some_colors(num_points), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec { - (0..NUM_FRAMES_STRINGS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_strings as _, - // We still need to create points because they are the primary for the - // archetype query we want to do. We won't actually deserialize the points - // during the query -- we just need it for the primary keys. - // TODO(jleibs): switch this to use `TextEntry` once the new type has - // landed. - ( - build_some_point2d(num_strings), - build_some_strings(num_strings), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn insert_rows<'a>(msgs: impl Iterator) -> DataStore { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - msgs.for_each(|row| { - store.insert_row(row).unwrap(); - }); - store -} - -struct SavePoint { - _pos: Position2D, - _color: Option, -} - -fn query_and_visit_points(store: &DataStore, paths: &[EntityPath]) -> Vec { - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_POINTS as i64 / 2); - - let mut points = Vec::with_capacity(NUM_POINTS as _); - - // TODO(jleibs): Add Radius once we have support for it in field_types - for path in paths { - let arch_view = query_archetype::(store, &query, path).unwrap(); - itertools::izip!( - arch_view.iter_required_component::().unwrap(), - arch_view.iter_optional_component::().unwrap() - ) - .for_each(|(pos, color)| { - points.push(SavePoint { - _pos: pos, - _color: color, - }); - }); - } - assert_eq!(NUM_POINTS as usize, points.len()); - points -} - -struct SaveString { - _label: Option, -} - -fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec { - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_STRINGS as i64 / 2); - - let mut strings = Vec::with_capacity(NUM_STRINGS as _); - - for path in paths { - let arch_view = query_archetype::(store, &query, path).unwrap(); - arch_view - .iter_optional_component::() - .unwrap() - .for_each(|label| { - strings.push(SaveString { _label: label }); - }); - } - assert_eq!(NUM_STRINGS as usize, strings.len()); - - criterion::black_box(strings) -} diff --git a/crates/re_query/src/archetype_view.rs b/crates/re_query/src/archetype_view.rs deleted file mode 100644 index 371bd66dc705..000000000000 --- a/crates/re_query/src/archetype_view.rs +++ /dev/null @@ -1,669 +0,0 @@ -use std::{collections::BTreeMap, marker::PhantomData}; - -use arrow2::array::{Array, PrimitiveArray}; - -use re_log_types::{DataCell, DataCellRow, RowId, TimeInt}; -use re_types_core::{ - components::InstanceKey, Archetype, Component, ComponentName, DeserializationError, - DeserializationResult, Loggable, SerializationResult, -}; - -use crate::QueryError; - -/// A type-erased array of [`Component`] values and the corresponding [`InstanceKey`] keys. -/// -/// See: [`crate::get_component_with_instances`] -#[derive(Clone, Debug)] -pub struct ComponentWithInstances { - pub(crate) instance_keys: DataCell, - pub(crate) values: DataCell, -} - -impl std::fmt::Display for ComponentWithInstances { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let table = re_format_arrow::format_table( - [ - self.instance_keys.as_arrow_ref(), - self.values.as_arrow_ref(), - ], - ["InstanceKey", self.values.component_name().as_ref()], - ); - - f.write_fmt(format_args!("ComponentWithInstances:\n{table}")) - } -} - -impl ComponentWithInstances { - /// Name of the [`Component`] - #[inline] - pub fn name(&self) -> ComponentName { - self.values.component_name() - } - - /// Number of values. 1 for splats. - #[inline] - pub fn len(&self) -> usize { - self.values.num_instances() as _ - } - - #[inline] - /// Whether this [`ComponentWithInstances`] contains any data - pub fn is_empty(&self) -> bool { - self.values.is_empty() - } - - /// Returns the array of [`InstanceKey`]s. - #[inline] - pub fn instance_keys(&self) -> Vec { - re_tracing::profile_function!(); - self.instance_keys.to_native::() - } - - /// Returns the array of values as native [`Component`]s. - #[inline] - pub fn values<'a, C: Component + 'a>(&'a self) -> crate::Result>> { - if C::name() != self.name() { - return Err(QueryError::TypeMismatch { - actual: self.name(), - requested: C::name(), - }); - } - - Ok(self.values.try_to_native_opt::<'a, C>()?) - } - - /// Look up the value that corresponds to a given [`InstanceKey`] and convert to [`Component`] - pub fn lookup(&self, instance_key: &InstanceKey) -> crate::Result { - if C::name() != self.name() { - return Err(QueryError::TypeMismatch { - actual: self.name(), - requested: C::name(), - }); - } - let arr = self - .lookup_arrow(instance_key) - .map_or_else(|| Err(crate::ComponentNotFoundError(C::name())), Ok)?; - - let mut iter = C::from_arrow(arr.as_ref())?.into_iter(); - - let val = iter - .next() - .map_or_else(|| Err(crate::ComponentNotFoundError(C::name())), Ok)?; - Ok(val) - } - - /// Look up the value that corresponds to a given [`InstanceKey`] and return as an arrow [`Array`] - pub fn lookup_arrow(&self, instance_key: &InstanceKey) -> Option> { - let keys = self - .instance_keys - .as_arrow_ref() - .as_any() - .downcast_ref::>()? - .values(); - - // If the value is splatted, return the offset of the splat - let offset = if keys.len() == 1 && keys[0] == InstanceKey::SPLAT.0 { - 0 - } else { - // Otherwise binary search to find the offset of the instance - keys.binary_search(&instance_key.0).ok()? - }; - - (self.len() > offset) - .then(|| self.values.as_arrow_ref().sliced(offset, 1)) - .or_else(|| { - re_log::error_once!("found corrupt cell -- mismatched number of instances"); - None - }) - } - - /// Produce a [`ComponentWithInstances`] from native [`Component`] types - pub fn from_native<'a, C: Component + Clone + 'a>( - instance_keys: impl IntoIterator>>, - values: impl IntoIterator>>, - ) -> SerializationResult { - // Unwrap: If the data is valid for the native types, it's valid in serialized form. - let instance_keys = InstanceKey::to_arrow(instance_keys)?; - let values = C::to_arrow(values)?; - Ok(ComponentWithInstances { - instance_keys: DataCell::from_arrow(InstanceKey::name(), instance_keys), - values: DataCell::from_arrow(C::name(), values), - }) - } - - #[inline] - pub fn into_data_cell_row(self) -> DataCellRow { - let Self { - instance_keys, - values, - } = self; - DataCellRow(smallvec::smallvec![instance_keys, values]) - } -} - -/// Iterator over a single [`Component`] joined onto a primary [`Component`] -/// -/// This is equivalent to a left join between one table made up of the -/// [`InstanceKey`]s from the primary component and another table with the -/// [`InstanceKey`]s and values of the iterated [`Component`]. -/// -/// Instances have a [`InstanceKey::SPLAT`] key that will cause the value to be -/// repeated for the entirety of the join. -/// -/// For example -/// ```text -/// primary -/// +----------+ -/// | instance | -/// +----------+ -/// | key0 | -/// | key1 | -/// | Key2 | -/// -/// component -/// +----------+-------+ -/// | instance | value | -/// +----------+-------+ -/// | key0 | val0 | -/// | Key2 | val2 | -/// -/// SELECT value FROM LEFT JOIN primary.instance = component.instance; -/// -/// output -/// +-------+ -/// | value | -/// +-------+ -/// | val0 | -/// | NULL | -/// | val2 | -/// -/// ``` -pub struct ComponentJoinedIterator { - pub primary_instance_key_iter: IIter1, - pub component_instance_key_iter: IIter2, - pub component_value_iter: VIter, - pub next_component_instance_key: Option, - pub splatted_component_value: Option, -} - -impl Iterator for ComponentJoinedIterator -where - IIter1: Iterator, - IIter2: Iterator, - VIter: Iterator>, - C: Clone, -{ - type Item = Option; - - fn next(&mut self) -> Option> { - // For each value of primary_instance_iter we must find a result - if let Some(primary_key) = self.primary_instance_key_iter.next() { - loop { - match &self.next_component_instance_key { - // If we have a next component key, we either… - Some(instance_key) => { - if instance_key.is_splat() { - if self.splatted_component_value.is_none() { - self.splatted_component_value = - self.component_value_iter.next().flatten(); - } - break Some(self.splatted_component_value.clone()); - } else { - match primary_key.0.cmp(&instance_key.0) { - // Return a None if the primary_key hasn't reached it yet - std::cmp::Ordering::Less => break Some(None), - // Return the value if the keys match - std::cmp::Ordering::Equal => { - self.next_component_instance_key = - self.component_instance_key_iter.next(); - break self.component_value_iter.next(); - } - // Skip this component if the key is behind the primary key - std::cmp::Ordering::Greater => { - _ = self.component_value_iter.next(); - self.next_component_instance_key = - self.component_instance_key_iter.next(); - } - } - } - } - // Otherwise, we ran out of component elements. Just return - // None until the primary iter ends. - None => break Some(None), - }; - } - } else { - None - } - } -} - -impl ExactSizeIterator - for ComponentJoinedIterator -where - IIter1: ExactSizeIterator, - IIter2: ExactSizeIterator, - VIter: ExactSizeIterator>, - C: Clone, -{ -} - -/// A view of an [`Archetype`] at a particular point in time returned by [`crate::get_component_with_instances`]. -/// -/// The required [`Component`]s of an [`ArchetypeView`] determines the length of an entity -/// batch. When iterating over individual components, they will be implicitly joined onto -/// the required [`Component`]s using [`InstanceKey`] values. -#[derive(Clone, Debug)] -pub struct ArchetypeView { - /// The _data_ time of the most recent component in the view (not necessarily the primary!). - pub(crate) data_time: TimeInt, - - /// The [`RowId`] of the primary component in the view. - pub(crate) primary_row_id: RowId, - - pub(crate) components: BTreeMap, - - pub(crate) phantom: PhantomData, -} - -impl std::fmt::Display for ArchetypeView { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let first_required = self.required_comp(); - - let primary_table = re_format_arrow::format_table( - [ - first_required.instance_keys.as_arrow_ref(), - first_required.values.as_arrow_ref(), - ], - ["InstanceId", first_required.name().as_ref()], - ); - - f.write_fmt(format_args!("ArchetypeView:\n{primary_table}")) - } -} - -impl ArchetypeView { - #[inline] - pub fn num_instances(&self) -> usize { - self.required_comp().len() - } - - /// The _data_ time of the most recent component in the view (not necessarily the primary!). - #[inline] - pub fn data_time(&self) -> TimeInt { - self.data_time - } - - /// Returns the [`RowId`] associated with the _primary_ component that was used to drive this - /// entire query. - /// - /// Beware: when using this [`RowId`] for caching/versioning purposes, make sure the component - /// you are about to cache is in fact the primary component of the query! - /// See also . - #[inline] - pub fn primary_row_id(&self) -> RowId { - self.primary_row_id - } -} - -impl ArchetypeView { - #[inline] - fn required_comp(&self) -> &ComponentWithInstances { - // TODO(jleibs): Do all archetypes always have at least 1 required components? - let first_required = A::required_components()[0]; - &self.components[&first_required] - } - - /// Returns an iterator over [`InstanceKey`]s. - #[inline] - pub fn iter_instance_keys(&self) -> impl ExactSizeIterator { - re_tracing::profile_function!(); - // TODO(#2750): Maybe make this an intersection instead - self.required_comp().instance_keys().into_iter() - } - - /// Check if the entity has a component and its not empty - #[inline] - pub fn has_component(&self) -> bool { - let name = C::name(); - self.components.get(&name).map_or(false, |c| !c.is_empty()) - } - - /// Iterate over the values of a required multi-component. - #[inline] - pub fn iter_required_component<'a, C: Component + 'a>( - &'a self, - ) -> DeserializationResult + '_> { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(); - - debug_assert!(A::required_components() - .iter() - .any(|c| c.as_ref() == C::name())); - let component = self.components.get(&C::name()); - - if let Some(component) = component { - let component_value_iter = component - .values - .try_to_native() - .map_err(|err| DeserializationError::DataCellError(err.to_string()))? - .into_iter(); - - Ok(component_value_iter) - } else { - Err(DeserializationError::MissingComponent { - component: C::name(), - backtrace: ::backtrace::Backtrace::new_unresolved(), - }) - } - } - - /// Get a single required mono-component. - #[inline] - pub fn required_mono_component(&self) -> DeserializationResult { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(); - - let mut iter = self.iter_required_component::()?; - let value = iter - .next() - .ok_or_else(|| DeserializationError::MissingComponent { - component: C::name(), - backtrace: re_types_core::_Backtrace::new_unresolved(), - })?; - let count = 1 + iter.count(); - if count != 1 { - re_log::warn_once!("Expected a single value of {} but found {count}", C::name()); - } - Ok(value) - } - - /// Iterate over optional values as native [`Component`]s. - /// - /// Always produces an iterator that matches the length of a primary - /// component by joining on the `InstanceKey` values. - #[inline] - pub fn iter_optional_component<'a, C: Component + Clone + 'a>( - &'a self, - ) -> DeserializationResult> + '_> { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(C::name()); - - let component = self.components.get(&C::name()); - - // If the component is found and not empty, run the joining iterator on it. - // Otherwise just output nulls of the length of the primary. - // Note that this guard is specifically a precondition of the inner optimization - // for matched instance keys which will debug_assert if a zero-length component is - // referenced there. - let is_empty = component.map_or(true, |c| c.is_empty()); - if let (Some(component), false) = (component, is_empty) { - // NOTE(1): Autogenerated instance keys are interned behind datacells. - // If two or more rows in the store share the same keys, then they will share - // also the same cells. - // Therefore we can compare those cells, and early out if they match. - // - // NOTE(2): Comparing cells that point to the same backing storage is a simple pointer - // comparison; no data comparison involved. - // If the cells are not interned, this will fall back to a more costly data comparison: - // - If the data is the same, the cost of the comparison will be won back by having a - // faster iterator. - // - If the data isn't the same, the cost of the comparison will be dwarfed by the cost - // of the join anyway. - - if self.required_comp().instance_keys == component.instance_keys { - // This fast iterator is assumed to match the length of the - // primary component We shouldn't hit this since the store - // should enforce matched lengths for non-empty components, and - // the outer if-guard should keep us from reaching this in the - // case of an empty component. - // TODO(#1893): This assert and the implementation both need to - // be addressed when we allow single rows containing splats. - debug_assert_eq!( - self.required_comp().instance_keys.num_instances(), - component.values.num_instances() - ); - - // NOTE: A component instance cannot be optional in itself, and if we're on this - // path then we know for a fact that both batches can be intersected 1-to-1. - // Therefore there cannot be any null values, therefore we can go through the fast - // deserialization path. - let component_value_iter = { - C::from_arrow(component.values.as_arrow_ref())? - .into_iter() - .map(Some) - }; - - return Ok(itertools::Either::Left(itertools::Either::Left( - component_value_iter, - ))); - } - - let component_value_iter = - { C::from_arrow_opt(component.values.as_arrow_ref())?.into_iter() }; - - let primary_instance_key_iter = self.iter_instance_keys(); - let mut component_instance_key_iter = component.instance_keys().into_iter(); - - let next_component_instance_key = component_instance_key_iter.next(); - - Ok(itertools::Either::Left(itertools::Either::Right( - ComponentJoinedIterator { - primary_instance_key_iter, - component_instance_key_iter, - component_value_iter, - next_component_instance_key, - splatted_component_value: None, - }, - ))) - } else { - let primary = self.required_comp(); - let nulls = (0..primary.len()).map(|_| None); - Ok(itertools::Either::Right(nulls)) - } - } - - /// Get a single optional mono-component. - #[inline] - pub fn optional_mono_component(&self) -> DeserializationResult> { - let mut iter = self.iter_optional_component::()?; - if let Some(first_value) = iter.next() { - let count = 1 + iter.count(); - if count != 1 { - re_log::warn_once!("Expected a single value of {} but found {count}", C::name()); - } - Ok(first_value) - } else { - Ok(None) - } - } - - /// Iterate over optional values as native [`Component`]s. - /// - /// The contents of the cell are returned as-is, without joining with any other component. - #[inline] - pub fn iter_raw_optional_component<'a, C: Component + Clone + 'a>( - &'a self, - ) -> DeserializationResult + '_>> { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(C::name()); - - let component = self.components.get(&C::name()); - - if let Some(component) = component { - return Ok(Some( - C::from_arrow(component.values.as_arrow_ref())?.into_iter(), - )); - } - - Ok(None) - } - - /// Get a single optional mono-component. - #[inline] - pub fn raw_optional_mono_component(&self) -> DeserializationResult> { - if let Some(mut iter) = self.iter_raw_optional_component::()? { - if let Some(value) = iter.next() { - let count = 1 + iter.count(); - if count != 1 { - re_log::warn_once!( - "Expected a single value of {} but found {count}", - C::name() - ); - } - Ok(Some(value)) - } else { - Ok(None) - } - } else { - Ok(None) - } - } - - /// Helper function to produce an [`ArchetypeView`] from a collection of [`ComponentWithInstances`]. - #[inline] - pub fn from_components( - data_time: TimeInt, - primary_row_id: RowId, - components: impl IntoIterator, - ) -> Self { - Self { - data_time, - primary_row_id, - components: components - .into_iter() - .map(|comp| (comp.name(), comp)) - .collect(), - phantom: PhantomData, - } - } - - /// Convert an `ArchetypeView` back into a native Archetype instance - pub fn to_archetype(&self) -> crate::Result { - for component in A::required_components().iter() { - if self - .components - .get(component) - .map_or(true, |cwi| cwi.is_empty()) - { - return Err(QueryError::PrimaryNotFound(*component)); - } - } - - Ok(A::from_arrow_components( - self.components - .values() - .map(|comp| (comp.name(), comp.values.to_arrow())), - )?) - } - - /// Useful for tests. - pub fn to_data_cell_row_1< - 'a, - C1: re_types_core::Component + Clone + Into<::std::borrow::Cow<'a, C1>> + 'a, - >( - &self, - ) -> crate::Result { - let cell0 = DataCell::from_native(self.iter_instance_keys()); - let cell1 = DataCell::from_native_sparse(self.iter_optional_component::()?); - Ok(DataCellRow(smallvec::smallvec![cell0, cell1])) - } - - /// Useful for tests. - pub fn to_data_cell_row_2< - 'a, - C1: re_types_core::Component + Clone + Into<::std::borrow::Cow<'a, C1>> + 'a, - C2: re_types_core::Component + Clone + Into<::std::borrow::Cow<'a, C2>> + 'a, - >( - &self, - ) -> crate::Result { - let cell0 = DataCell::from_native(self.iter_instance_keys()); - let cell1 = DataCell::from_native_sparse(self.iter_optional_component::()?); - let cell2 = DataCell::from_native_sparse(self.iter_optional_component::()?); - Ok(DataCellRow(smallvec::smallvec![cell0, cell1, cell2])) - } -} - -#[test] -fn lookup_value() { - use re_types::components::{Color, InstanceKey, Position2D}; - - let instance_keys = InstanceKey::from_iter(0..5); - - let points = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let component = ComponentWithInstances::from_native(instance_keys, points).unwrap(); - - let missing_value = component.lookup_arrow(&InstanceKey(5)); - assert_eq!(missing_value, None); - - let value = component.lookup_arrow(&InstanceKey(2)).unwrap(); - - let expected_point = [points[2]]; - let expected_arrow = Position2D::to_arrow(expected_point).unwrap(); - - assert_eq!(expected_arrow, value); - - let instance_keys = [ - InstanceKey(17), - InstanceKey(47), - InstanceKey(48), - InstanceKey(99), - InstanceKey(472), - ]; - - let component = ComponentWithInstances::from_native(instance_keys, points).unwrap(); - - let missing_value = component.lookup_arrow(&InstanceKey(46)); - assert_eq!(missing_value, None); - - let value = component.lookup_arrow(&InstanceKey(99)).unwrap(); - - let expected_point = [points[3]]; - let expected_arrow = Position2D::to_arrow(expected_point).unwrap(); - - assert_eq!(expected_arrow, value); - - // Lookups with serialization - - let value = component.lookup::(&InstanceKey(99)).unwrap(); - assert_eq!(expected_point[0], value); - - let missing_value = component.lookup::(&InstanceKey(46)); - assert!(matches!( - missing_value.err().unwrap(), - QueryError::ComponentNotFound(_) - )); - - let missing_value = component.lookup::(&InstanceKey(99)); - assert!(matches!( - missing_value.err().unwrap(), - QueryError::TypeMismatch { .. } - )); -} - -#[test] -fn lookup_splat() { - use re_types::components::{InstanceKey, Position2D}; - let instances = [ - InstanceKey::SPLAT, // - ]; - let points = [ - Position2D::new(1.0, 2.0), // - ]; - - let component = ComponentWithInstances::from_native(instances, points).unwrap(); - - // Any instance we look up will return the slatted value - let value = component.lookup::(&InstanceKey(1)).unwrap(); - assert_eq!(points[0], value); - - let value = component.lookup::(&InstanceKey(99)).unwrap(); - assert_eq!(points[0], value); -} diff --git a/crates/re_query/src/lib.rs b/crates/re_query/src/lib.rs deleted file mode 100644 index b888c376abec..000000000000 --- a/crates/re_query/src/lib.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! Provide query-centric access to the [`re_data_store`]. - -mod archetype_view; -mod query; -mod range; -mod util; - -pub use self::archetype_view::{ArchetypeView, ComponentWithInstances}; -pub use self::query::{get_component_with_instances, query_archetype}; -pub use self::range::{range_archetype, range_component_set}; -pub use self::util::{ - query_archetype_with_history, ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary, -}; - -// Used for doc-tests -#[doc(hidden)] -pub use self::query::__populate_example_store; - -#[derive(Debug, Clone, Copy)] -pub struct ComponentNotFoundError(pub re_types_core::ComponentName); - -impl std::fmt::Display for ComponentNotFoundError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("Could not find component: {}", self.0)) - } -} - -impl std::error::Error for ComponentNotFoundError {} - -#[derive(thiserror::Error, Debug)] -pub enum QueryError { - #[error("Tried to access a column that doesn't exist")] - BadAccess, - - #[error("Could not find primary component: {0}")] - PrimaryNotFound(re_types_core::ComponentName), - - #[error(transparent)] - ComponentNotFound(#[from] ComponentNotFoundError), - - #[error("Tried to access component of type '{actual:?}' using component '{requested:?}'")] - TypeMismatch { - actual: re_types_core::ComponentName, - requested: re_types_core::ComponentName, - }, - - #[error("Error with one or more the underlying data cells: {0}")] - DataCell(#[from] re_log_types::DataCellError), - - #[error("Error deserializing: {0}")] - DeserializationError(#[from] re_types_core::DeserializationError), - - #[error("Error serializing: {0}")] - SerializationError(#[from] re_types_core::SerializationError), - - #[error("Error converting arrow data: {0}")] - ArrowError(#[from] arrow2::error::Error), - - #[error("Not implemented")] - NotImplemented, -} - -pub type Result = std::result::Result; diff --git a/crates/re_query/src/query.rs b/crates/re_query/src/query.rs deleted file mode 100644 index 2580ff33c31f..000000000000 --- a/crates/re_query/src/query.rs +++ /dev/null @@ -1,269 +0,0 @@ -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::{EntityPath, RowId, TimeInt}; -use re_types_core::{components::InstanceKey, Archetype, ComponentName, Loggable}; - -use crate::{ArchetypeView, ComponentWithInstances, QueryError}; - -/// Retrieves a [`ComponentWithInstances`] from the [`DataStore`]. -/// -/// Returns `None` if the component is not found. -/// -/// ``` -/// # use re_data_store::LatestAtQuery; -/// # use re_log_types::{Timeline, TimeInt, example_components::{MyColor, MyPoint}}; -/// # use re_types_core::Loggable as _; -/// # let store = re_query::__populate_example_store(); -/// -/// let ent_path = "point"; -/// let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), TimeInt::new_temporal(123)); -/// -/// let (_, _, component) = re_query::get_component_with_instances( -/// &store, -/// &query, -/// &ent_path.into(), -/// MyPoint::name(), -/// ) -/// .unwrap(); -/// -/// //println!("{component}"); -/// ``` -/// -/// Outputs: -/// ```text -/// ┌─────────────┬───────────┐ -/// │ InstanceKey ┆ MyPoint │ -/// │ --- ┆ --- │ -/// │ u64 ┆ struct[2] │ -/// ╞═════════════╪═══════════╡ -/// │ 42 ┆ {1.0,2.0} │ -/// ├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ -/// │ 96 ┆ {3.0,4.0} │ -/// └─────────────┴───────────┘ -/// ``` -pub fn get_component_with_instances( - store: &DataStore, - query: &LatestAtQuery, - ent_path: &EntityPath, - component: ComponentName, -) -> Option<(TimeInt, RowId, ComponentWithInstances)> { - debug_assert_eq!(store.cluster_key(), InstanceKey::name()); - - let components = [InstanceKey::name(), component]; - - let (data_time, row_id, mut cells) = - store.latest_at(query, ent_path, component, &components)?; - - Some(( - data_time, - row_id, - ComponentWithInstances { - // NOTE: The unwrap cannot fail, the cluster key's presence is guaranteed - // by the store. - instance_keys: cells[0].take().unwrap(), - values: cells[1].take()?, - }, - )) -} - -/// Retrieve an [`ArchetypeView`] from the `DataStore`, as well as the associated _data_ time of -/// its _most recent component_. -/// -/// If you expect only one instance (e.g. for mono-components like `Transform` `Tensor`] -/// and have no additional components you can use `Caches::latest_at_component` instead. -/// -/// ``` -/// # use re_data_store::LatestAtQuery; -/// # use re_log_types::{Timeline, TimeInt, example_components::{MyColor, MyPoint, MyPoints}}; -/// # use re_types_core::Component; -/// # let store = re_query::__populate_example_store(); -/// -/// let ent_path = "point"; -/// let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), TimeInt::new_temporal(123)); -/// -/// let arch_view = re_query::query_archetype::( -/// &store, -/// &query, -/// &ent_path.into(), -/// ) -/// .unwrap(); -/// -/// //println!("{arch_view:?}"); -/// ``` -/// -/// Outputs: -/// ```text -/// ┌────────────────────┬───────────────┬─────────────────┐ -/// │ InstanceKey ┆ MyPoint ┆ MyColor │ -/// │ --- ┆ --- ┆ --- │ -/// │ u64 ┆ struct[2] ┆ u32 │ -/// ╞════════════════════╪═══════════════╪═════════════════╡ -/// │ 42 ┆ {1.0,2.0} ┆ null │ -/// │ 96 ┆ {3.0,4.0} ┆ 4278190080 │ -/// └────────────────────┴───────────────┴─────────────────┘ -/// ``` -pub fn query_archetype( - store: &DataStore, - query: &LatestAtQuery, - ent_path: &EntityPath, -) -> crate::Result> { - // Profiling this can be useful, but we have many queries of very small archetypes, adding a lot of profiling overhead. - //re_tracing::profile_function!(); - - let required_components: Vec<_> = A::required_components() - .iter() - .map(|component| get_component_with_instances(store, query, ent_path, *component)) - .collect(); - - // NOTE: It's important to use `PrimaryNotFound` here. Any other error will be - // reported to the user. - // - // `query_archetype` is currently run for every archetype on every path in the view - // each path that's missing the primary is then ignored rather than being visited. - for (name, c) in itertools::izip!(A::required_components().iter(), &required_components) { - if c.is_none() { - return crate::Result::Err(QueryError::PrimaryNotFound(*name)); - } - } - - use itertools::Itertools as _; - let (data_times, row_ids, required_components): (Vec<_>, Vec<_>, Vec<_>) = - required_components.into_iter().flatten().multiunzip(); - - // NOTE: Since this is a compound API that actually emits multiple queries, the data time of the - // final result is the most recent data time among all of its components. - let mut max_data_time = data_times.iter().max().copied().unwrap_or(TimeInt::STATIC); - let row_id = row_ids.first().unwrap_or(&RowId::ZERO); - - let recommended_components = A::recommended_components(); - let optional_components = A::optional_components(); - - let other_components = recommended_components - .iter() - .chain(optional_components.iter()) - .filter_map(|component| { - get_component_with_instances(store, query, ent_path, *component).map( - |(data_time, _, component_result)| { - max_data_time = TimeInt::max(max_data_time, data_time); - component_result - }, - ) - }); - - // NOTE: Need to collect so we can compute `max_data_time`. - let cwis: Vec<_> = required_components - .into_iter() - .chain(other_components) - .collect(); - let arch_view = ArchetypeView::from_components(max_data_time, *row_id, cwis); - - Ok(arch_view) -} - -/// Helper used to create an example store we can use for querying in doctests -pub fn __populate_example_store() -> DataStore { - use re_log_types::example_components::{MyColor, MyPoint}; - use re_log_types::{build_frame_nr, DataRow}; - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let instances = vec![InstanceKey(42), InstanceKey(96)]; - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - instances.len() as _, - (&instances, &positions), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - let instances = vec![InstanceKey(96)]; - let colors = vec![MyColor::from(0xff000000)]; - - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - instances.len() as _, - (instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - store -} - -// Minimal test matching the doctest for `get_component_with_instances` -#[test] -fn simple_get_component() { - use smallvec::smallvec; - - use re_data_store::LatestAtQuery; - use re_log_types::{example_components::MyPoint, DataCellRow}; - use re_log_types::{DataCell, Timeline}; - - let store = __populate_example_store(); - - let ent_path = "point"; - let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), 123); - - let (_, _, component) = - get_component_with_instances(&store, &query, &ent_path.into(), MyPoint::name()).unwrap(); - - { - let row = component.into_data_cell_row(); - eprintln!("{row:?}"); - - let instances = vec![Some(InstanceKey(42)), Some(InstanceKey(96))]; - let positions = vec![Some(MyPoint::new(1.0, 2.0)), Some(MyPoint::new(3.0, 4.0))]; - - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - ]); - - assert_eq!(row, expected); - } -} - -// Minimal test matching the doctest for `query_entity_with_primary` -#[test] -fn simple_query_archetype() { - use re_data_store::LatestAtQuery; - use re_log_types::example_components::{MyColor, MyPoint, MyPoints}; - use re_log_types::Timeline; - - let store = __populate_example_store(); - - let ent_path = "point"; - let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), 123); - - let arch_view = query_archetype::(&store, &query, &ent_path.into()).unwrap(); - - let expected_positions = [MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = [None, Some(MyColor::from(0xff000000))]; - - let view_positions: Vec<_> = arch_view - .iter_required_component::() - .unwrap() - .collect(); - - let view_colors: Vec<_> = arch_view - .iter_optional_component::() - .unwrap() - .collect(); - - assert_eq!(expected_positions, view_positions.as_slice()); - assert_eq!(expected_colors, view_colors.as_slice()); - - eprintln!("{arch_view:?}"); -} diff --git a/crates/re_query/src/range.rs b/crates/re_query/src/range.rs deleted file mode 100644 index 2e55fca35571..000000000000 --- a/crates/re_query/src/range.rs +++ /dev/null @@ -1,170 +0,0 @@ -use itertools::Itertools as _; -use re_data_store::{DataStore, LatestAtQuery, RangeQuery}; -use re_log_types::{EntityPath, TimeInt}; -use re_types_core::{Archetype, ComponentName}; - -use crate::{get_component_with_instances, ArchetypeView, ComponentWithInstances}; - -// --- - -/// Iterates over the rows of any number of components and their respective cluster keys, all from -/// the point-of-view of the required components, returning an iterator of [`ArchetypeView`]s. -/// -/// The iterator only ever yields entity-views iff a required component has changed: a change -/// affecting only optional components will not yield an entity-view. -/// However, the changes in those secondary components will be accumulated into the next yielded -/// entity-view. -/// -/// This is a streaming-join: every yielded [`ArchetypeView`] will be the result of joining the latest -/// known state of all components, from their respective point-of-views. -/// -/// ⚠ The semantics are subtle! See `examples/range.rs` for an example of use. -pub fn range_archetype<'a, A: Archetype + 'a, const N: usize>( - store: &'a DataStore, - query: &RangeQuery, - ent_path: &'a EntityPath, -) -> impl Iterator> + 'a { - re_tracing::profile_function!(); - - // TODO(jleibs) this shim is super gross - let povs: [ComponentName; 1] = A::required_components().into_owned().try_into().unwrap(); - let components: [ComponentName; N] = A::all_components().into_owned().try_into().unwrap(); - - range_component_set::(store, query, ent_path, &povs, components) -} - -/// Iterates over the rows of any number of components and their respective cluster keys, all from -/// the point-of-view of the `povs` components, returning an iterator of [`ArchetypeView`]s. -/// -/// The iterator only ever yields entity-views iff a point-of-view component has changed: a change -/// affecting only optional components will not yield an entity-view. -/// However, the changes in those secondary components will be accumulated into the next yielded -/// entity-view. -/// -/// This is a streaming-join: every yielded [`ArchetypeView`] will be the result of joining the latest -/// known state of all components, from their respective point-of-views. -/// -/// ⚠ The semantics are subtle! See `examples/range.rs` for an example of use. -pub fn range_component_set<'a, A: Archetype + 'a, const N: usize>( - store: &'a DataStore, - query: &RangeQuery, - ent_path: &'a EntityPath, - povs: &[ComponentName], - components: [ComponentName; N], -) -> impl Iterator> + 'a { - re_tracing::profile_function!(); - - let primary: ComponentName = povs[0]; - let cluster_key = store.cluster_key(); - - // TODO(cmc): Ideally, we'd want to simply add the cluster and primary key to the `components` - // array if they are missing, yielding either `[ComponentName; N+1]` or `[ComponentName; N+2]`. - // Unfortunately this is not supported on stable at the moment, and requires - // feature(generic_const_exprs) on nightly. - // - // The alternative to these assertions (and thus putting the burden on the caller), for now, - // would be to drop the constant sizes all the way down, which would be way more painful to - // deal with. - assert!(components.contains(&cluster_key), "{components:?}"); - assert!(components.contains(&primary), "{components:?}"); - - let cluster_col = components - .iter() - .find_position(|component| **component == cluster_key) - .map(|(col, _)| col) - .unwrap(); // asserted on entry - let primary_col = components - .iter() - .find_position(|component| **component == primary) - .map(|(col, _)| col) - .unwrap(); // asserted on entry - - let mut state: Vec<_> = std::iter::repeat_with(|| None) - .take(components.len()) - .collect(); - - // NOTE: This will return none for `TimeInt::Min`, i.e. range queries that start infinitely far - // into the past don't have a latest-at state! - let query_time = TimeInt::try_from(query.range.min().as_i64().saturating_sub(1)).ok(); - - let mut cwis_latest = None; - if let Some(query_time) = query_time { - let mut cwis_latest_raw: Vec<_> = std::iter::repeat_with(|| None) - .take(components.len()) - .collect(); - - // Fetch the latest data for every single component from their respective point-of-views, - // this will allow us to build up the initial state and send an initial latest-at - // entity-view if needed. - for (i, primary) in components.iter().enumerate() { - cwis_latest_raw[i] = get_component_with_instances( - store, - &LatestAtQuery::new(query.timeline, query_time), - ent_path, - *primary, - ) - .map(|(_, row_id, cwi)| (row_id, cwi)); - } - - cwis_latest = Some(cwis_latest_raw); - } - - // send the latest-at state before anything else - cwis_latest - .into_iter() - // NOTE: `false` here means we will _not_ yield the latest-at state as an actual - // ArchetypeView! - // That is a very important detail: for overlapping range queries to be correct in a - // multi-tenant cache context, we need to make sure to inherit the latest-at state - // from T-1, while also making sure to _not_ yield the view that comes with that state. - // - // Consider e.g. what happens when one system queries for `range(10, 20)` while another - // queries for `range(9, 20)`: the data at timestamp `10` would differ because of the - // statefulness of range queries! - .map(move |cwis| (query_time.unwrap_or(TimeInt::STATIC), false, cwis)) - .chain(store.range(query, ent_path, components).map( - move |(data_time, row_id, mut cells)| { - // NOTE: The unwrap cannot fail, the cluster key's presence is guaranteed - // by the store. - let instance_keys = cells[cluster_col].take().unwrap(); - let is_primary = cells[primary_col].is_some(); - let cwis = cells - .into_iter() - .map(|cell| { - cell.map(|cell| { - ( - row_id, - ComponentWithInstances { - instance_keys: instance_keys.clone(), /* shallow */ - values: cell, - }, - ) - }) - }) - .collect::>(); - (data_time, is_primary, cwis) - }, - )) - .filter_map(move |(data_time, is_primary, cwis)| { - for (i, cwi) in cwis - .into_iter() - .enumerate() - .filter(|(_, cwi)| cwi.is_some()) - { - state[i] = cwi; - } - - // We only yield if the primary component has been updated! - is_primary.then(|| { - let (row_id, _) = state[primary_col].clone().unwrap(); // shallow - - let components: Vec<_> = state - .clone() - .into_iter() - .filter_map(|cwi| cwi.map(|(_, cwi)| cwi)) - .collect(); - - ArchetypeView::from_components(data_time, row_id, components) - }) - }) -} diff --git a/crates/re_query/src/util.rs b/crates/re_query/src/util.rs deleted file mode 100644 index 42831caa9bb5..000000000000 --- a/crates/re_query/src/util.rs +++ /dev/null @@ -1,143 +0,0 @@ -use re_data_store::{DataStore, LatestAtQuery, RangeQuery, TimeInt, TimeRange, Timeline}; -use re_log_types::EntityPath; -use re_types_core::Archetype; - -use crate::{query_archetype, range::range_archetype, ArchetypeView}; - -// --- - -/// One of the boundaries of the visible history. -/// -/// For [`VisibleHistoryBoundary::RelativeToTimeCursor`] and [`VisibleHistoryBoundary::Absolute`], -/// the value are either nanos or frames, depending on the type of timeline. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum VisibleHistoryBoundary { - /// Boundary is a value relative to the time cursor - RelativeToTimeCursor(i64), - - /// Boundary is an absolute value - Absolute(i64), - - /// The boundary extends to infinity. - Infinite, -} - -impl VisibleHistoryBoundary { - /// Value when the boundary is set to the current time cursor. - pub const AT_CURSOR: Self = Self::RelativeToTimeCursor(0); -} - -impl Default for VisibleHistoryBoundary { - fn default() -> Self { - Self::AT_CURSOR - } -} - -/// Visible history bounds. -#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -pub struct VisibleHistory { - /// Low time boundary. - pub from: VisibleHistoryBoundary, - - /// High time boundary. - pub to: VisibleHistoryBoundary, -} - -impl VisibleHistory { - /// Value with the visible history feature is disabled. - pub const OFF: Self = Self { - from: VisibleHistoryBoundary::AT_CURSOR, - to: VisibleHistoryBoundary::AT_CURSOR, - }; - - pub const ALL: Self = Self { - from: VisibleHistoryBoundary::Infinite, - to: VisibleHistoryBoundary::Infinite, - }; - - /// Returns the start boundary of the time range given an input cursor position. - /// - /// This is not guaranteed to be lesser than or equal to [`Self::to`]. - /// Do not use this to build a [`TimeRange`], use [`Self::time_range`]. - #[doc(hidden)] - pub fn range_start_from_cursor(&self, cursor: TimeInt) -> TimeInt { - match self.from { - VisibleHistoryBoundary::Absolute(value) => TimeInt::new_temporal(value), - VisibleHistoryBoundary::RelativeToTimeCursor(value) => { - cursor + TimeInt::new_temporal(value) - } - VisibleHistoryBoundary::Infinite => TimeInt::MIN, - } - } - - /// Returns the end boundary of the time range given an input cursor position. - /// - /// This is not guaranteed to be greater than [`Self::from`]. - /// Do not use this to build a [`TimeRange`], use [`Self::time_range`]. - #[doc(hidden)] - pub fn range_end_from_cursor(&self, cursor: TimeInt) -> TimeInt { - match self.to { - VisibleHistoryBoundary::Absolute(value) => TimeInt::new_temporal(value), - VisibleHistoryBoundary::RelativeToTimeCursor(value) => { - cursor + TimeInt::new_temporal(value) - } - VisibleHistoryBoundary::Infinite => TimeInt::MAX, - } - } - - /// Returns a _sanitized_ [`TimeRange`], i.e. guaranteed to be monotonically increasing. - pub fn time_range(&self, cursor: TimeInt) -> TimeRange { - let mut from = self.range_start_from_cursor(cursor); - let mut to = self.range_end_from_cursor(cursor); - - // TODO(#4993): visible time range UI can yield inverted ranges - if from > to { - std::mem::swap(&mut from, &mut to); - } - - TimeRange::new(from, to) - } -} - -/// When showing an entity in the history view, add this much history to it. -#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -pub struct ExtraQueryHistory { - /// Is the feature enabled? - pub enabled: bool, - - /// Visible history settings for time timelines - pub nanos: VisibleHistory, - - /// Visible history settings for frame timelines - pub sequences: VisibleHistory, -} - -// --- - -pub fn query_archetype_with_history<'a, A: Archetype + 'a, const N: usize>( - store: &'a DataStore, - timeline: &'a Timeline, - time: &'a TimeInt, - history: &ExtraQueryHistory, - ent_path: &'a EntityPath, -) -> crate::Result> + 'a> { - let visible_history = match timeline.typ() { - re_log_types::TimeType::Time => history.nanos, - re_log_types::TimeType::Sequence => history.sequences, - }; - - let time_range = visible_history.time_range(*time); - - if !history.enabled || time_range.min() == time_range.max() { - let latest_query = LatestAtQuery::new(*timeline, time_range.min()); - let latest = query_archetype::(store, &latest_query, ent_path)?; - - Ok(itertools::Either::Left(std::iter::once(latest))) - } else { - let range_query = RangeQuery::new(*timeline, time_range); - - let range = range_archetype::(store, &range_query, ent_path); - - Ok(itertools::Either::Right(range)) - } -} diff --git a/crates/re_query/tests/archetype_query_tests.rs b/crates/re_query/tests/archetype_query_tests.rs deleted file mode 100644 index 6160aa593a40..000000000000 --- a/crates/re_query/tests/archetype_query_tests.rs +++ /dev/null @@ -1,336 +0,0 @@ -use smallvec::smallvec; - -use re_data_store::DataStore; -use re_log_types::{build_frame_nr, DataCell, DataCellRow, DataRow, RowId, TimePoint}; -use re_query::query_archetype; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D}, -}; -use re_types_core::Loggable as _; - -#[test] -fn simple_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬─────────────┬────────────┐ - // │ instance ┆ positions2D ┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═════════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 4278190080 │ - // └──────────┴─────────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![None, Some(Color::from_rgb(255, 0, 0))]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} - -#[test] -fn static_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance.. statically! - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - TimePoint::default(), - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬───────────┬────────────┐ - // │ instance ┆ Position2D┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═══════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 4278190080 │ - // └──────────┴───────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![None, Some(Color::from_rgb(255, 0, 0))]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - // eprintln!("{arch_view:#?}"); - // eprintln!("{expected:#?}"); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} - -#[test] -fn no_instance_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign them colors with explicit instances - let colors = vec![Color::from_rgb(255, 0, 0), Color::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, colors).unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬───────────┬────────────┐ - // │ instance ┆ Position2D┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═══════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 16711680 │ - // └──────────┴───────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(255, 0, 0)), - Some(Color::from_rgb(0, 255, 0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{df:?}"); - //eprintln!("{expected:?}"); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} - -#[test] -fn missing_column_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // - // ┌──────────┬───────────┐ - // │ instance ┆ Position2D │ - // │ --- ┆ --- │ - // │ u64 ┆ struct[2] │ - // ╞══════════╪═══════════╡ - // │ 0 ┆ {1.0,2.0} │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} │ - // └──────────┴───────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - ]); - - //eprintln!("{df:?}"); - //eprintln!("{expected:?}"); - - assert_eq!( - &arch_view.to_data_cell_row_1::().unwrap(), - &expected - ); - } -} - -#[test] -fn splatted_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign all of them a color via splat - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬───────────┬────────────┐ - // │ instance ┆ Position2D┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═══════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 4278190080 │ - // └──────────┴───────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(255, 0, 0)), - Some(Color::from_rgb(255, 0, 0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{df:?}"); - //eprintln!("{expected:?}"); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} diff --git a/crates/re_query/tests/archetype_range_tests.rs b/crates/re_query/tests/archetype_range_tests.rs deleted file mode 100644 index 29c0f56b4754..000000000000 --- a/crates/re_query/tests/archetype_range_tests.rs +++ /dev/null @@ -1,675 +0,0 @@ -use smallvec::smallvec; - -use re_data_store::{DataStore, TimeInt, TimeRange}; -use re_log_types::{build_frame_nr, DataCell, DataCellRow, DataRow, EntityPath, RowId, TimePoint}; -use re_query::range_archetype; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D}, -}; -use re_types_core::Loggable as _; - -#[test] -fn simple_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(10.0, 20.0), Position2D::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #323: - // ┌─────────────┬──────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞═════════════╪══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ null │ - // └─────────────┴──────────────┴─────────────────┘ - - { - // Frame #323 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #123: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ null │ - // └────────────────────┴───────────────┴─────────────────┘ - // - // Frame #323: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ null │ - // └────────────────────┴───────────────┴─────────────────┘ - - { - // Frame #123 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors: Vec> = vec![None, None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } -} - -#[test] -fn static_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let mut row = - DataRow::from_cells1(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - row.compute_all_size_bytes(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances.clone(), colors.clone()), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances.clone(), colors.clone()), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Insert statically too! - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(10.0, 20.0), Position2D::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - // ┌───────────┬──────────┬────────┬─────────────────┬────────────────────┬────────────────────┬────────────────────────────┐ - // │ insert_id ┆ frame_nr ┆ entity ┆ Color ┆ InstanceKey ┆ rerun.row_id ┆ Point2D │ - // ╞═══════════╪══════════╪════════╪═════════════════╪════════════════════╪════════════════════╪════════════════════════════╡ - // │ 4 ┆ null ┆ point ┆ [4278190080] ┆ [1] ┆ [{167328063302246… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ 123 ┆ point ┆ null ┆ [0, 1] ┆ [{167328063302236… ┆ [{1.0,2.0}, {3.0,4.0}] │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 3 ┆ 123 ┆ point ┆ [4278190080] ┆ [1] ┆ [{167328063302245… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 5 ┆ 223 ┆ point ┆ [4278190080] ┆ [0] ┆ [{167328063302247… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 6 ┆ 223 ┆ point ┆ [4278190080] ┆ [0] ┆ [{167328063302248… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 7 ┆ 323 ┆ point ┆ null ┆ [0, 1] ┆ [{167328063302248… ┆ [{10.0,20.0}, {30.0,40.0}] │ - // └───────────┴──────────┴────────┴─────────────────┴────────────────────┴────────────────────┴────────────────────────────┘ - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - { - // Frame #323 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - { - // Frame #123 (partially static) - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - // eprintln!("{arch_view:#?}"); - // eprintln!("{expected:#?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - - // --- Third test: `[-inf, +inf]` --- - - let query = - re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - { - // Frame #123 (partially static) - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - // eprintln!("{arch_view:#?}"); - // eprintln!("{expected:#?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } -} - -#[test] -fn simple_splatted_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with a splatted instance - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![Color::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(10.0, 20.0), Position2D::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #323: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 16711680 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ 16711680 │ - // └────────────────────┴───────────────┴─────────────────┘ - - assert_eq!(results.len(), 1); - - { - // Frame #323 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(0, 255, 0)), - Some(Color::from_rgb(0, 255, 0)), - ]; - - let df = arch_view.to_data_cell_row_2::().unwrap(); - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!(&expected, &df); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #123: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ null │ - // └────────────────────┴───────────────┴─────────────────┘ - // - // Frame #323: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 16711680 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ 16711680 │ - // └────────────────────┴───────────────┴─────────────────┘ - - { - // Frame #123 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors: Vec> = vec![None, None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(0, 255, 0)), - Some(Color::from_rgb(0, 255, 0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } -} diff --git a/crates/re_query/tests/archetype_visit_tests.rs b/crates/re_query/tests/archetype_visit_tests.rs deleted file mode 100644 index b2cb5660f992..000000000000 --- a/crates/re_query/tests/archetype_visit_tests.rs +++ /dev/null @@ -1,392 +0,0 @@ -use itertools::Itertools; -use re_log_types::{RowId, TimeInt}; -use re_query::{ArchetypeView, ComponentWithInstances}; -use re_types::archetypes::Points2D; -use re_types::components::{Color, InstanceKey, Position2D}; - -#[test] -fn basic_single_iter() { - let instance_keys = InstanceKey::from_iter(0..2); - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - ]; - - let component = ComponentWithInstances::from_native(instance_keys, positions).unwrap(); - - let results = itertools::izip!( - positions.into_iter(), - component.values::().unwrap() - ) - .collect_vec(); - assert_eq!(results.len(), 2); - results - .iter() - .for_each(|(a, b)| assert_eq!(a, b.as_ref().unwrap())); -} - -#[test] -fn directly_joined_iter() { - let instance_keys = InstanceKey::from_iter(0..3); - - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - ]; - - let colors = [ - Color::from(0), // - Color::from(1), - Color::from(2), - ]; - - let positions_comp = - ComponentWithInstances::from_native(instance_keys.clone(), positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(instance_keys, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [ - Some(Color::from(0)), - Some(Color::from(1)), - Some(Color::from(2)), - ]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn joined_iter_dense_primary() { - let point_ids = InstanceKey::from_iter(0..3); - - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - ]; - - let color_ids = [ - InstanceKey(1), // - InstanceKey(2), - ]; - - let colors = [ - Color::from(1), // - Color::from(2), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [None, Some(Color::from(1)), Some(Color::from(2))]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn joined_iter_dense_secondary() { - let point_ids = [ - InstanceKey(0), // - InstanceKey(2), - InstanceKey(4), - ]; - - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - ]; - - let color_ids = InstanceKey::from_iter(0..5); - - let colors = [ - Color::from(0), // - Color::from(1), - Color::from(2), - Color::from(3), - Color::from(4), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [ - Some(Color::from(0)), // - Some(Color::from(2)), - Some(Color::from(4)), - ]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn complex_joined_iter() { - let point_ids = vec![ - InstanceKey(0), // - InstanceKey(17), - InstanceKey(42), - InstanceKey(96), - ]; - - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - ]; - - let color_ids = vec![ - InstanceKey(17), // - InstanceKey(19), - InstanceKey(44), - InstanceKey(96), - InstanceKey(254), - ]; - - let colors = vec![ - Color::from(17), // - Color::from(19), - Color::from(44), - Color::from(96), - Color::from(254), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [ - None, - Some(Color::from(17)), // - None, - Some(Color::from(96)), - ]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn single_visit() { - let instance_keys = InstanceKey::from_iter(0..4); - let positions = [ - Position2D::new(1.0, 2.0), - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - ]; - - let positions_comp = - ComponentWithInstances::from_native(instance_keys.clone(), positions).unwrap(); - - let arch_view = - ArchetypeView::::from_components(TimeInt::STATIC, RowId::ZERO, [positions_comp]); - - let mut instance_key_out = Vec::::new(); - let mut positions_out = Vec::::new(); - - itertools::izip!( - arch_view.iter_instance_keys(), - arch_view.iter_required_component::().unwrap() - ) - .for_each(|(inst, point)| { - instance_key_out.push(inst); - positions_out.push(point); - }); - - assert_eq!(instance_key_out, instance_keys); - assert_eq!(positions.as_slice(), positions_out.as_slice()); -} - -#[test] -fn joint_visit() { - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let point_ids = InstanceKey::from_iter(0..5); - - let colors = vec![ - Color::from(0xff000000), // - Color::from(0x00ff0000), - ]; - - let color_ids = vec![ - InstanceKey(2), // - InstanceKey(4), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions.clone()).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let mut positions_out = Vec::::new(); - let mut colors_out = Vec::>::new(); - - itertools::izip!( - arch_view.iter_required_component::().unwrap(), - arch_view.iter_optional_component::().unwrap() - ) - .for_each(|(point, color)| { - positions_out.push(point); - colors_out.push(color); - }); - - let expected_colors = vec![ - None, - None, - Some(Color::from(0xff000000)), - None, - Some(Color::from(0x00ff0000)), - ]; - - assert_eq!(positions, positions_out); - assert_eq!(expected_colors, colors_out); -} - -#[test] -fn joint_visit_with_empty() { - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let shared_ids = InstanceKey::from_iter(0..5); - - let colors: Vec = vec![]; - - let positions_comp = - ComponentWithInstances::from_native(shared_ids.clone(), positions.clone()).unwrap(); - let colors_comp = ComponentWithInstances::from_native(shared_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let positions_out = arch_view - .iter_required_component::() - .unwrap() - .collect_vec(); - let colors_out = arch_view - .iter_optional_component::() - .unwrap() - .collect_vec(); - assert_eq!(positions_out.len(), colors_out.len()); - - let expected_colors = vec![None, None, None, None, None]; - - assert_eq!(positions, positions_out); - assert_eq!(expected_colors, colors_out); -} - -#[test] -fn joint_visit_with_splat() { - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let shared_ids = InstanceKey::from_iter(0..5); - - let color = Color::from(0xff000000); - let colors: Vec = vec![color]; - - let positions_comp = - ComponentWithInstances::from_native(shared_ids, positions.clone()).unwrap(); - // TODO(#1893): Replace the instance_keys with shared_ids. - let colors_comp = - ComponentWithInstances::from_native(vec![InstanceKey::SPLAT], colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let positions_out = arch_view - .iter_required_component::() - .unwrap() - .collect_vec(); - let colors_out = arch_view - .iter_optional_component::() - .unwrap() - .collect_vec(); - assert_eq!(positions_out.len(), colors_out.len()); - - let expected_colors = vec![ - Some(color), - Some(color), - Some(color), - Some(color), - Some(color), - ]; - - assert_eq!(positions, positions_out); - assert_eq!(expected_colors, colors_out); -} diff --git a/crates/re_query/tests/store.rs b/crates/re_query/tests/store.rs deleted file mode 100644 index 6f6e87488211..000000000000 --- a/crates/re_query/tests/store.rs +++ /dev/null @@ -1,73 +0,0 @@ -use itertools::Itertools; - -use re_data_store::{test_row, DataStore}; -use re_log_types::EntityPath; -use re_log_types::{build_frame_nr, TimeInt, TimeType, Timeline}; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D}, - datagen::{build_some_colors, build_some_positions2d}, -}; -use re_types_core::Loggable as _; - -// --- - -// This one demonstrates a nasty edge case when stream-joining multiple iterators that happen to -// share the same exact row of data at some point (because, for that specific entry, it turns out -// that those component where inserted together). -// -// When that happens, one must be very careful to not only compare time and index row numbers, but -// also make sure that, if all else if equal, the primary iterator comes last so that it gathers as -// much state as possible! - -#[test] -fn range_join_across_single_row() { - for config in re_data_store::test_util::all_configs() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - config.clone(), - ); - range_join_across_single_row_impl(&mut store); - } -} - -fn range_join_across_single_row_impl(store: &mut DataStore) { - let ent_path = EntityPath::from("this/that"); - - let positions = build_some_positions2d(3); - let colors = build_some_colors(3); - let row = test_row!(ent_path @ [build_frame_nr(42)] => 3; [positions.clone(), colors.clone()]); - store.insert_row(&row).unwrap(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = re_data_store::RangeQuery::new( - timeline_frame_nr, - re_data_store::TimeRange::new(TimeInt::MIN, TimeInt::MAX), - ); - - let mut arch_views = re_query::range_archetype::( - store, &query, &ent_path, - ); - - let arch_view = arch_views.next().unwrap(); - assert!(arch_views.next().is_none()); - - let actual_instance_keys = arch_view.iter_instance_keys().collect_vec(); - let actual_positions = arch_view - .iter_required_component::() - .unwrap() - .collect_vec(); - let actual_colors = arch_view - .iter_optional_component::() - .unwrap() - .collect_vec(); - - let expected_instance_keys = vec![InstanceKey(0), InstanceKey(1), InstanceKey(2)]; - let expected_positions = positions; - let expected_colors = colors.into_iter().map(Some).collect_vec(); - - similar_asserts::assert_eq!(expected_instance_keys, actual_instance_keys); - similar_asserts::assert_eq!(expected_positions, actual_positions); - similar_asserts::assert_eq!(expected_colors, actual_colors); -} diff --git a/crates/re_space_view/Cargo.toml b/crates/re_space_view/Cargo.toml index cc5bab4a1c02..013e73ce7bcc 100644 --- a/crates/re_space_view/Cargo.toml +++ b/crates/re_space_view/Cargo.toml @@ -26,7 +26,6 @@ re_log.workspace = true re_log_types.workspace = true re_data_store.workspace = true re_entity_db.workspace = true -re_query.workspace = true re_query2.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_space_view_dataframe/Cargo.toml b/crates/re_space_view_dataframe/Cargo.toml index 969405f37a85..daa865ee5b44 100644 --- a/crates/re_space_view_dataframe/Cargo.toml +++ b/crates/re_space_view_dataframe/Cargo.toml @@ -23,7 +23,6 @@ re_data_store.workspace = true re_data_ui.workspace = true re_entity_db.workspace = true re_log_types.workspace = true -re_query.workspace = true re_query2.workspace = true re_renderer.workspace = true re_tracing.workspace = true diff --git a/crates/re_space_view_spatial/Cargo.toml b/crates/re_space_view_spatial/Cargo.toml index 3ac935a86647..99d793f70c5f 100644 --- a/crates/re_space_view_spatial/Cargo.toml +++ b/crates/re_space_view_spatial/Cargo.toml @@ -26,7 +26,6 @@ re_error.workspace = true re_format.workspace = true re_log_types.workspace = true re_log.workspace = true -re_query.workspace = true re_query2.workspace = true re_renderer = { workspace = true, features = [ "import-gltf", diff --git a/crates/re_space_view_text_document/Cargo.toml b/crates/re_space_view_text_document/Cargo.toml index b924d7ab60de..70a369abfa45 100644 --- a/crates/re_space_view_text_document/Cargo.toml +++ b/crates/re_space_view_text_document/Cargo.toml @@ -26,7 +26,6 @@ markdown = ["dep:egui_commonmark"] [dependencies] re_data_store.workspace = true re_log.workspace = true -re_query.workspace = true re_renderer.workspace = true re_space_view.workspace = true re_tracing.workspace = true diff --git a/crates/re_space_view_time_series/Cargo.toml b/crates/re_space_view_time_series/Cargo.toml index 8b0b69d7f89f..2b031765e7b8 100644 --- a/crates/re_space_view_time_series/Cargo.toml +++ b/crates/re_space_view_time_series/Cargo.toml @@ -23,7 +23,6 @@ re_data_store.workspace = true re_format.workspace = true re_log.workspace = true re_log_types.workspace = true -re_query.workspace = true re_query2.workspace = true re_renderer.workspace = true re_space_view.workspace = true diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 816b95a168ad..7be7e86d1dcb 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -25,7 +25,6 @@ re_entity_db = { workspace = true, features = ["serde"] } re_log_types.workspace = true re_log.workspace = true re_query2.workspace = true -re_query.workspace = true re_renderer.workspace = true re_smart_channel.workspace = true re_string_interner.workspace = true diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index a8413981515f..ef02ea868ba3 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -76,7 +76,7 @@ pub use clipboard::Clipboard; pub mod external { pub use nohash_hasher; - pub use {re_data_store, re_entity_db, re_log_types, re_query, re_ui}; + pub use {re_data_store, re_entity_db, re_log_types, re_query2, re_ui}; } // --------------------------------------------------------------------------- diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 61c60dfadf77..a80e16ba7539 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -46,10 +46,7 @@ pub enum SpaceViewSystemExecutionError { VisualizerSystemNotFound(&'static str), #[error(transparent)] - QueryError(#[from] re_query::QueryError), - - #[error(transparent)] - QueryError2(#[from] re_query2::QueryError), + QueryError(#[from] re_query2::QueryError), #[error(transparent)] DeserializationError(#[from] re_types::DeserializationError), From 0988a23ab3fc14a6a43ebda435f02d1175f9bc70 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 24 Apr 2024 12:56:20 +0200 Subject: [PATCH 3/9] re_query2 replaces re_query --- ARCHITECTURE.md | 1 - Cargo.lock | 20 +++++------ Cargo.toml | 2 +- crates/re_data_ui/src/component.rs | 2 +- .../re_data_ui/src/component_ui_registry.rs | 2 +- crates/re_data_ui/src/editors.rs | 2 +- crates/re_entity_db/Cargo.toml | 2 +- crates/re_entity_db/src/entity_db.rs | 28 +++++++-------- crates/re_entity_db/src/lib.rs | 4 +-- crates/{re_query2 => re_query}/Cargo.toml | 2 +- crates/{re_query2 => re_query}/README.md | 4 +-- .../benches/flat_vec_deque.rs | 2 +- .../benches/latest_at.rs | 4 +-- .../examples/latest_at.rs | 4 +-- .../examples/latest_at_archetype.rs | 6 ++-- .../{re_query2 => re_query}/examples/range.rs | 4 +-- .../src/bin/clamped_zip.rs | 0 .../src/bin/range_zip.rs | 0 crates/{re_query2 => re_query}/src/cache.rs | 0 .../src/cache_stats.rs | 0 .../src/clamped_zip/.gitattributes | 0 .../src/clamped_zip/generated.rs | 0 .../src/clamped_zip/mod.rs | 0 .../src/flat_vec_deque.rs | 0 .../src/latest_at/helpers.rs | 0 .../src/latest_at/mod.rs | 0 .../src/latest_at/query.rs | 0 .../src/latest_at/results.rs | 0 .../src/latest_at/to_archetype/.gitattributes | 0 .../to_archetype/annotation_context.rs | 0 .../src/latest_at/to_archetype/arrows2d.rs | 0 .../src/latest_at/to_archetype/arrows3d.rs | 0 .../src/latest_at/to_archetype/asset3d.rs | 0 .../src/latest_at/to_archetype/bar_chart.rs | 0 .../src/latest_at/to_archetype/boxes2d.rs | 0 .../src/latest_at/to_archetype/boxes3d.rs | 0 .../src/latest_at/to_archetype/clear.rs | 0 .../to_archetype/container_blueprint.rs | 0 .../src/latest_at/to_archetype/depth_image.rs | 0 .../to_archetype/disconnected_space.rs | 0 .../src/latest_at/to_archetype/image.rs | 0 .../latest_at/to_archetype/line_strips2d.rs | 0 .../latest_at/to_archetype/line_strips3d.rs | 0 .../src/latest_at/to_archetype/mesh3d.rs | 0 .../src/latest_at/to_archetype/mod.rs | 0 .../latest_at/to_archetype/panel_blueprint.rs | 0 .../src/latest_at/to_archetype/pinhole.rs | 0 .../src/latest_at/to_archetype/plot_legend.rs | 0 .../src/latest_at/to_archetype/points2d.rs | 0 .../src/latest_at/to_archetype/points3d.rs | 0 .../src/latest_at/to_archetype/scalar.rs | 0 .../src/latest_at/to_archetype/scalar_axis.rs | 0 .../to_archetype/segmentation_image.rs | 0 .../src/latest_at/to_archetype/series_line.rs | 0 .../latest_at/to_archetype/series_point.rs | 0 .../to_archetype/space_view_blueprint.rs | 0 .../to_archetype/space_view_contents.rs | 0 .../src/latest_at/to_archetype/tensor.rs | 0 .../latest_at/to_archetype/text_document.rs | 0 .../src/latest_at/to_archetype/text_log.rs | 0 .../src/latest_at/to_archetype/transform3d.rs | 0 .../to_archetype/view_coordinates.rs | 0 .../to_archetype/viewport_blueprint.rs | 0 crates/{re_query2 => re_query}/src/lib.rs | 0 crates/{re_query2 => re_query}/src/promise.rs | 0 .../{re_query2 => re_query}/src/range/mod.rs | 0 .../src/range/query.rs | 0 .../src/range/results.rs | 0 .../src/range_zip/.gitattributes | 0 .../src/range_zip/generated.rs | 0 .../src/range_zip/mod.rs | 0 .../src/visible_history.rs | 0 .../tests/latest_at.rs | 6 ++-- crates/{re_query2 => re_query}/tests/range.rs | 4 +-- crates/re_space_view/Cargo.toml | 2 +- crates/re_space_view/src/space_view.rs | 2 +- .../re_space_view/src/space_view_contents.rs | 2 +- crates/re_space_view/src/sub_archetypes.rs | 2 +- crates/re_space_view/src/visual_time_range.rs | 2 +- crates/re_space_view_dataframe/Cargo.toml | 2 +- crates/re_space_view_spatial/Cargo.toml | 2 +- .../src/visualizers/arrows2d.rs | 2 +- .../src/visualizers/arrows3d.rs | 2 +- .../src/visualizers/assets3d.rs | 2 +- .../src/visualizers/boxes2d.rs | 2 +- .../src/visualizers/boxes3d.rs | 2 +- .../src/visualizers/entity_iterator.rs | 2 +- .../src/visualizers/images.rs | 2 +- .../src/visualizers/lines2d.rs | 2 +- .../src/visualizers/lines3d.rs | 2 +- .../src/visualizers/meshes.rs | 2 +- .../src/visualizers/points2d.rs | 2 +- .../src/visualizers/points3d.rs | 2 +- .../src/visualizers/results_ext.rs | 34 +++++++++---------- .../src/visualizer_system.rs | 2 +- .../src/visualizer_system.rs | 2 +- crates/re_space_view_text_log/Cargo.toml | 2 +- .../src/visualizer_system.rs | 8 ++--- crates/re_space_view_time_series/Cargo.toml | 2 +- .../src/line_visualizer_system.rs | 6 ++-- .../src/point_visualizer_system.rs | 8 ++--- .../src/codegen/rust/to_archetype.rs | 8 ++--- crates/re_viewer/Cargo.toml | 2 +- crates/re_viewer/src/lib.rs | 2 +- crates/re_viewer/src/ui/memory_panel.rs | 2 +- crates/re_viewer_context/Cargo.toml | 2 +- .../src/component_ui_registry.rs | 2 +- crates/re_viewer_context/src/item.rs | 2 +- crates/re_viewer_context/src/lib.rs | 2 +- .../re_viewer_context/src/space_view/mod.rs | 2 +- crates/re_viewer_context/src/store_hub.rs | 2 +- crates/re_viewport/src/container.rs | 2 +- crates/re_viewport/src/viewport_blueprint.rs | 2 +- examples/rust/custom_space_view/Cargo.toml | 2 +- .../color_coordinates_visualizer_system.rs | 10 +++--- scripts/lint.py | 2 +- 116 files changed, 122 insertions(+), 123 deletions(-) rename crates/{re_query2 => re_query}/Cargo.toml (99%) rename crates/{re_query2 => re_query}/README.md (72%) rename crates/{re_query2 => re_query}/benches/flat_vec_deque.rs (99%) rename crates/{re_query2 => re_query}/benches/latest_at.rs (99%) rename crates/{re_query2 => re_query}/examples/latest_at.rs (98%) rename crates/{re_query2 => re_query}/examples/latest_at_archetype.rs (94%) rename crates/{re_query2 => re_query}/examples/range.rs (98%) rename crates/{re_query2 => re_query}/src/bin/clamped_zip.rs (100%) rename crates/{re_query2 => re_query}/src/bin/range_zip.rs (100%) rename crates/{re_query2 => re_query}/src/cache.rs (100%) rename crates/{re_query2 => re_query}/src/cache_stats.rs (100%) rename crates/{re_query2 => re_query}/src/clamped_zip/.gitattributes (100%) rename crates/{re_query2 => re_query}/src/clamped_zip/generated.rs (100%) rename crates/{re_query2 => re_query}/src/clamped_zip/mod.rs (100%) rename crates/{re_query2 => re_query}/src/flat_vec_deque.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/helpers.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/mod.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/query.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/results.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/.gitattributes (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/annotation_context.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/arrows2d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/arrows3d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/asset3d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/bar_chart.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/boxes2d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/boxes3d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/clear.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/container_blueprint.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/depth_image.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/disconnected_space.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/image.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/line_strips2d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/line_strips3d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/mesh3d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/mod.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/panel_blueprint.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/pinhole.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/plot_legend.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/points2d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/points3d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/scalar.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/scalar_axis.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/segmentation_image.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/series_line.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/series_point.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/space_view_blueprint.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/space_view_contents.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/tensor.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/text_document.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/text_log.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/transform3d.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/view_coordinates.rs (100%) rename crates/{re_query2 => re_query}/src/latest_at/to_archetype/viewport_blueprint.rs (100%) rename crates/{re_query2 => re_query}/src/lib.rs (100%) rename crates/{re_query2 => re_query}/src/promise.rs (100%) rename crates/{re_query2 => re_query}/src/range/mod.rs (100%) rename crates/{re_query2 => re_query}/src/range/query.rs (100%) rename crates/{re_query2 => re_query}/src/range/results.rs (100%) rename crates/{re_query2 => re_query}/src/range_zip/.gitattributes (100%) rename crates/{re_query2 => re_query}/src/range_zip/generated.rs (100%) rename crates/{re_query2 => re_query}/src/range_zip/mod.rs (100%) rename crates/{re_query2 => re_query}/src/visible_history.rs (100%) rename crates/{re_query2 => re_query}/tests/latest_at.rs (99%) rename crates/{re_query2 => re_query}/tests/range.rs (99%) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 0c23e5f22566..f7c54b5dd2da 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -149,7 +149,6 @@ Update instructions: |----------------------|--------------------------------------------------------------------------| | re_entity_db | In-memory storage of Rerun entities | | re_query | Querying data in the re_data_store | -| re_query2 | Caching datastructures for re_query | | re_types | The built-in Rerun data types, component types, and archetypes. | | re_types_blueprint | The core traits and types that power Rerun's Blueprint sub-system. | | re_log_encoding | Helpers for encoding and transporting Rerun log messages | diff --git a/Cargo.lock b/Cargo.lock index 5d6ea852edf8..ac78976d7797 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,7 +1418,7 @@ version = "0.16.0-alpha.2" dependencies = [ "mimalloc", "re_crash_handler", - "re_query2", + "re_query", "re_sdk_comms", "re_viewer", ] @@ -4308,7 +4308,7 @@ dependencies = [ "re_log", "re_log_encoding", "re_log_types", - "re_query2", + "re_query", "re_smart_channel", "re_tracing", "re_types", @@ -4455,7 +4455,7 @@ dependencies = [ ] [[package]] -name = "re_query2" +name = "re_query" version = "0.16.0-alpha.2" dependencies = [ "ahash", @@ -4629,7 +4629,7 @@ dependencies = [ "re_entity_db", "re_log", "re_log_types", - "re_query2", + "re_query", "re_tracing", "re_types", "re_types_core", @@ -4666,7 +4666,7 @@ dependencies = [ "re_data_ui", "re_entity_db", "re_log_types", - "re_query2", + "re_query", "re_renderer", "re_tracing", "re_types_core", @@ -4698,7 +4698,7 @@ dependencies = [ "re_format", "re_log", "re_log_types", - "re_query2", + "re_query", "re_renderer", "re_space_view", "re_tracing", @@ -4765,7 +4765,7 @@ dependencies = [ "re_entity_db", "re_log", "re_log_types", - "re_query2", + "re_query", "re_renderer", "re_tracing", "re_types", @@ -4785,7 +4785,7 @@ dependencies = [ "re_format", "re_log", "re_log_types", - "re_query2", + "re_query", "re_renderer", "re_space_view", "re_tracing", @@ -5001,7 +5001,7 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_memory", - "re_query2", + "re_query", "re_renderer", "re_smart_channel", "re_space_view", @@ -5060,7 +5060,7 @@ dependencies = [ "re_entity_db", "re_log", "re_log_types", - "re_query2", + "re_query", "re_renderer", "re_smart_channel", "re_string_interner", diff --git a/Cargo.toml b/Cargo.toml index e6c265343f8f..778307ce3fa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ re_log = { path = "crates/re_log", version = "=0.16.0-alpha.2", default-features re_log_encoding = { path = "crates/re_log_encoding", version = "=0.16.0-alpha.2", default-features = false } re_log_types = { path = "crates/re_log_types", version = "=0.16.0-alpha.2", default-features = false } re_memory = { path = "crates/re_memory", version = "=0.16.0-alpha.2", default-features = false } -re_query2 = { path = "crates/re_query2", version = "=0.16.0-alpha.2", default-features = false } +re_query = { path = "crates/re_query", version = "=0.16.0-alpha.2", default-features = false } re_renderer = { path = "crates/re_renderer", version = "=0.16.0-alpha.2", default-features = false } re_sdk = { path = "crates/re_sdk", version = "=0.16.0-alpha.2", default-features = false } re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.16.0-alpha.2", default-features = false } diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index 09498e200955..dc3c9a66ad4d 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use egui::NumExt; use re_entity_db::{ - external::re_query2::CachedLatestAtComponentResults, EntityPath, InstancePath, + external::re_query::CachedLatestAtComponentResults, EntityPath, InstancePath, }; use re_types::ComponentName; use re_ui::SyntaxHighlighting as _; diff --git a/crates/re_data_ui/src/component_ui_registry.rs b/crates/re_data_ui/src/component_ui_registry.rs index 0c81db82a40d..89bdda270d9c 100644 --- a/crates/re_data_ui/src/component_ui_registry.rs +++ b/crates/re_data_ui/src/component_ui_registry.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query2::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query::CachedLatestAtComponentResults, EntityDb}; use re_log_types::{external::arrow2, EntityPath}; use re_types::external::arrow2::array::Utf8Array; use re_viewer_context::{ComponentUiRegistry, UiVerbosity, ViewerContext}; diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index 4b05b89381c4..e794d4b7814f 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -2,7 +2,7 @@ use egui::NumExt as _; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query2::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query::CachedLatestAtComponentResults, EntityDb}; use re_log_types::EntityPath; use re_types::{ components::{ diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index 202ad566d862..178cc0f8e3ee 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -33,7 +33,7 @@ re_int_histogram.workspace = true re_log.workspace = true re_log_encoding = { workspace = true, features = ["decoder"] } re_log_types.workspace = true -re_query2 = { workspace = true, features = ["to_archetype"] } +re_query = { workspace = true, features = ["to_archetype"] } re_smart_channel.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index f77dd7ad1e32..d82b9fb3279e 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -12,7 +12,7 @@ use re_log_types::{ EntityPathHash, LogMsg, RowId, SetStoreInfo, StoreId, StoreInfo, StoreKind, TimePoint, TimeRange, TimeRangeF, Timeline, }; -use re_query2::PromiseResult; +use re_query::PromiseResult; use re_types_core::{components::InstanceKey, Archetype, Loggable}; use crate::{ClearCascade, CompactedStoreEvents, Error, TimesPerTimeline}; @@ -117,10 +117,10 @@ pub struct EntityDb { data_store: DataStore, /// The active promise resolver for this DB. - resolver: re_query2::PromiseResolver, + resolver: re_query::PromiseResolver, /// Query caches for the data in [`Self::data_store`]. - query_caches: re_query2::Caches, + query_caches: re_query::Caches, stats: IngestionStatistics, } @@ -132,7 +132,7 @@ impl EntityDb { InstanceKey::name(), DataStoreConfig::default(), ); - let query_caches = re_query2::Caches::new(&data_store); + let query_caches = re_query::Caches::new(&data_store); Self { data_source: None, set_store_info: None, @@ -142,7 +142,7 @@ impl EntityDb { times_per_timeline: Default::default(), tree: crate::EntityTree::root(), data_store, - resolver: re_query2::PromiseResolver::default(), + resolver: re_query::PromiseResolver::default(), query_caches, stats: IngestionStatistics::new(store_id), } @@ -192,12 +192,12 @@ impl EntityDb { } #[inline] - pub fn query_caches(&self) -> &re_query2::Caches { + pub fn query_caches(&self) -> &re_query::Caches { &self.query_caches } #[inline] - pub fn resolver(&self) -> &re_query2::PromiseResolver { + pub fn resolver(&self) -> &re_query::PromiseResolver { &self.resolver } @@ -209,7 +209,7 @@ impl EntityDb { query: &re_data_store::LatestAtQuery, ) -> PromiseResult> where - re_query2::CachedLatestAtResults: re_query2::ToArchetype, + re_query::CachedLatestAtResults: re_query::ToArchetype, { let results = self.query_caches().latest_at( self.store(), @@ -218,12 +218,12 @@ impl EntityDb { A::all_components().iter().copied(), // no generics! ); - use re_query2::ToArchetype as _; + use re_query::ToArchetype as _; match results.to_archetype(self.resolver()).flatten() { PromiseResult::Pending => PromiseResult::Pending, PromiseResult::Error(err) => { - if let Some(err) = err.downcast_ref::() { - if matches!(err, re_query2::QueryError::PrimaryNotFound(_)) { + if let Some(err) = err.downcast_ref::() { + if matches!(err, re_query::QueryError::PrimaryNotFound(_)) { return PromiseResult::Ready(None); } } @@ -240,7 +240,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { + ) -> Option> { self.query_caches().latest_at_component::( self.store(), self.resolver(), @@ -254,7 +254,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { + ) -> Option> { self.query_caches().latest_at_component_quiet::( self.store(), self.resolver(), @@ -268,7 +268,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option<(EntityPath, re_query2::CachedLatestAtMonoResult)> { + ) -> Option<(EntityPath, re_query::CachedLatestAtMonoResult)> { self.query_caches() .latest_at_component_at_closest_ancestor::( self.store(), diff --git a/crates/re_entity_db/src/lib.rs b/crates/re_entity_db/src/lib.rs index c403a71de340..1d981b4a4d3f 100644 --- a/crates/re_entity_db/src/lib.rs +++ b/crates/re_entity_db/src/lib.rs @@ -34,7 +34,7 @@ pub(crate) use self::entity_tree::{ClearCascade, CompactedStoreEvents}; use re_log_types::DataTableError; pub use re_log_types::{EntityPath, EntityPathPart, TimeInt, Timeline}; -pub use re_query2::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +pub use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; #[cfg(feature = "serde")] pub use blueprint::components::EntityPropertiesComponent; @@ -43,7 +43,7 @@ pub use editable_auto_value::EditableAutoValue; pub mod external { pub use re_data_store; - pub use re_query2; + pub use re_query; } // ---------------------------------------------------------------------------- diff --git a/crates/re_query2/Cargo.toml b/crates/re_query/Cargo.toml similarity index 99% rename from crates/re_query2/Cargo.toml rename to crates/re_query/Cargo.toml index 6ad863379d29..c62574cb88e7 100644 --- a/crates/re_query2/Cargo.toml +++ b/crates/re_query/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "re_query2" +name = "re_query" authors.workspace = true description = "High-level query APIs" edition.workspace = true diff --git a/crates/re_query2/README.md b/crates/re_query/README.md similarity index 72% rename from crates/re_query2/README.md rename to crates/re_query/README.md index 2928fb493f1f..7d0c4241b353 100644 --- a/crates/re_query2/README.md +++ b/crates/re_query/README.md @@ -1,8 +1,8 @@ -# re_query2 +# re_query Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_query2.svg)](https://crates.io/crates/re_query2) +[![Latest version](https://img.shields.io/crates/v/re_query.svg)](https://crates.io/crates/re_query) [![Documentation](https://docs.rs/re_query/badge.svg)](https://docs.rs/re_query) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/re_query2/benches/flat_vec_deque.rs b/crates/re_query/benches/flat_vec_deque.rs similarity index 99% rename from crates/re_query2/benches/flat_vec_deque.rs rename to crates/re_query/benches/flat_vec_deque.rs index a435d40d64ae..bce849d9a43c 100644 --- a/crates/re_query2/benches/flat_vec_deque.rs +++ b/crates/re_query/benches/flat_vec_deque.rs @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use itertools::Itertools as _; -use re_query2::FlatVecDeque; +use re_query::FlatVecDeque; // --- diff --git a/crates/re_query2/benches/latest_at.rs b/crates/re_query/benches/latest_at.rs similarity index 99% rename from crates/re_query2/benches/latest_at.rs rename to crates/re_query/benches/latest_at.rs index a724c2e1e301..0c76e42a3c88 100644 --- a/crates/re_query2/benches/latest_at.rs +++ b/crates/re_query/benches/latest_at.rs @@ -6,8 +6,8 @@ use criterion::{criterion_group, criterion_main, Criterion}; use itertools::Itertools; use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query2::{clamped_zip_1x1, PromiseResolver}; -use re_query2::{CachedLatestAtResults, Caches}; +use re_query::{clamped_zip_1x1, PromiseResolver}; +use re_query::{CachedLatestAtResults, Caches}; use re_types::{ archetypes::Points2D, components::{Color, InstanceKey, Position2D, Text}, diff --git a/crates/re_query2/examples/latest_at.rs b/crates/re_query/examples/latest_at.rs similarity index 98% rename from crates/re_query2/examples/latest_at.rs rename to crates/re_query/examples/latest_at.rs index aa43552574c6..aab700222652 100644 --- a/crates/re_query2/examples/latest_at.rs +++ b/crates/re_query/examples/latest_at.rs @@ -4,7 +4,7 @@ use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; use re_types_core::{Archetype as _, Loggable as _}; -use re_query2::{ +use re_query::{ clamped_zip_1x2, CachedLatestAtComponentResults, CachedLatestAtResults, PromiseResolver, PromiseResult, }; @@ -22,7 +22,7 @@ fn main() -> anyhow::Result<()> { let query = LatestAtQuery::latest(timeline); eprintln!("query:{query:?}"); - let caches = re_query2::Caches::new(&store); + let caches = re_query::Caches::new(&store); // First, get the results for this query. // diff --git a/crates/re_query2/examples/latest_at_archetype.rs b/crates/re_query/examples/latest_at_archetype.rs similarity index 94% rename from crates/re_query2/examples/latest_at_archetype.rs rename to crates/re_query/examples/latest_at_archetype.rs index 3205598557e5..37766c6aa8aa 100644 --- a/crates/re_query2/examples/latest_at_archetype.rs +++ b/crates/re_query/examples/latest_at_archetype.rs @@ -7,7 +7,7 @@ use re_types::{ }; use re_types_core::{Archetype as _, Loggable as _}; -use re_query2::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; +use re_query::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; // --- @@ -22,7 +22,7 @@ fn main() -> anyhow::Result<()> { let query = LatestAtQuery::latest(timeline); eprintln!("query:{query:?}"); - let caches = re_query2::Caches::new(&store); + let caches = re_query::Caches::new(&store); // First, get the results for this query. // @@ -37,7 +37,7 @@ fn main() -> anyhow::Result<()> { // Then make use of the `ToArchetype` helper trait in order to query, resolve, deserialize and // cache an entire archetype all at once. - use re_query2::ToArchetype as _; + use re_query::ToArchetype as _; let arch: Points2D = match results.to_archetype(&resolver).flatten() { PromiseResult::Pending => { diff --git a/crates/re_query2/examples/range.rs b/crates/re_query/examples/range.rs similarity index 98% rename from crates/re_query2/examples/range.rs rename to crates/re_query/examples/range.rs index d1bd8e4d55da..c62ac2ee54b1 100644 --- a/crates/re_query2/examples/range.rs +++ b/crates/re_query/examples/range.rs @@ -4,7 +4,7 @@ use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline}; use re_types_core::{Archetype as _, Loggable as _}; -use re_query2::{ +use re_query::{ clamped_zip_1x2, range_zip_1x2, CachedRangeComponentResults, CachedRangeResults, PromiseResolver, PromiseResult, }; @@ -22,7 +22,7 @@ fn main() -> anyhow::Result<()> { let query = RangeQuery::new(timeline, TimeRange::EVERYTHING); eprintln!("query:{query:?}"); - let caches = re_query2::Caches::new(&store); + let caches = re_query::Caches::new(&store); // First, get the raw results for this query. // diff --git a/crates/re_query2/src/bin/clamped_zip.rs b/crates/re_query/src/bin/clamped_zip.rs similarity index 100% rename from crates/re_query2/src/bin/clamped_zip.rs rename to crates/re_query/src/bin/clamped_zip.rs diff --git a/crates/re_query2/src/bin/range_zip.rs b/crates/re_query/src/bin/range_zip.rs similarity index 100% rename from crates/re_query2/src/bin/range_zip.rs rename to crates/re_query/src/bin/range_zip.rs diff --git a/crates/re_query2/src/cache.rs b/crates/re_query/src/cache.rs similarity index 100% rename from crates/re_query2/src/cache.rs rename to crates/re_query/src/cache.rs diff --git a/crates/re_query2/src/cache_stats.rs b/crates/re_query/src/cache_stats.rs similarity index 100% rename from crates/re_query2/src/cache_stats.rs rename to crates/re_query/src/cache_stats.rs diff --git a/crates/re_query2/src/clamped_zip/.gitattributes b/crates/re_query/src/clamped_zip/.gitattributes similarity index 100% rename from crates/re_query2/src/clamped_zip/.gitattributes rename to crates/re_query/src/clamped_zip/.gitattributes diff --git a/crates/re_query2/src/clamped_zip/generated.rs b/crates/re_query/src/clamped_zip/generated.rs similarity index 100% rename from crates/re_query2/src/clamped_zip/generated.rs rename to crates/re_query/src/clamped_zip/generated.rs diff --git a/crates/re_query2/src/clamped_zip/mod.rs b/crates/re_query/src/clamped_zip/mod.rs similarity index 100% rename from crates/re_query2/src/clamped_zip/mod.rs rename to crates/re_query/src/clamped_zip/mod.rs diff --git a/crates/re_query2/src/flat_vec_deque.rs b/crates/re_query/src/flat_vec_deque.rs similarity index 100% rename from crates/re_query2/src/flat_vec_deque.rs rename to crates/re_query/src/flat_vec_deque.rs diff --git a/crates/re_query2/src/latest_at/helpers.rs b/crates/re_query/src/latest_at/helpers.rs similarity index 100% rename from crates/re_query2/src/latest_at/helpers.rs rename to crates/re_query/src/latest_at/helpers.rs diff --git a/crates/re_query2/src/latest_at/mod.rs b/crates/re_query/src/latest_at/mod.rs similarity index 100% rename from crates/re_query2/src/latest_at/mod.rs rename to crates/re_query/src/latest_at/mod.rs diff --git a/crates/re_query2/src/latest_at/query.rs b/crates/re_query/src/latest_at/query.rs similarity index 100% rename from crates/re_query2/src/latest_at/query.rs rename to crates/re_query/src/latest_at/query.rs diff --git a/crates/re_query2/src/latest_at/results.rs b/crates/re_query/src/latest_at/results.rs similarity index 100% rename from crates/re_query2/src/latest_at/results.rs rename to crates/re_query/src/latest_at/results.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/.gitattributes b/crates/re_query/src/latest_at/to_archetype/.gitattributes similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/.gitattributes rename to crates/re_query/src/latest_at/to_archetype/.gitattributes diff --git a/crates/re_query2/src/latest_at/to_archetype/annotation_context.rs b/crates/re_query/src/latest_at/to_archetype/annotation_context.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/annotation_context.rs rename to crates/re_query/src/latest_at/to_archetype/annotation_context.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/arrows2d.rs b/crates/re_query/src/latest_at/to_archetype/arrows2d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/arrows2d.rs rename to crates/re_query/src/latest_at/to_archetype/arrows2d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/arrows3d.rs b/crates/re_query/src/latest_at/to_archetype/arrows3d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/arrows3d.rs rename to crates/re_query/src/latest_at/to_archetype/arrows3d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/asset3d.rs b/crates/re_query/src/latest_at/to_archetype/asset3d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/asset3d.rs rename to crates/re_query/src/latest_at/to_archetype/asset3d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/bar_chart.rs b/crates/re_query/src/latest_at/to_archetype/bar_chart.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/bar_chart.rs rename to crates/re_query/src/latest_at/to_archetype/bar_chart.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/boxes2d.rs b/crates/re_query/src/latest_at/to_archetype/boxes2d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/boxes2d.rs rename to crates/re_query/src/latest_at/to_archetype/boxes2d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/boxes3d.rs b/crates/re_query/src/latest_at/to_archetype/boxes3d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/boxes3d.rs rename to crates/re_query/src/latest_at/to_archetype/boxes3d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/clear.rs b/crates/re_query/src/latest_at/to_archetype/clear.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/clear.rs rename to crates/re_query/src/latest_at/to_archetype/clear.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/container_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/container_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/container_blueprint.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/depth_image.rs b/crates/re_query/src/latest_at/to_archetype/depth_image.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/depth_image.rs rename to crates/re_query/src/latest_at/to_archetype/depth_image.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/disconnected_space.rs b/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/disconnected_space.rs rename to crates/re_query/src/latest_at/to_archetype/disconnected_space.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/image.rs b/crates/re_query/src/latest_at/to_archetype/image.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/image.rs rename to crates/re_query/src/latest_at/to_archetype/image.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/line_strips2d.rs b/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/line_strips2d.rs rename to crates/re_query/src/latest_at/to_archetype/line_strips2d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/line_strips3d.rs b/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/line_strips3d.rs rename to crates/re_query/src/latest_at/to_archetype/line_strips3d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/mesh3d.rs b/crates/re_query/src/latest_at/to_archetype/mesh3d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/mesh3d.rs rename to crates/re_query/src/latest_at/to_archetype/mesh3d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/mod.rs b/crates/re_query/src/latest_at/to_archetype/mod.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/mod.rs rename to crates/re_query/src/latest_at/to_archetype/mod.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/panel_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/panel_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/pinhole.rs b/crates/re_query/src/latest_at/to_archetype/pinhole.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/pinhole.rs rename to crates/re_query/src/latest_at/to_archetype/pinhole.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/plot_legend.rs b/crates/re_query/src/latest_at/to_archetype/plot_legend.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/plot_legend.rs rename to crates/re_query/src/latest_at/to_archetype/plot_legend.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/points2d.rs b/crates/re_query/src/latest_at/to_archetype/points2d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/points2d.rs rename to crates/re_query/src/latest_at/to_archetype/points2d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/points3d.rs b/crates/re_query/src/latest_at/to_archetype/points3d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/points3d.rs rename to crates/re_query/src/latest_at/to_archetype/points3d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/scalar.rs b/crates/re_query/src/latest_at/to_archetype/scalar.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/scalar.rs rename to crates/re_query/src/latest_at/to_archetype/scalar.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/scalar_axis.rs b/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/scalar_axis.rs rename to crates/re_query/src/latest_at/to_archetype/scalar_axis.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/segmentation_image.rs b/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/segmentation_image.rs rename to crates/re_query/src/latest_at/to_archetype/segmentation_image.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/series_line.rs b/crates/re_query/src/latest_at/to_archetype/series_line.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/series_line.rs rename to crates/re_query/src/latest_at/to_archetype/series_line.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/series_point.rs b/crates/re_query/src/latest_at/to_archetype/series_point.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/series_point.rs rename to crates/re_query/src/latest_at/to_archetype/series_point.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/space_view_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/space_view_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/space_view_contents.rs b/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/space_view_contents.rs rename to crates/re_query/src/latest_at/to_archetype/space_view_contents.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/tensor.rs b/crates/re_query/src/latest_at/to_archetype/tensor.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/tensor.rs rename to crates/re_query/src/latest_at/to_archetype/tensor.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/text_document.rs b/crates/re_query/src/latest_at/to_archetype/text_document.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/text_document.rs rename to crates/re_query/src/latest_at/to_archetype/text_document.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/text_log.rs b/crates/re_query/src/latest_at/to_archetype/text_log.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/text_log.rs rename to crates/re_query/src/latest_at/to_archetype/text_log.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/transform3d.rs b/crates/re_query/src/latest_at/to_archetype/transform3d.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/transform3d.rs rename to crates/re_query/src/latest_at/to_archetype/transform3d.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/view_coordinates.rs b/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/view_coordinates.rs rename to crates/re_query/src/latest_at/to_archetype/view_coordinates.rs diff --git a/crates/re_query2/src/latest_at/to_archetype/viewport_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs similarity index 100% rename from crates/re_query2/src/latest_at/to_archetype/viewport_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs diff --git a/crates/re_query2/src/lib.rs b/crates/re_query/src/lib.rs similarity index 100% rename from crates/re_query2/src/lib.rs rename to crates/re_query/src/lib.rs diff --git a/crates/re_query2/src/promise.rs b/crates/re_query/src/promise.rs similarity index 100% rename from crates/re_query2/src/promise.rs rename to crates/re_query/src/promise.rs diff --git a/crates/re_query2/src/range/mod.rs b/crates/re_query/src/range/mod.rs similarity index 100% rename from crates/re_query2/src/range/mod.rs rename to crates/re_query/src/range/mod.rs diff --git a/crates/re_query2/src/range/query.rs b/crates/re_query/src/range/query.rs similarity index 100% rename from crates/re_query2/src/range/query.rs rename to crates/re_query/src/range/query.rs diff --git a/crates/re_query2/src/range/results.rs b/crates/re_query/src/range/results.rs similarity index 100% rename from crates/re_query2/src/range/results.rs rename to crates/re_query/src/range/results.rs diff --git a/crates/re_query2/src/range_zip/.gitattributes b/crates/re_query/src/range_zip/.gitattributes similarity index 100% rename from crates/re_query2/src/range_zip/.gitattributes rename to crates/re_query/src/range_zip/.gitattributes diff --git a/crates/re_query2/src/range_zip/generated.rs b/crates/re_query/src/range_zip/generated.rs similarity index 100% rename from crates/re_query2/src/range_zip/generated.rs rename to crates/re_query/src/range_zip/generated.rs diff --git a/crates/re_query2/src/range_zip/mod.rs b/crates/re_query/src/range_zip/mod.rs similarity index 100% rename from crates/re_query2/src/range_zip/mod.rs rename to crates/re_query/src/range_zip/mod.rs diff --git a/crates/re_query2/src/visible_history.rs b/crates/re_query/src/visible_history.rs similarity index 100% rename from crates/re_query2/src/visible_history.rs rename to crates/re_query/src/visible_history.rs diff --git a/crates/re_query2/tests/latest_at.rs b/crates/re_query/tests/latest_at.rs similarity index 99% rename from crates/re_query2/tests/latest_at.rs rename to crates/re_query/tests/latest_at.rs index c91dc3edeeb2..b16caa84c495 100644 --- a/crates/re_query2/tests/latest_at.rs +++ b/crates/re_query/tests/latest_at.rs @@ -8,8 +8,8 @@ use re_log_types::{ example_components::{MyColor, MyPoint, MyPoints}, DataRow, EntityPath, RowId, TimePoint, }; -use re_query2::Caches; -use re_query2::PromiseResolver; +use re_query::Caches; +use re_query::PromiseResolver; use re_types::Archetype as _; use re_types_core::{components::InstanceKey, Loggable as _}; @@ -500,7 +500,7 @@ use re_types_core::{components::InstanceKey, Loggable as _}; // .flatten() // .unwrap(); // -// let expected = re_query2::latest_at( +// let expected = re_query::latest_at( // store, // query, // entity_path, diff --git a/crates/re_query2/tests/range.rs b/crates/re_query/tests/range.rs similarity index 99% rename from crates/re_query2/tests/range.rs rename to crates/re_query/tests/range.rs index 3a7f6de0ab7e..4cdccf88c626 100644 --- a/crates/re_query2/tests/range.rs +++ b/crates/re_query/tests/range.rs @@ -6,7 +6,7 @@ use re_log_types::{ example_components::{MyColor, MyPoint, MyPoints}, DataRow, EntityPath, RowId, TimePoint, }; -use re_query2::{Caches, PromiseResolver, PromiseResult}; +use re_query::{Caches, PromiseResolver, PromiseResult}; use re_types::{components::InstanceKey, Archetype}; use re_types_core::Loggable as _; @@ -537,7 +537,7 @@ use re_types_core::Loggable as _; // )); // let cached_all_colors_indexed = cached_all_colors.range_indexed(); // -// let expected = re_query2::range( +// let expected = re_query::range( // store, // query, // entity_path, diff --git a/crates/re_space_view/Cargo.toml b/crates/re_space_view/Cargo.toml index 013e73ce7bcc..36b53d591f51 100644 --- a/crates/re_space_view/Cargo.toml +++ b/crates/re_space_view/Cargo.toml @@ -26,7 +26,7 @@ re_log.workspace = true re_log_types.workspace = true re_data_store.workspace = true re_entity_db.workspace = true -re_query2.workspace = true +re_query.workspace = true re_tracing.workspace = true re_types_core.workspace = true re_types.workspace = true diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index bcf94714852f..8e435edeb682 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -1,6 +1,6 @@ use itertools::{FoldWhile, Itertools}; use nohash_hasher::IntMap; -use re_entity_db::external::re_query2::PromiseResult; +use re_entity_db::external::re_query::PromiseResult; use crate::SpaceViewContents; use re_data_store::LatestAtQuery; diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 4ed247703593..82116aef381e 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -3,7 +3,7 @@ use slotmap::SlotMap; use smallvec::SmallVec; use re_entity_db::{ - external::{re_data_store::LatestAtQuery, re_query2::PromiseResult}, + external::{re_data_store::LatestAtQuery, re_query::PromiseResult}, EntityDb, EntityProperties, EntityPropertiesComponent, EntityPropertyMap, EntityTree, }; use re_log_types::{ diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 961fb8659aad..671248628e0a 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -1,6 +1,6 @@ use re_data_store::LatestAtQuery; use re_entity_db::{ - external::re_query2::{CachedLatestAtResults, PromiseResult, ToArchetype}, + external::re_query::{CachedLatestAtResults, PromiseResult, ToArchetype}, EntityDb, }; use re_log_types::EntityPath; diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs index cfa4590fbd06..4a55c27e31f9 100644 --- a/crates/re_space_view/src/visual_time_range.rs +++ b/crates/re_space_view/src/visual_time_range.rs @@ -8,7 +8,7 @@ //! to reduce the amount of changes in code that is likely to be refactored soon anyways. use re_log_types::TimeRange; -use re_query2::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; use re_types::blueprint::{ components::VisibleTimeRange, datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}, diff --git a/crates/re_space_view_dataframe/Cargo.toml b/crates/re_space_view_dataframe/Cargo.toml index daa865ee5b44..aab59723a55b 100644 --- a/crates/re_space_view_dataframe/Cargo.toml +++ b/crates/re_space_view_dataframe/Cargo.toml @@ -23,7 +23,7 @@ re_data_store.workspace = true re_data_ui.workspace = true re_entity_db.workspace = true re_log_types.workspace = true -re_query2.workspace = true +re_query.workspace = true re_renderer.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_space_view_spatial/Cargo.toml b/crates/re_space_view_spatial/Cargo.toml index 99d793f70c5f..57aa3d632a16 100644 --- a/crates/re_space_view_spatial/Cargo.toml +++ b/crates/re_space_view_spatial/Cargo.toml @@ -26,7 +26,7 @@ re_error.workspace = true re_format.workspace = true re_log_types.workspace = true re_log.workspace = true -re_query2.workspace = true +re_query.workspace = true re_renderer = { workspace = true, features = [ "import-gltf", "import-obj", diff --git a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs index 7f16b7516d3f..ec00b93d87c1 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query2::range_zip_1x6; +use re_query::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows2D, diff --git a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs index 465ad511cda1..d82e6f86b883 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query2::range_zip_1x6; +use re_query::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows3D, diff --git a/crates/re_space_view_spatial/src/visualizers/assets3d.rs b/crates/re_space_view_spatial/src/visualizers/assets3d.rs index 195f03785d69..9ac4c27c3b13 100644 --- a/crates/re_space_view_spatial/src/visualizers/assets3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/assets3d.rs @@ -1,6 +1,6 @@ use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query2::range_zip_1x2; +use re_query::range_zip_1x2; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Asset3D, diff --git a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs index 442b1007a43d..f03073e31d8f 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query2::range_zip_1x6; +use re_query::range_zip_1x6; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes2D, diff --git a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs index e4f1a552cbf3..894c318d2bb2 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query2::range_zip_1x7; +use re_query::range_zip_1x7; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes3D, diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 6db63aba7a39..d4edecab423c 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -2,7 +2,7 @@ use itertools::Either; use re_data_store::{LatestAtQuery, RangeQuery}; use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::{EntityPath, TimeInt, Timeline}; -use re_query2::{CachedResults, ExtraQueryHistory}; +use re_query::{CachedResults, ExtraQueryHistory}; use re_renderer::DepthOffset; use re_space_view::query_visual_history; use re_types::Archetype; diff --git a/crates/re_space_view_spatial/src/visualizers/images.rs b/crates/re_space_view_spatial/src/visualizers/images.rs index c638b3d03996..a26468b15fa7 100644 --- a/crates/re_space_view_spatial/src/visualizers/images.rs +++ b/crates/re_space_view_spatial/src/visualizers/images.rs @@ -6,7 +6,7 @@ use nohash_hasher::IntSet; use re_entity_db::{EntityPath, EntityProperties}; use re_log_types::{EntityPathHash, RowId, TimeInt}; -use re_query2::range_zip_1x2; +use re_query::range_zip_1x2; use re_renderer::{ renderer::{DepthCloud, DepthClouds, RectangleOptions, TexturedRect}, Colormap, diff --git a/crates/re_space_view_spatial/src/visualizers/lines2d.rs b/crates/re_space_view_spatial/src/visualizers/lines2d.rs index 2e86c40a1c13..24968114f67d 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query2::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::LineStrips2D, diff --git a/crates/re_space_view_spatial/src/visualizers/lines3d.rs b/crates/re_space_view_spatial/src/visualizers/lines3d.rs index 6be3cc460879..abbaded57525 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query2::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::PickingLayerInstanceId; use re_types::{ archetypes::LineStrips3D, diff --git a/crates/re_space_view_spatial/src/visualizers/meshes.rs b/crates/re_space_view_spatial/src/visualizers/meshes.rs index 651352f0efc7..55b8f0fc3bec 100644 --- a/crates/re_space_view_spatial/src/visualizers/meshes.rs +++ b/crates/re_space_view_spatial/src/visualizers/meshes.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query2::range_zip_1x7; +use re_query::range_zip_1x7; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Mesh3D, diff --git a/crates/re_space_view_spatial/src/visualizers/points2d.rs b/crates/re_space_view_spatial/src/visualizers/points2d.rs index efc82d15b3c8..b25d3a4b1041 100644 --- a/crates/re_space_view_spatial/src/visualizers/points2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points2d.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; -use re_query2::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points2D, diff --git a/crates/re_space_view_spatial/src/visualizers/points3d.rs b/crates/re_space_view_spatial/src/visualizers/points3d.rs index a4d1f5376676..252e9fbe6a6c 100644 --- a/crates/re_space_view_spatial/src/visualizers/points3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points3d.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; -use re_query2::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points3D, diff --git a/crates/re_space_view_spatial/src/visualizers/results_ext.rs b/crates/re_space_view_spatial/src/visualizers/results_ext.rs index 7481f173e800..c0f64548178d 100644 --- a/crates/re_space_view_spatial/src/visualizers/results_ext.rs +++ b/crates/re_space_view_spatial/src/visualizers/results_ext.rs @@ -1,4 +1,4 @@ -use re_query2::{ +use re_query::{ CachedLatestAtResults, CachedRangeData, CachedRangeResults, CachedResults, PromiseResolver, PromiseResult, }; @@ -14,19 +14,19 @@ pub trait CachedRangeResultsExt { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>>; + ) -> Option>>; fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query2::Result>; + ) -> re_query::Result>; } impl CachedRangeResultsExt for CachedResults { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { match self { CachedResults::LatestAt(_, results) => results.get_dense(resolver), CachedResults::Range(_, results) => results.get_dense(resolver), @@ -36,7 +36,7 @@ impl CachedRangeResultsExt for CachedResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query2::Result> { + ) -> re_query::Result> { match self { CachedResults::LatestAt(_, results) => results.get_or_empty_dense(resolver), CachedResults::Range(_, results) => results.get_or_empty_dense(resolver), @@ -49,20 +49,20 @@ impl CachedRangeResultsExt for CachedRangeResults { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?.to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { PromiseResult::Error(err) => { - return Some(Err(re_query2::QueryError::Other(err.into()))) + return Some(Err(re_query::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Error(err) => { - return Some(Err(re_query2::QueryError::Other(err.into()))) + return Some(Err(re_query::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -74,17 +74,17 @@ impl CachedRangeResultsExt for CachedRangeResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query2::Result> { + ) -> re_query::Result> { let results = self.get_or_empty(C::name()).to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { - PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -97,7 +97,7 @@ impl CachedRangeResultsExt for CachedLatestAtResults { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?; let data = CachedRangeData::from_latest_at(resolver, results); @@ -105,13 +105,13 @@ impl CachedRangeResultsExt for CachedLatestAtResults { let (front_status, back_status) = data.status(); match front_status { PromiseResult::Error(err) => { - return Some(Err(re_query2::QueryError::Other(err.into()))) + return Some(Err(re_query::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Error(err) => { - return Some(Err(re_query2::QueryError::Other(err.into()))) + return Some(Err(re_query::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -123,18 +123,18 @@ impl CachedRangeResultsExt for CachedLatestAtResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query2::Result> { + ) -> re_query::Result> { let results = self.get_or_empty(C::name()); let data = CachedRangeData::from_latest_at(resolver, results); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); match front_status { - PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_tensor/src/visualizer_system.rs b/crates/re_space_view_tensor/src/visualizer_system.rs index 7c4e4ec1faf6..a40414c63458 100644 --- a/crates/re_space_view_tensor/src/visualizer_system.rs +++ b/crates/re_space_view_tensor/src/visualizer_system.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query2::CachedLatestAtMonoResult, EntityPath}; +use re_entity_db::{external::re_query::CachedLatestAtMonoResult, EntityPath}; use re_log_types::RowId; use re_types::{archetypes::Tensor, components::TensorData, tensor_data::DecodedTensor}; use re_viewer_context::{ diff --git a/crates/re_space_view_text_document/src/visualizer_system.rs b/crates/re_space_view_text_document/src/visualizer_system.rs index 01eb0207789a..057dc85b1aee 100644 --- a/crates/re_space_view_text_document/src/visualizer_system.rs +++ b/crates/re_space_view_text_document/src/visualizer_system.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_space_view::external::re_query2::PromiseResult; +use re_space_view::external::re_query::PromiseResult; use re_types::{archetypes::TextDocument, components}; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, diff --git a/crates/re_space_view_text_log/Cargo.toml b/crates/re_space_view_text_log/Cargo.toml index 7faaa5d68cf0..0d277c329970 100644 --- a/crates/re_space_view_text_log/Cargo.toml +++ b/crates/re_space_view_text_log/Cargo.toml @@ -24,7 +24,7 @@ re_data_ui.workspace = true re_entity_db.workspace = true re_log_types.workspace = true re_log.workspace = true -re_query2.workspace = true +re_query.workspace = true re_renderer.workspace = true re_tracing.workspace = true re_types.workspace = true diff --git a/crates/re_space_view_text_log/src/visualizer_system.rs b/crates/re_space_view_text_log/src/visualizer_system.rs index ade23fb25dbc..74d6a62bc76c 100644 --- a/crates/re_space_view_text_log/src/visualizer_system.rs +++ b/crates/re_space_view_text_log/src/visualizer_system.rs @@ -1,7 +1,7 @@ use re_data_store::TimeRange; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query2::{clamped_zip_1x2, range_zip_1x2, CachedRangeData, PromiseResult}; +use re_query::{clamped_zip_1x2, range_zip_1x2, CachedRangeData, PromiseResult}; use re_types::{ archetypes::TextLog, components::{Color, Text, TextLogLevel}, @@ -129,16 +129,16 @@ impl VisualizerSystem for TextLogSystem { #[inline] fn check_range<'a, C: Component>( results: &'a CachedRangeData<'a, C>, -) -> re_query2::Result<()> { +) -> re_query::Result<()> { let (front_status, back_status) = results.status(); match front_status { PromiseResult::Pending => return Ok(()), - PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Pending => return Ok(()), - PromiseResult::Error(err) => return Err(re_query2::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_time_series/Cargo.toml b/crates/re_space_view_time_series/Cargo.toml index 2b031765e7b8..bcbfc845c815 100644 --- a/crates/re_space_view_time_series/Cargo.toml +++ b/crates/re_space_view_time_series/Cargo.toml @@ -23,7 +23,7 @@ re_data_store.workspace = true re_format.workspace = true re_log.workspace = true re_log_types.workspace = true -re_query2.workspace = true +re_query.workspace = true re_renderer.workspace = true re_space_view.workspace = true re_tracing.workspace = true diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 91940b9c0f2d..3ed39dbb062c 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -1,5 +1,5 @@ use itertools::Itertools as _; -use re_query2::{PromiseResult, QueryError}; +use re_query::{PromiseResult, QueryError}; use re_types::archetypes; use re_types::{ archetypes::SeriesLine, @@ -259,7 +259,7 @@ fn load_series( .map(|index| (index, ())); let all_frames = - re_query2::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) + re_query::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) .enumerate(); for (i, (_index, _scalars, colors)) in all_frames { @@ -296,7 +296,7 @@ fn load_series( .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query2::range_zip_1x1( + let all_frames = re_query::range_zip_1x1( all_scalars_indexed, all_stroke_widths.range_indexed(), ) diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index 2625f52dd368..6bfeca20cd0e 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -1,6 +1,6 @@ use itertools::Itertools as _; -use re_query2::{PromiseResult, QueryError}; +use re_query::{PromiseResult, QueryError}; use re_types::{ archetypes::{self, SeriesPoint}, components::{Color, MarkerShape, MarkerSize, Name, Scalar}, @@ -217,7 +217,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query2::range_zip_1x1( + let all_frames = re_query::range_zip_1x1( all_scalars_indexed, all_colors.range_indexed(), ) @@ -257,7 +257,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query2::range_zip_1x1( + let all_frames = re_query::range_zip_1x1( all_scalars_indexed, all_marker_sizes.range_indexed(), ) @@ -289,7 +289,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query2::range_zip_1x1( + let all_frames = re_query::range_zip_1x1( all_scalars_indexed, all_marker_shapes.range_indexed(), ) diff --git a/crates/re_types_builder/src/codegen/rust/to_archetype.rs b/crates/re_types_builder/src/codegen/rust/to_archetype.rs index 5f74b89901c6..2aa251977910 100644 --- a/crates/re_types_builder/src/codegen/rust/to_archetype.rs +++ b/crates/re_types_builder/src/codegen/rust/to_archetype.rs @@ -1,4 +1,4 @@ -//! Generates code in `re_query2` so that cached results can easily be converted to +//! Generates code in `re_query` so that cached results can easily be converted to //! ready-to-use archetypes. //! //! That code needs to be generated directly in the caching crates as it needs access to the cached @@ -35,7 +35,7 @@ fn generate_mod( files_to_write: &mut BTreeMap, ) { let generated_path = - Utf8PathBuf::from("crates/re_query2/src/latest_at/to_archetype/mod.rs"); + Utf8PathBuf::from("crates/re_query/src/latest_at/to_archetype/mod.rs"); let mut code = String::new(); code.push_str(&format!("// {}\n\n", crate::codegen::autogen_warning!())); @@ -62,12 +62,12 @@ fn generate_impls( objects: &Objects, files_to_write: &mut BTreeMap, ) { - let generated_path = Utf8PathBuf::from("crates/re_query2/src/latest_at/to_archetype"); + let generated_path = Utf8PathBuf::from("crates/re_query/src/latest_at/to_archetype"); let quoted_imports = quote! { use std::sync::Arc; - use re_query2::{PromiseResolver, PromiseResult}; + use re_query::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use crate::CachedLatestAtResults; diff --git a/crates/re_viewer/Cargo.toml b/crates/re_viewer/Cargo.toml index 6cfdac38b458..3db7e4dcebef 100644 --- a/crates/re_viewer/Cargo.toml +++ b/crates/re_viewer/Cargo.toml @@ -53,7 +53,7 @@ re_log_encoding = { workspace = true, features = [ ] } re_log_types.workspace = true re_memory.workspace = true -re_query2.workspace = true +re_query.workspace = true re_renderer = { workspace = true, default-features = false } re_smart_channel.workspace = true re_space_view.workspace = true diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs index 1df586ea3d14..610a26cc7074 100644 --- a/crates/re_viewer/src/lib.rs +++ b/crates/re_viewer/src/lib.rs @@ -34,7 +34,7 @@ pub mod external { pub use {eframe, egui}; pub use { re_data_store, re_data_store::external::*, re_entity_db, re_log, re_log_types, re_memory, - re_query2, re_renderer, re_types, re_ui, re_viewer_context, + re_query, re_renderer, re_types, re_ui, re_viewer_context, re_viewer_context::external::*, re_viewport, re_viewport::external::*, }; } diff --git a/crates/re_viewer/src/ui/memory_panel.rs b/crates/re_viewer/src/ui/memory_panel.rs index c252eda89fe9..e7a434e77cb0 100644 --- a/crates/re_viewer/src/ui/memory_panel.rs +++ b/crates/re_viewer/src/ui/memory_panel.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use re_data_store::{DataStoreConfig, DataStoreRowStats, DataStoreStats}; use re_format::{format_bytes, format_uint}; use re_memory::{util::sec_since_start, MemoryHistory, MemoryLimit, MemoryUse}; -use re_query2::{CachedComponentStats, CachesStats}; +use re_query::{CachedComponentStats, CachesStats}; use re_renderer::WgpuResourcePoolStatistics; use re_viewer_context::store_hub::StoreHubStats; diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 7be7e86d1dcb..f90f05f6eb63 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -24,7 +24,7 @@ re_data_store.workspace = true re_entity_db = { workspace = true, features = ["serde"] } re_log_types.workspace = true re_log.workspace = true -re_query2.workspace = true +re_query.workspace = true re_renderer.workspace = true re_smart_channel.workspace = true re_string_interner.workspace = true diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index b98255c1874c..80eb3008caa2 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use re_data_store::LatestAtQuery; use re_entity_db::{ - external::re_query2::CachedLatestAtComponentResults, EntityDb, EntityPath, + external::re_query::CachedLatestAtComponentResults, EntityDb, EntityPath, }; use re_log_types::DataCell; use re_types::{components::InstanceKey, ComponentName, Loggable as _}; diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index 3a78f8482d08..3c07a9f91b8c 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -199,7 +199,7 @@ pub fn resolve_mono_instance_path( [component], ); if let Some(results) = results.get(component) { - if let re_query2::PromiseResult::Ready(cell) = + if let re_query::PromiseResult::Ready(cell) = results.resolved(entity_db.resolver()) { if cell.num_instances() > 1 { diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index ef02ea868ba3..a8413981515f 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -76,7 +76,7 @@ pub use clipboard::Clipboard; pub mod external { pub use nohash_hasher; - pub use {re_data_store, re_entity_db, re_log_types, re_query2, re_ui}; + pub use {re_data_store, re_entity_db, re_log_types, re_query, re_ui}; } // --------------------------------------------------------------------------- diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index a80e16ba7539..b4da1ba5f82b 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -46,7 +46,7 @@ pub enum SpaceViewSystemExecutionError { VisualizerSystemNotFound(&'static str), #[error(transparent)] - QueryError(#[from] re_query2::QueryError), + QueryError(#[from] re_query::QueryError), #[error(transparent)] DeserializationError(#[from] re_types::DeserializationError), diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index 871c3d79b8d9..0160a1a14915 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -7,7 +7,7 @@ use re_data_store::StoreGeneration; use re_data_store::{DataStoreConfig, DataStoreStats}; use re_entity_db::{EntityDb, StoreBundle}; use re_log_types::{ApplicationId, StoreId, StoreKind}; -use re_query2::CachesStats; +use re_query::CachesStats; use crate::StoreContext; diff --git a/crates/re_viewport/src/container.rs b/crates/re_viewport/src/container.rs index 6a9c29da7a8e..15a2f3b83011 100644 --- a/crates/re_viewport/src/container.rs +++ b/crates/re_viewport/src/container.rs @@ -2,7 +2,7 @@ use ahash::HashMap; use egui_tiles::TileId; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query2::PromiseResult, EntityDb}; +use re_entity_db::{external::re_query::PromiseResult, EntityDb}; use re_log::ResultExt; use re_log_types::{DataRow, EntityPath, RowId}; use re_types::blueprint::components::Visible; diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index 2a32a6799eba..e608e63a6805 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -7,7 +7,7 @@ use nohash_hasher::IntSet; use smallvec::SmallVec; use re_data_store::LatestAtQuery; -use re_entity_db::external::re_query2::PromiseResult; +use re_entity_db::external::re_query::PromiseResult; use re_entity_db::EntityPath; use re_space_view::SpaceViewBlueprint; use re_types::blueprint::components::ViewerRecommendationHash; diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml index 32d7f1bd44a0..0b773c3de1ca 100644 --- a/examples/rust/custom_space_view/Cargo.toml +++ b/examples/rust/custom_space_view/Cargo.toml @@ -14,7 +14,7 @@ analytics = ["re_crash_handler/analytics", "re_viewer/analytics"] [dependencies] re_crash_handler = { path = "../../../crates/re_crash_handler" } -re_query2 = { path = "../../../crates/re_query2" } +re_query = { path = "../../../crates/re_query" } re_viewer = { path = "../../../crates/re_viewer", default-features = false } # We need re_sdk_comms to receive log events from and SDK: diff --git a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs index 25cd1ea0a939..acb442037850 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs @@ -1,7 +1,7 @@ use re_viewer::external::{ egui, re_log_types::EntityPath, - re_query2, re_renderer, + re_query, re_renderer, re_types::{ self, components::{Color, InstanceKey}, @@ -38,13 +38,13 @@ impl re_types::Archetype for ColorArchetype { } } -impl re_query2::ToArchetype for re_query2::CachedLatestAtResults { +impl re_query::ToArchetype for re_query::CachedLatestAtResults { #[inline] fn to_archetype( &self, - _resolver: &re_query2::PromiseResolver, - ) -> re_query2::PromiseResult> { - re_query2::PromiseResult::Ready(Ok(ColorArchetype)) + _resolver: &re_query::PromiseResolver, + ) -> re_query::PromiseResult> { + re_query::PromiseResult::Ready(Ok(ColorArchetype)) } } diff --git a/scripts/lint.py b/scripts/lint.py index 51cf334d17db..60584707c615 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -980,7 +980,7 @@ def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: """Make sure ARCHITECTURE.md talks about every single crate we have.""" # These crates will replace existing ones and won't ever be published as-is. - tmp_crates = ["re_query2"] + tmp_crates = ["re_query"] crates_dir = Path("crates") architecture_md_file = Path("ARCHITECTURE.md") From d73d6558f7f1ae633ea20ce4e8f4f9877661b8a0 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 24 Apr 2024 13:01:34 +0200 Subject: [PATCH 4/9] codegen --- crates/re_data_ui/src/component.rs | 4 +--- crates/re_query/src/latest_at/query.rs | 3 +-- .../latest_at/to_archetype/annotation_context.rs | 3 +-- .../src/latest_at/to_archetype/arrows2d.rs | 3 +-- .../src/latest_at/to_archetype/arrows3d.rs | 3 +-- .../src/latest_at/to_archetype/asset3d.rs | 3 +-- .../src/latest_at/to_archetype/bar_chart.rs | 3 +-- .../src/latest_at/to_archetype/boxes2d.rs | 3 +-- .../src/latest_at/to_archetype/boxes3d.rs | 3 +-- .../re_query/src/latest_at/to_archetype/clear.rs | 3 +-- .../to_archetype/container_blueprint.rs | 3 +-- .../src/latest_at/to_archetype/depth_image.rs | 3 +-- .../latest_at/to_archetype/disconnected_space.rs | 3 +-- .../re_query/src/latest_at/to_archetype/image.rs | 3 +-- .../src/latest_at/to_archetype/line_strips2d.rs | 3 +-- .../src/latest_at/to_archetype/line_strips3d.rs | 3 +-- .../src/latest_at/to_archetype/mesh3d.rs | 3 +-- .../latest_at/to_archetype/panel_blueprint.rs | 3 +-- .../src/latest_at/to_archetype/pinhole.rs | 3 +-- .../src/latest_at/to_archetype/plot_legend.rs | 3 +-- .../src/latest_at/to_archetype/points2d.rs | 3 +-- .../src/latest_at/to_archetype/points3d.rs | 3 +-- .../src/latest_at/to_archetype/scalar.rs | 3 +-- .../src/latest_at/to_archetype/scalar_axis.rs | 3 +-- .../latest_at/to_archetype/segmentation_image.rs | 3 +-- .../src/latest_at/to_archetype/series_line.rs | 3 +-- .../src/latest_at/to_archetype/series_point.rs | 3 +-- .../to_archetype/space_view_blueprint.rs | 3 +-- .../to_archetype/space_view_contents.rs | 3 +-- .../src/latest_at/to_archetype/tensor.rs | 3 +-- .../src/latest_at/to_archetype/text_document.rs | 3 +-- .../src/latest_at/to_archetype/text_log.rs | 3 +-- .../src/latest_at/to_archetype/transform3d.rs | 3 +-- .../latest_at/to_archetype/view_coordinates.rs | 3 +-- .../latest_at/to_archetype/viewport_blueprint.rs | 3 +-- .../src/visualizers/results_ext.rs | 16 ++++------------ .../src/visualizer_system.rs | 4 +--- .../src/line_visualizer_system.rs | 8 +++----- .../src/codegen/rust/to_archetype.rs | 6 ++---- crates/re_viewer/src/lib.rs | 4 ++-- .../src/component_ui_registry.rs | 4 +--- crates/re_viewer_context/src/item.rs | 3 +-- 42 files changed, 49 insertions(+), 102 deletions(-) diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index dc3c9a66ad4d..0d89e689791f 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -2,9 +2,7 @@ use std::sync::Arc; use egui::NumExt; -use re_entity_db::{ - external::re_query::CachedLatestAtComponentResults, EntityPath, InstancePath, -}; +use re_entity_db::{external::re_query::CachedLatestAtComponentResults, EntityPath, InstancePath}; use re_types::ComponentName; use re_ui::SyntaxHighlighting as _; use re_viewer_context::{UiVerbosity, ViewerContext}; diff --git a/crates/re_query/src/latest_at/query.rs b/crates/re_query/src/latest_at/query.rs index 825830e9a731..972e26c3c054 100644 --- a/crates/re_query/src/latest_at/query.rs +++ b/crates/re_query/src/latest_at/query.rs @@ -7,11 +7,10 @@ use parking_lot::RwLock; use re_data_store::{DataStore, LatestAtQuery, TimeInt}; use re_log_types::EntityPath; -use re_query2::Promise; use re_types_core::ComponentName; use re_types_core::SizeBytes; -use crate::{CacheKey, CachedLatestAtComponentResults, CachedLatestAtResults, Caches}; +use crate::{CacheKey, CachedLatestAtComponentResults, CachedLatestAtResults, Caches, Promise}; // --- diff --git a/crates/re_query/src/latest_at/to_archetype/annotation_context.rs b/crates/re_query/src/latest_at/to_archetype/annotation_context.rs index 32c55996d1d4..bfaaeefe469d 100644 --- a/crates/re_query/src/latest_at/to_archetype/annotation_context.rs +++ b/crates/re_query/src/latest_at/to_archetype/annotation_context.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/arrows2d.rs b/crates/re_query/src/latest_at/to_archetype/arrows2d.rs index 04183db62d79..ee459578a185 100644 --- a/crates/re_query/src/latest_at/to_archetype/arrows2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/arrows2d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/arrows3d.rs b/crates/re_query/src/latest_at/to_archetype/arrows3d.rs index 06436d914c7a..b29e12c981e0 100644 --- a/crates/re_query/src/latest_at/to_archetype/arrows3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/arrows3d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/asset3d.rs b/crates/re_query/src/latest_at/to_archetype/asset3d.rs index a1ad89a64e70..5c99a7642c34 100644 --- a/crates/re_query/src/latest_at/to_archetype/asset3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/asset3d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/bar_chart.rs b/crates/re_query/src/latest_at/to_archetype/bar_chart.rs index ae974df725af..27573bd97b14 100644 --- a/crates/re_query/src/latest_at/to_archetype/bar_chart.rs +++ b/crates/re_query/src/latest_at/to_archetype/bar_chart.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/boxes2d.rs b/crates/re_query/src/latest_at/to_archetype/boxes2d.rs index 2a41e9b3896e..af0f54ae5c52 100644 --- a/crates/re_query/src/latest_at/to_archetype/boxes2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/boxes2d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/boxes3d.rs b/crates/re_query/src/latest_at/to_archetype/boxes3d.rs index 4aff333508f6..430a87d62f9d 100644 --- a/crates/re_query/src/latest_at/to_archetype/boxes3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/boxes3d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/clear.rs b/crates/re_query/src/latest_at/to_archetype/clear.rs index c3cea969637b..584e074f006e 100644 --- a/crates/re_query/src/latest_at/to_archetype/clear.rs +++ b/crates/re_query/src/latest_at/to_archetype/clear.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs index 03a0757bf605..04b69f9c9f44 100644 --- a/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/depth_image.rs b/crates/re_query/src/latest_at/to_archetype/depth_image.rs index c40adca04815..c05a7be56ab5 100644 --- a/crates/re_query/src/latest_at/to_archetype/depth_image.rs +++ b/crates/re_query/src/latest_at/to_archetype/depth_image.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs b/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs index 8f497f463645..98df2990993a 100644 --- a/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs +++ b/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/image.rs b/crates/re_query/src/latest_at/to_archetype/image.rs index c051ca501069..38d80e36dd9c 100644 --- a/crates/re_query/src/latest_at/to_archetype/image.rs +++ b/crates/re_query/src/latest_at/to_archetype/image.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs b/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs index d0d8c607294e..9d32f0ebd842 100644 --- a/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs b/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs index 1ac3c7629104..5493bbcd3e86 100644 --- a/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/mesh3d.rs b/crates/re_query/src/latest_at/to_archetype/mesh3d.rs index d3b526d7da4c..b02a99d7070e 100644 --- a/crates/re_query/src/latest_at/to_archetype/mesh3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/mesh3d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs index f45127c1fe63..a12885d44432 100644 --- a/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/pinhole.rs b/crates/re_query/src/latest_at/to_archetype/pinhole.rs index 6ee4d70f6fbd..a9743c71de42 100644 --- a/crates/re_query/src/latest_at/to_archetype/pinhole.rs +++ b/crates/re_query/src/latest_at/to_archetype/pinhole.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/plot_legend.rs b/crates/re_query/src/latest_at/to_archetype/plot_legend.rs index 39afedddce07..84933b3a44af 100644 --- a/crates/re_query/src/latest_at/to_archetype/plot_legend.rs +++ b/crates/re_query/src/latest_at/to_archetype/plot_legend.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/points2d.rs b/crates/re_query/src/latest_at/to_archetype/points2d.rs index f3a232cad0a9..1731d09f374a 100644 --- a/crates/re_query/src/latest_at/to_archetype/points2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/points2d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/points3d.rs b/crates/re_query/src/latest_at/to_archetype/points3d.rs index 46e0378bb920..69b74f091d8d 100644 --- a/crates/re_query/src/latest_at/to_archetype/points3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/points3d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/scalar.rs b/crates/re_query/src/latest_at/to_archetype/scalar.rs index 5cf1e24252c2..28fbc2346ca8 100644 --- a/crates/re_query/src/latest_at/to_archetype/scalar.rs +++ b/crates/re_query/src/latest_at/to_archetype/scalar.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs b/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs index 435c508a6631..370ced7a0428 100644 --- a/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs +++ b/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs b/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs index 75dcc768d020..76f6ec92608e 100644 --- a/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs +++ b/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/series_line.rs b/crates/re_query/src/latest_at/to_archetype/series_line.rs index dea250769fd5..fcae51c2b6ac 100644 --- a/crates/re_query/src/latest_at/to_archetype/series_line.rs +++ b/crates/re_query/src/latest_at/to_archetype/series_line.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/series_point.rs b/crates/re_query/src/latest_at/to_archetype/series_point.rs index 29bf8d0cc8b8..6c2ece1ba1b6 100644 --- a/crates/re_query/src/latest_at/to_archetype/series_point.rs +++ b/crates/re_query/src/latest_at/to_archetype/series_point.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs index 85062f94fe02..80ce26e40829 100644 --- a/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs b/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs index f66bffb13718..af3c452143f3 100644 --- a/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs +++ b/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/tensor.rs b/crates/re_query/src/latest_at/to_archetype/tensor.rs index 2b6e569aac7e..3ef88a780e69 100644 --- a/crates/re_query/src/latest_at/to_archetype/tensor.rs +++ b/crates/re_query/src/latest_at/to_archetype/tensor.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/text_document.rs b/crates/re_query/src/latest_at/to_archetype/text_document.rs index f423045cb5e9..2a49a8a9d182 100644 --- a/crates/re_query/src/latest_at/to_archetype/text_document.rs +++ b/crates/re_query/src/latest_at/to_archetype/text_document.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/text_log.rs b/crates/re_query/src/latest_at/to_archetype/text_log.rs index 6e4cf9e7e6db..7eba912e76fd 100644 --- a/crates/re_query/src/latest_at/to_archetype/text_log.rs +++ b/crates/re_query/src/latest_at/to_archetype/text_log.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/transform3d.rs b/crates/re_query/src/latest_at/to_archetype/transform3d.rs index ecbe2a651c2f..1b85796396b7 100644 --- a/crates/re_query/src/latest_at/to_archetype/transform3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/transform3d.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs b/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs index d9ea4c9de036..d3a50ec80434 100644 --- a/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs +++ b/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs index f4ba63de006a..d9b23b7835b5 100644 --- a/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs @@ -5,8 +5,7 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use crate::{PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; diff --git a/crates/re_space_view_spatial/src/visualizers/results_ext.rs b/crates/re_space_view_spatial/src/visualizers/results_ext.rs index c0f64548178d..fb068cee4c8b 100644 --- a/crates/re_space_view_spatial/src/visualizers/results_ext.rs +++ b/crates/re_space_view_spatial/src/visualizers/results_ext.rs @@ -55,15 +55,11 @@ impl CachedRangeResultsExt for CachedRangeResults { // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { - PromiseResult::Error(err) => { - return Some(Err(re_query::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => { - return Some(Err(re_query::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -104,15 +100,11 @@ impl CachedRangeResultsExt for CachedLatestAtResults { // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); match front_status { - PromiseResult::Error(err) => { - return Some(Err(re_query::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => { - return Some(Err(re_query::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_text_log/src/visualizer_system.rs b/crates/re_space_view_text_log/src/visualizer_system.rs index 74d6a62bc76c..1940f5c314d0 100644 --- a/crates/re_space_view_text_log/src/visualizer_system.rs +++ b/crates/re_space_view_text_log/src/visualizer_system.rs @@ -127,9 +127,7 @@ impl VisualizerSystem for TextLogSystem { // TODO(#5607): what should happen if the promise is still pending? #[inline] -fn check_range<'a, C: Component>( - results: &'a CachedRangeData<'a, C>, -) -> re_query::Result<()> { +fn check_range<'a, C: Component>(results: &'a CachedRangeData<'a, C>) -> re_query::Result<()> { let (front_status, back_status) = results.status(); match front_status { PromiseResult::Pending => return Ok(()), diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 3ed39dbb062c..5525f0ec0db8 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -296,11 +296,9 @@ fn load_series( .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query::range_zip_1x1( - all_scalars_indexed, - all_stroke_widths.range_indexed(), - ) - .enumerate(); + let all_frames = + re_query::range_zip_1x1(all_scalars_indexed, all_stroke_widths.range_indexed()) + .enumerate(); for (i, (_index, _scalars, stroke_widths)) in all_frames { if let Some(stroke_width) = diff --git a/crates/re_types_builder/src/codegen/rust/to_archetype.rs b/crates/re_types_builder/src/codegen/rust/to_archetype.rs index 2aa251977910..d588f1aafe90 100644 --- a/crates/re_types_builder/src/codegen/rust/to_archetype.rs +++ b/crates/re_types_builder/src/codegen/rust/to_archetype.rs @@ -34,8 +34,7 @@ fn generate_mod( objects: &Objects, files_to_write: &mut BTreeMap, ) { - let generated_path = - Utf8PathBuf::from("crates/re_query/src/latest_at/to_archetype/mod.rs"); + let generated_path = Utf8PathBuf::from("crates/re_query/src/latest_at/to_archetype/mod.rs"); let mut code = String::new(); code.push_str(&format!("// {}\n\n", crate::codegen::autogen_warning!())); @@ -67,10 +66,9 @@ fn generate_impls( let quoted_imports = quote! { use std::sync::Arc; - use re_query::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; - use crate::CachedLatestAtResults; + use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; }; for obj in objects.ordered_objects(Some(ObjectKind::Archetype)) { diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs index 610a26cc7074..54344896001c 100644 --- a/crates/re_viewer/src/lib.rs +++ b/crates/re_viewer/src/lib.rs @@ -34,8 +34,8 @@ pub mod external { pub use {eframe, egui}; pub use { re_data_store, re_data_store::external::*, re_entity_db, re_log, re_log_types, re_memory, - re_query, re_renderer, re_types, re_ui, re_viewer_context, - re_viewer_context::external::*, re_viewport, re_viewport::external::*, + re_query, re_renderer, re_types, re_ui, re_viewer_context, re_viewer_context::external::*, + re_viewport, re_viewport::external::*, }; } diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index 80eb3008caa2..133d95d8ed01 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -1,9 +1,7 @@ use std::collections::BTreeMap; use re_data_store::LatestAtQuery; -use re_entity_db::{ - external::re_query::CachedLatestAtComponentResults, EntityDb, EntityPath, -}; +use re_entity_db::{external::re_query::CachedLatestAtComponentResults, EntityDb, EntityPath}; use re_log_types::DataCell; use re_types::{components::InstanceKey, ComponentName, Loggable as _}; diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index 3c07a9f91b8c..3fbdee8ca299 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -199,8 +199,7 @@ pub fn resolve_mono_instance_path( [component], ); if let Some(results) = results.get(component) { - if let re_query::PromiseResult::Ready(cell) = - results.resolved(entity_db.resolver()) + if let re_query::PromiseResult::Ready(cell) = results.resolved(entity_db.resolver()) { if cell.num_instances() > 1 { return instance.clone(); From dbdcd6255a445aba4209fab4eff42835cefc6d9f Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 24 Apr 2024 13:08:00 +0200 Subject: [PATCH 5/9] Cached prefix can go away now --- crates/re_data_ui/src/component.rs | 4 +- .../re_data_ui/src/component_ui_registry.rs | 4 +- crates/re_data_ui/src/editors.rs | 20 ++--- crates/re_entity_db/src/entity_db.rs | 8 +- crates/re_query/Cargo.toml | 2 +- crates/re_query/benches/latest_at.rs | 6 +- crates/re_query/examples/latest_at.rs | 11 ++- .../re_query/examples/latest_at_archetype.rs | 4 +- crates/re_query/examples/range.rs | 12 +-- crates/re_query/src/latest_at/helpers.rs | 20 ++--- crates/re_query/src/latest_at/mod.rs | 4 +- crates/re_query/src/latest_at/query.rs | 16 ++-- crates/re_query/src/latest_at/results.rs | 48 +++++----- .../to_archetype/annotation_context.rs | 4 +- .../src/latest_at/to_archetype/arrows2d.rs | 4 +- .../src/latest_at/to_archetype/arrows3d.rs | 4 +- .../src/latest_at/to_archetype/asset3d.rs | 4 +- .../src/latest_at/to_archetype/bar_chart.rs | 4 +- .../src/latest_at/to_archetype/boxes2d.rs | 4 +- .../src/latest_at/to_archetype/boxes3d.rs | 4 +- .../src/latest_at/to_archetype/clear.rs | 4 +- .../to_archetype/container_blueprint.rs | 4 +- .../src/latest_at/to_archetype/depth_image.rs | 4 +- .../to_archetype/disconnected_space.rs | 4 +- .../src/latest_at/to_archetype/image.rs | 4 +- .../latest_at/to_archetype/line_strips2d.rs | 4 +- .../latest_at/to_archetype/line_strips3d.rs | 4 +- .../src/latest_at/to_archetype/mesh3d.rs | 4 +- .../latest_at/to_archetype/panel_blueprint.rs | 4 +- .../src/latest_at/to_archetype/pinhole.rs | 4 +- .../src/latest_at/to_archetype/plot_legend.rs | 4 +- .../src/latest_at/to_archetype/points2d.rs | 4 +- .../src/latest_at/to_archetype/points3d.rs | 4 +- .../src/latest_at/to_archetype/scalar.rs | 4 +- .../src/latest_at/to_archetype/scalar_axis.rs | 4 +- .../to_archetype/segmentation_image.rs | 4 +- .../src/latest_at/to_archetype/series_line.rs | 4 +- .../latest_at/to_archetype/series_point.rs | 4 +- .../to_archetype/space_view_blueprint.rs | 6 +- .../to_archetype/space_view_contents.rs | 6 +- .../src/latest_at/to_archetype/tensor.rs | 4 +- .../latest_at/to_archetype/text_document.rs | 4 +- .../src/latest_at/to_archetype/text_log.rs | 4 +- .../src/latest_at/to_archetype/transform3d.rs | 4 +- .../to_archetype/view_coordinates.rs | 4 +- .../to_archetype/viewport_blueprint.rs | 4 +- crates/re_query/src/lib.rs | 22 +++-- crates/re_query/src/range/mod.rs | 3 +- crates/re_query/src/range/query.rs | 17 ++-- crates/re_query/src/range/results.rs | 88 +++++++++---------- crates/re_space_view/src/sub_archetypes.rs | 6 +- .../src/visualizers/arrows2d.rs | 2 +- .../src/visualizers/arrows3d.rs | 2 +- .../src/visualizers/assets3d.rs | 2 +- .../src/visualizers/boxes2d.rs | 2 +- .../src/visualizers/boxes3d.rs | 2 +- .../src/visualizers/entity_iterator.rs | 6 +- .../src/visualizers/images.rs | 2 +- .../src/visualizers/lines2d.rs | 2 +- .../src/visualizers/lines3d.rs | 2 +- .../src/visualizers/meshes.rs | 2 +- .../src/visualizers/mod.rs | 2 +- .../src/visualizers/points2d.rs | 2 +- .../src/visualizers/points3d.rs | 2 +- .../src/visualizers/results_ext.rs | 41 ++++----- .../src/visualizer_system.rs | 4 +- .../src/visualizer_system.rs | 4 +- .../src/codegen/rust/to_archetype.rs | 4 +- .../src/component_ui_registry.rs | 10 +-- .../color_coordinates_visualizer_system.rs | 2 +- 70 files changed, 252 insertions(+), 274 deletions(-) diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index 0d89e689791f..1fe709c7ea2b 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use egui::NumExt; -use re_entity_db::{external::re_query::CachedLatestAtComponentResults, EntityPath, InstancePath}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityPath, InstancePath}; use re_types::ComponentName; use re_ui::SyntaxHighlighting as _; use re_viewer_context::{UiVerbosity, ViewerContext}; @@ -14,7 +14,7 @@ use crate::item_ui; pub struct EntityLatestAtResults { pub entity_path: EntityPath, pub component_name: ComponentName, - pub results: Arc, + pub results: Arc, } impl DataUi for EntityLatestAtResults { diff --git a/crates/re_data_ui/src/component_ui_registry.rs b/crates/re_data_ui/src/component_ui_registry.rs index 89bdda270d9c..19c92ed3c541 100644 --- a/crates/re_data_ui/src/component_ui_registry.rs +++ b/crates/re_data_ui/src/component_ui_registry.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb}; use re_log_types::{external::arrow2, EntityPath}; use re_types::external::arrow2::array::Utf8Array; use re_viewer_context::{ComponentUiRegistry, UiVerbosity, ViewerContext}; @@ -62,7 +62,7 @@ fn fallback_component_ui( _query: &LatestAtQuery, db: &EntityDb, _entity_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { // TODO(#5607): what should happen if the promise is still pending? diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index e794d4b7814f..b22499105bce 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -2,7 +2,7 @@ use egui::NumExt as _; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb}; use re_log_types::EntityPath; use re_types::{ components::{ @@ -23,7 +23,7 @@ fn edit_color_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_color = component @@ -66,7 +66,7 @@ fn edit_text_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_text = component @@ -106,7 +106,7 @@ fn edit_name_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_text = component @@ -147,7 +147,7 @@ fn edit_scatter_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_scatter = component @@ -196,7 +196,7 @@ fn edit_radius_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_radius = component @@ -243,7 +243,7 @@ fn edit_marker_shape_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_marker = component @@ -329,7 +329,7 @@ fn edit_stroke_width_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_stroke_width = component @@ -376,7 +376,7 @@ fn edit_marker_size_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_marker_size = component @@ -425,7 +425,7 @@ fn register_editor<'a, C: Component + Loggable + 'static>( &EntityDb, &EntityPath, &EntityPath, - &CachedLatestAtComponentResults, + &LatestAtComponentResults, &re_types::components::InstanceKey, ), ) where diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index d82b9fb3279e..2355ce9dfe1b 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -209,7 +209,7 @@ impl EntityDb { query: &re_data_store::LatestAtQuery, ) -> PromiseResult> where - re_query::CachedLatestAtResults: re_query::ToArchetype, + re_query::LatestAtResults: re_query::ToArchetype, { let results = self.query_caches().latest_at( self.store(), @@ -240,7 +240,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { + ) -> Option> { self.query_caches().latest_at_component::( self.store(), self.resolver(), @@ -254,7 +254,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { + ) -> Option> { self.query_caches().latest_at_component_quiet::( self.store(), self.resolver(), @@ -268,7 +268,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option<(EntityPath, re_query::CachedLatestAtMonoResult)> { + ) -> Option<(EntityPath, re_query::LatestAtMonoResult)> { self.query_caches() .latest_at_component_at_closest_ancestor::( self.store(), diff --git a/crates/re_query/Cargo.toml b/crates/re_query/Cargo.toml index c62574cb88e7..9d223195d0b5 100644 --- a/crates/re_query/Cargo.toml +++ b/crates/re_query/Cargo.toml @@ -22,7 +22,7 @@ all-features = true [features] default = ["to_archetype"] -## Implements `ToArchetype` for all builtin archetypes on `CachedLatestAtResults`. +## Implements `ToArchetype` for all builtin archetypes on `LatestAtResults`. to_archetype = ["dep:re_types", "dep:re_types_blueprint"] ## Enable codegen helper binaries (generates ClampedZip & RangeZip implementations). diff --git a/crates/re_query/benches/latest_at.rs b/crates/re_query/benches/latest_at.rs index 0c76e42a3c88..feba6dde04f6 100644 --- a/crates/re_query/benches/latest_at.rs +++ b/crates/re_query/benches/latest_at.rs @@ -7,7 +7,7 @@ use itertools::Itertools; use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; use re_query::{clamped_zip_1x1, PromiseResolver}; -use re_query::{CachedLatestAtResults, Caches}; +use re_query::{Caches, LatestAtResults}; use re_types::{ archetypes::Points2D, components::{Color, InstanceKey, Position2D, Text}, @@ -289,7 +289,7 @@ fn query_and_visit_points( // TODO(jleibs): Add Radius once we have support for it in field_types for entity_path in paths { - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( store, &query, entity_path, @@ -340,7 +340,7 @@ fn query_and_visit_strings( let mut strings = Vec::with_capacity(NUM_STRINGS as _); for entity_path in paths { - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( store, &query, entity_path, diff --git a/crates/re_query/examples/latest_at.rs b/crates/re_query/examples/latest_at.rs index aab700222652..eb450f091cc2 100644 --- a/crates/re_query/examples/latest_at.rs +++ b/crates/re_query/examples/latest_at.rs @@ -5,8 +5,7 @@ use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; use re_types_core::{Archetype as _, Loggable as _}; use re_query::{ - clamped_zip_1x2, CachedLatestAtComponentResults, CachedLatestAtResults, PromiseResolver, - PromiseResult, + clamped_zip_1x2, LatestAtComponentResults, LatestAtResults, PromiseResolver, PromiseResult, }; // --- @@ -28,7 +27,7 @@ fn main() -> anyhow::Result<()> { // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( &store, &query, &entity_path.into(), @@ -41,9 +40,9 @@ fn main() -> anyhow::Result<()> { // * `get` returns an option // // At this point we still don't know whether they are cached or not. That's the next step. - let points: &CachedLatestAtComponentResults = results.get_required(MyPoint::name())?; - let colors: &CachedLatestAtComponentResults = results.get_or_empty(MyColor::name()); - let labels: &CachedLatestAtComponentResults = results.get_or_empty(MyLabel::name()); + let points: &LatestAtComponentResults = results.get_required(MyPoint::name())?; + let colors: &LatestAtComponentResults = results.get_or_empty(MyColor::name()); + let labels: &LatestAtComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. diff --git a/crates/re_query/examples/latest_at_archetype.rs b/crates/re_query/examples/latest_at_archetype.rs index 37766c6aa8aa..af3215fdc3bc 100644 --- a/crates/re_query/examples/latest_at_archetype.rs +++ b/crates/re_query/examples/latest_at_archetype.rs @@ -7,7 +7,7 @@ use re_types::{ }; use re_types_core::{Archetype as _, Loggable as _}; -use re_query::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; +use re_query::{clamped_zip_1x2, LatestAtResults, PromiseResolver, PromiseResult}; // --- @@ -28,7 +28,7 @@ fn main() -> anyhow::Result<()> { // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( &store, &query, &entity_path.into(), diff --git a/crates/re_query/examples/range.rs b/crates/re_query/examples/range.rs index c62ac2ee54b1..0defca92ed8a 100644 --- a/crates/re_query/examples/range.rs +++ b/crates/re_query/examples/range.rs @@ -5,8 +5,8 @@ use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline use re_types_core::{Archetype as _, Loggable as _}; use re_query::{ - clamped_zip_1x2, range_zip_1x2, CachedRangeComponentResults, CachedRangeResults, - PromiseResolver, PromiseResult, + clamped_zip_1x2, range_zip_1x2, PromiseResolver, PromiseResult, RangeComponentResults, + RangeResults, }; // --- @@ -28,7 +28,7 @@ fn main() -> anyhow::Result<()> { // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. - let results: CachedRangeResults = caches.range( + let results: RangeResults = caches.range( &store, &query, &entity_path.into(), @@ -41,9 +41,9 @@ fn main() -> anyhow::Result<()> { // * `get` returns an option // // At this point we still don't know whether they are cached or not. That's the next step. - let all_points: &CachedRangeComponentResults = results.get_required(MyPoint::name())?; - let all_colors: &CachedRangeComponentResults = results.get_or_empty(MyColor::name()); - let all_labels: &CachedRangeComponentResults = results.get_or_empty(MyLabel::name()); + let all_points: &RangeComponentResults = results.get_required(MyPoint::name())?; + let all_colors: &RangeComponentResults = results.get_or_empty(MyColor::name()); + let all_labels: &RangeComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. diff --git a/crates/re_query/src/latest_at/helpers.rs b/crates/re_query/src/latest_at/helpers.rs index a941fe7b56bd..d850bfc660de 100644 --- a/crates/re_query/src/latest_at/helpers.rs +++ b/crates/re_query/src/latest_at/helpers.rs @@ -3,11 +3,11 @@ use re_log_types::{EntityPath, RowId, TimeInt}; use re_types_core::Component; use re_types_core::{external::arrow2::array::Array, ComponentName}; -use crate::{CachedLatestAtComponentResults, Caches, PromiseResolver, PromiseResult}; +use crate::{Caches, LatestAtComponentResults, PromiseResolver, PromiseResult}; // --- -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { /// Returns the component data as a dense vector. /// /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. @@ -241,12 +241,12 @@ impl CachedLatestAtComponentResults { // --- #[derive(Clone)] -pub struct CachedLatestAtMonoResult { +pub struct LatestAtMonoResult { pub index: (TimeInt, RowId), pub value: C, } -impl CachedLatestAtMonoResult { +impl LatestAtMonoResult { #[inline] pub fn data_time(&self) -> TimeInt { self.index.0 @@ -258,7 +258,7 @@ impl CachedLatestAtMonoResult { } } -impl std::ops::Deref for CachedLatestAtMonoResult { +impl std::ops::Deref for LatestAtMonoResult { type Target = C; #[inline] @@ -287,7 +287,7 @@ impl Caches { entity_path: &EntityPath, query: &LatestAtQuery, level: re_log::Level, - ) -> Option> { + ) -> Option> { re_tracing::profile_function!(); let results = self.latest_at(store, query, entity_path, [C::name()]); @@ -303,7 +303,7 @@ impl Caches { ); None } - PromiseResult::Ready(data) if data.len() == 1 => Some(CachedLatestAtMonoResult { + PromiseResult::Ready(data) if data.len() == 1 => Some(LatestAtMonoResult { index, value: data[0].clone(), }), @@ -343,7 +343,7 @@ impl Caches { resolver: &PromiseResolver, entity_path: &EntityPath, query: &LatestAtQuery, - ) -> Option> { + ) -> Option> { self.latest_at_component_with_log_level( store, resolver, @@ -368,7 +368,7 @@ impl Caches { resolver: &PromiseResolver, entity_path: &EntityPath, query: &LatestAtQuery, - ) -> Option> { + ) -> Option> { self.latest_at_component_with_log_level( store, resolver, @@ -385,7 +385,7 @@ impl Caches { resolver: &PromiseResolver, entity_path: &EntityPath, query: &LatestAtQuery, - ) -> Option<(EntityPath, CachedLatestAtMonoResult)> { + ) -> Option<(EntityPath, LatestAtMonoResult)> { re_tracing::profile_function!(); let mut cur_entity_path = Some(entity_path.clone()); diff --git a/crates/re_query/src/latest_at/mod.rs b/crates/re_query/src/latest_at/mod.rs index 82fd889bce0b..04511f831260 100644 --- a/crates/re_query/src/latest_at/mod.rs +++ b/crates/re_query/src/latest_at/mod.rs @@ -5,6 +5,6 @@ mod results; #[cfg(feature = "to_archetype")] mod to_archetype; -pub use self::helpers::CachedLatestAtMonoResult; +pub use self::helpers::LatestAtMonoResult; pub use self::query::LatestAtCache; -pub use self::results::{CachedLatestAtComponentResults, CachedLatestAtResults}; +pub use self::results::{LatestAtComponentResults, LatestAtResults}; diff --git a/crates/re_query/src/latest_at/query.rs b/crates/re_query/src/latest_at/query.rs index 972e26c3c054..b4ca7cdfe059 100644 --- a/crates/re_query/src/latest_at/query.rs +++ b/crates/re_query/src/latest_at/query.rs @@ -10,14 +10,14 @@ use re_log_types::EntityPath; use re_types_core::ComponentName; use re_types_core::SizeBytes; -use crate::{CacheKey, CachedLatestAtComponentResults, CachedLatestAtResults, Caches, Promise}; +use crate::{CacheKey, Caches, LatestAtComponentResults, LatestAtResults, Promise}; // --- impl Caches { /// Queries for the given `component_names` using latest-at semantics. /// - /// See [`CachedLatestAtResults`] for more information about how to handle the results. + /// See [`LatestAtResults`] for more information about how to handle the results. /// /// This is a cached API -- data will be lazily cached upon access. pub fn latest_at( @@ -26,10 +26,10 @@ impl Caches { query: &LatestAtQuery, entity_path: &EntityPath, component_names: impl IntoIterator, - ) -> CachedLatestAtResults { + ) -> LatestAtResults { re_tracing::profile_function!(entity_path.to_string()); - let mut results = CachedLatestAtResults::default(); + let mut results = LatestAtResults::default(); for component_name in component_names { let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); @@ -64,7 +64,7 @@ pub struct LatestAtCache { /// if there is any data available for the resulting _data_ time in [`Self::per_data_time`]. // // NOTE: `Arc` so we can share buckets across query time & data time. - pub per_query_time: BTreeMap>, + pub per_query_time: BTreeMap>, /// Organized by _data_ time. /// @@ -72,7 +72,7 @@ pub struct LatestAtCache { /// can result in a data time of `T`. // // NOTE: `Arc` so we can share buckets across query time & data time. - pub per_data_time: BTreeMap>, + pub per_data_time: BTreeMap>, /// These timestamps have been invalidated asynchronously. /// @@ -195,7 +195,7 @@ impl LatestAtCache { query: &LatestAtQuery, entity_path: &EntityPath, component_name: ComponentName, - ) -> Option> { + ) -> Option> { re_tracing::profile_scope!("latest_at", format!("{query:?}")); let LatestAtCache { @@ -245,7 +245,7 @@ impl LatestAtCache { return None; }; - let bucket = Arc::new(CachedLatestAtComponentResults { + let bucket = Arc::new(LatestAtComponentResults { index: (data_time, row_id), promise: Some(Promise::new(cell)), cached_dense: Default::default(), diff --git a/crates/re_query/src/latest_at/results.rs b/crates/re_query/src/latest_at/results.rs index 44691217ac9d..a14ff7d2afb8 100644 --- a/crates/re_query/src/latest_at/results.rs +++ b/crates/re_query/src/latest_at/results.rs @@ -11,14 +11,14 @@ use crate::{ // --- -/// Cached results for a latest-at query. +/// results for a latest-at query. /// /// The data is both deserialized and resolved/converted. /// -/// Use [`CachedLatestAtResults::get`], [`CachedLatestAtResults::get_required`] and -/// [`CachedLatestAtResults::get_or_empty`] in order to access the results for each individual component. +/// Use [`LatestAtResults::get`], [`LatestAtResults::get_required`] and +/// [`LatestAtResults::get_or_empty`] in order to access the results for each individual component. #[derive(Debug)] -pub struct CachedLatestAtResults { +pub struct LatestAtResults { /// The compound index of this query result. /// /// A latest-at query is a compound operation that gathers data from many different rows. @@ -27,10 +27,10 @@ pub struct CachedLatestAtResults { pub compound_index: (TimeInt, RowId), /// Results for each individual component. - pub components: IntMap>, + pub components: IntMap>, } -impl Default for CachedLatestAtResults { +impl Default for LatestAtResults { #[inline] fn default() -> Self { Self { @@ -40,31 +40,31 @@ impl Default for CachedLatestAtResults { } } -impl CachedLatestAtResults { +impl LatestAtResults { #[inline] pub fn contains(&self, component_name: impl Into) -> bool { self.components.contains_key(&component_name.into()) } - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. #[inline] pub fn get( &self, component_name: impl Into, - ) -> Option<&CachedLatestAtComponentResults> { + ) -> Option<&LatestAtComponentResults> { self.components .get(&component_name.into()) .map(|arc| &**arc) } - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. /// /// Returns an error if the component is not present. #[inline] pub fn get_required( &self, component_name: impl Into, - ) -> crate::Result<&CachedLatestAtComponentResults> { + ) -> crate::Result<&LatestAtComponentResults> { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { Ok(component) @@ -73,32 +73,28 @@ impl CachedLatestAtResults { } } - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. /// /// Returns empty results if the component is not present. #[inline] pub fn get_or_empty( &self, component_name: impl Into, - ) -> &CachedLatestAtComponentResults { + ) -> &LatestAtComponentResults { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { component } else { - static EMPTY: CachedLatestAtComponentResults = CachedLatestAtComponentResults::empty(); + static EMPTY: LatestAtComponentResults = LatestAtComponentResults::empty(); &EMPTY } } } -impl CachedLatestAtResults { +impl LatestAtResults { #[doc(hidden)] #[inline] - pub fn add( - &mut self, - component_name: ComponentName, - cached: Arc, - ) { + pub fn add(&mut self, component_name: ComponentName, cached: Arc) { // NOTE: Since this is a compound API that actually emits multiple queries, the index of the // final result is the most recent index among all of its components, as defined by time // and row-id order. @@ -119,7 +115,7 @@ impl CachedLatestAtResults { // --- /// Lazily cached results for a particular component when using a cached latest-at query. -pub struct CachedLatestAtComponentResults { +pub struct LatestAtComponentResults { pub(crate) index: (TimeInt, RowId), // Option so we can have a constant default value for `Self`. @@ -129,7 +125,7 @@ pub struct CachedLatestAtComponentResults { pub(crate) cached_dense: OnceLock>, } -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { #[inline] pub const fn empty() -> Self { Self { @@ -170,7 +166,7 @@ impl CachedLatestAtComponentResults { } } -impl SizeBytes for CachedLatestAtComponentResults { +impl SizeBytes for LatestAtComponentResults { #[inline] fn heap_size_bytes(&self) -> u64 { let Self { @@ -187,7 +183,7 @@ impl SizeBytes for CachedLatestAtComponentResults { } } -impl std::fmt::Debug for CachedLatestAtComponentResults { +impl std::fmt::Debug for LatestAtComponentResults { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { index, @@ -204,7 +200,7 @@ impl std::fmt::Debug for CachedLatestAtComponentResults { } } -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { #[inline] pub fn index(&self) -> &(TimeInt, RowId) { &self.index @@ -257,7 +253,7 @@ impl CachedLatestAtComponentResults { } } -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { fn downcast_dense(&self, cell: &DataCell) -> crate::Result<&[C]> { // `OnceLock::get` is non-blocking -- this is a best-effort fast path in case the // data has already been computed. diff --git a/crates/re_query/src/latest_at/to_archetype/annotation_context.rs b/crates/re_query/src/latest_at/to_archetype/annotation_context.rs index bfaaeefe469d..8afa32ea8561 100644 --- a/crates/re_query/src/latest_at/to_archetype/annotation_context.rs +++ b/crates/re_query/src/latest_at/to_archetype/annotation_context.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/arrows2d.rs b/crates/re_query/src/latest_at/to_archetype/arrows2d.rs index ee459578a185..5adc4153fe65 100644 --- a/crates/re_query/src/latest_at/to_archetype/arrows2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/arrows2d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/arrows3d.rs b/crates/re_query/src/latest_at/to_archetype/arrows3d.rs index b29e12c981e0..fe4bd99f06c5 100644 --- a/crates/re_query/src/latest_at/to_archetype/arrows3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/arrows3d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/asset3d.rs b/crates/re_query/src/latest_at/to_archetype/asset3d.rs index 5c99a7642c34..03931257d1ce 100644 --- a/crates/re_query/src/latest_at/to_archetype/asset3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/asset3d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/bar_chart.rs b/crates/re_query/src/latest_at/to_archetype/bar_chart.rs index 27573bd97b14..7a71bf148d3d 100644 --- a/crates/re_query/src/latest_at/to_archetype/bar_chart.rs +++ b/crates/re_query/src/latest_at/to_archetype/bar_chart.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/boxes2d.rs b/crates/re_query/src/latest_at/to_archetype/boxes2d.rs index af0f54ae5c52..dd6aeb26070f 100644 --- a/crates/re_query/src/latest_at/to_archetype/boxes2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/boxes2d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/boxes3d.rs b/crates/re_query/src/latest_at/to_archetype/boxes3d.rs index 430a87d62f9d..c0790e887012 100644 --- a/crates/re_query/src/latest_at/to_archetype/boxes3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/boxes3d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/clear.rs b/crates/re_query/src/latest_at/to_archetype/clear.rs index 584e074f006e..6d4c8f01e4b3 100644 --- a/crates/re_query/src/latest_at/to_archetype/clear.rs +++ b/crates/re_query/src/latest_at/to_archetype/clear.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs index 04b69f9c9f44..d6db455e1e7f 100644 --- a/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs @@ -5,12 +5,12 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; impl crate::ToArchetype - for CachedLatestAtResults + for LatestAtResults { #[inline] fn to_archetype( diff --git a/crates/re_query/src/latest_at/to_archetype/depth_image.rs b/crates/re_query/src/latest_at/to_archetype/depth_image.rs index c05a7be56ab5..802da9f44971 100644 --- a/crates/re_query/src/latest_at/to_archetype/depth_image.rs +++ b/crates/re_query/src/latest_at/to_archetype/depth_image.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs b/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs index 98df2990993a..e409fcd63194 100644 --- a/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs +++ b/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/image.rs b/crates/re_query/src/latest_at/to_archetype/image.rs index 38d80e36dd9c..ddf966610409 100644 --- a/crates/re_query/src/latest_at/to_archetype/image.rs +++ b/crates/re_query/src/latest_at/to_archetype/image.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs b/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs index 9d32f0ebd842..b51624b9ab28 100644 --- a/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs b/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs index 5493bbcd3e86..a11a49c0eebd 100644 --- a/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/mesh3d.rs b/crates/re_query/src/latest_at/to_archetype/mesh3d.rs index b02a99d7070e..04c3b330042e 100644 --- a/crates/re_query/src/latest_at/to_archetype/mesh3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/mesh3d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs index a12885d44432..acf76c2788dd 100644 --- a/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs @@ -5,12 +5,12 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; impl crate::ToArchetype - for CachedLatestAtResults + for LatestAtResults { #[inline] fn to_archetype( diff --git a/crates/re_query/src/latest_at/to_archetype/pinhole.rs b/crates/re_query/src/latest_at/to_archetype/pinhole.rs index a9743c71de42..34419beb7435 100644 --- a/crates/re_query/src/latest_at/to_archetype/pinhole.rs +++ b/crates/re_query/src/latest_at/to_archetype/pinhole.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/plot_legend.rs b/crates/re_query/src/latest_at/to_archetype/plot_legend.rs index 84933b3a44af..b5d466095cc1 100644 --- a/crates/re_query/src/latest_at/to_archetype/plot_legend.rs +++ b/crates/re_query/src/latest_at/to_archetype/plot_legend.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/points2d.rs b/crates/re_query/src/latest_at/to_archetype/points2d.rs index 1731d09f374a..9fd2be9a01f1 100644 --- a/crates/re_query/src/latest_at/to_archetype/points2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/points2d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/points3d.rs b/crates/re_query/src/latest_at/to_archetype/points3d.rs index 69b74f091d8d..2525c7ca81bf 100644 --- a/crates/re_query/src/latest_at/to_archetype/points3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/points3d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/scalar.rs b/crates/re_query/src/latest_at/to_archetype/scalar.rs index 28fbc2346ca8..3f715f0bba97 100644 --- a/crates/re_query/src/latest_at/to_archetype/scalar.rs +++ b/crates/re_query/src/latest_at/to_archetype/scalar.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs b/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs index 370ced7a0428..67e59fff4a5e 100644 --- a/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs +++ b/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs b/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs index 76f6ec92608e..203ca4f697b3 100644 --- a/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs +++ b/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/series_line.rs b/crates/re_query/src/latest_at/to_archetype/series_line.rs index fcae51c2b6ac..88895798d555 100644 --- a/crates/re_query/src/latest_at/to_archetype/series_line.rs +++ b/crates/re_query/src/latest_at/to_archetype/series_line.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/series_point.rs b/crates/re_query/src/latest_at/to_archetype/series_point.rs index 6c2ece1ba1b6..273aca5ac53a 100644 --- a/crates/re_query/src/latest_at/to_archetype/series_point.rs +++ b/crates/re_query/src/latest_at/to_archetype/series_point.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs index 80ce26e40829..f4e94c1a4c16 100644 --- a/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs @@ -5,13 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype - for CachedLatestAtResults -{ +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs b/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs index af3c452143f3..b35439f90369 100644 --- a/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs +++ b/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs @@ -5,13 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype - for CachedLatestAtResults -{ +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/tensor.rs b/crates/re_query/src/latest_at/to_archetype/tensor.rs index 3ef88a780e69..2b72bef07906 100644 --- a/crates/re_query/src/latest_at/to_archetype/tensor.rs +++ b/crates/re_query/src/latest_at/to_archetype/tensor.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/text_document.rs b/crates/re_query/src/latest_at/to_archetype/text_document.rs index 2a49a8a9d182..9d4061fff7a9 100644 --- a/crates/re_query/src/latest_at/to_archetype/text_document.rs +++ b/crates/re_query/src/latest_at/to_archetype/text_document.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/text_log.rs b/crates/re_query/src/latest_at/to_archetype/text_log.rs index 7eba912e76fd..4cddf9829b23 100644 --- a/crates/re_query/src/latest_at/to_archetype/text_log.rs +++ b/crates/re_query/src/latest_at/to_archetype/text_log.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/transform3d.rs b/crates/re_query/src/latest_at/to_archetype/transform3d.rs index 1b85796396b7..7f7a1d96a383 100644 --- a/crates/re_query/src/latest_at/to_archetype/transform3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/transform3d.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs b/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs index d3a50ec80434..2abff463bb7f 100644 --- a/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs +++ b/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs @@ -5,11 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs index d9b23b7835b5..e5c19cca9fac 100644 --- a/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs @@ -5,12 +5,12 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; impl crate::ToArchetype - for CachedLatestAtResults + for LatestAtResults { #[inline] fn to_archetype( diff --git a/crates/re_query/src/lib.rs b/crates/re_query/src/lib.rs index 6113316f522e..d75b866986dd 100644 --- a/crates/re_query/src/lib.rs +++ b/crates/re_query/src/lib.rs @@ -15,16 +15,14 @@ pub use self::cache::{CacheKey, Caches}; pub use self::cache_stats::{CachedComponentStats, CachesStats}; pub use self::clamped_zip::*; pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; -pub use self::latest_at::{ - CachedLatestAtComponentResults, CachedLatestAtMonoResult, CachedLatestAtResults, -}; +pub use self::latest_at::{LatestAtComponentResults, LatestAtMonoResult, LatestAtResults}; pub use self::promise::{Promise, PromiseId, PromiseResolver, PromiseResult}; -pub use self::range::{CachedRangeComponentResults, CachedRangeData, CachedRangeResults}; +pub use self::range::{RangeComponentResults, RangeData, RangeResults}; pub use self::range_zip::*; pub use self::visible_history::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; pub(crate) use self::latest_at::LatestAtCache; -pub(crate) use self::range::{CachedRangeComponentResultsInner, RangeCache}; +pub(crate) use self::range::{RangeCache, RangeComponentResultsInner}; pub mod external { pub use paste; @@ -101,21 +99,21 @@ pub trait ToArchetype { use re_data_store::{LatestAtQuery, RangeQuery}; #[derive(Debug)] -pub enum CachedResults { - LatestAt(LatestAtQuery, CachedLatestAtResults), - Range(RangeQuery, CachedRangeResults), +pub enum Results { + LatestAt(LatestAtQuery, LatestAtResults), + Range(RangeQuery, RangeResults), } -impl From<(LatestAtQuery, CachedLatestAtResults)> for CachedResults { +impl From<(LatestAtQuery, LatestAtResults)> for Results { #[inline] - fn from((query, results): (LatestAtQuery, CachedLatestAtResults)) -> Self { + fn from((query, results): (LatestAtQuery, LatestAtResults)) -> Self { Self::LatestAt(query, results) } } -impl From<(RangeQuery, CachedRangeResults)> for CachedResults { +impl From<(RangeQuery, RangeResults)> for Results { #[inline] - fn from((query, results): (RangeQuery, CachedRangeResults)) -> Self { + fn from((query, results): (RangeQuery, RangeResults)) -> Self { Self::Range(query, results) } } diff --git a/crates/re_query/src/range/mod.rs b/crates/re_query/src/range/mod.rs index ffb93dd2f720..f11e2033ff8f 100644 --- a/crates/re_query/src/range/mod.rs +++ b/crates/re_query/src/range/mod.rs @@ -3,6 +3,5 @@ mod results; pub use self::query::RangeCache; pub use self::results::{ - CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeData, - CachedRangeResults, + RangeComponentResults, RangeComponentResultsInner, RangeData, RangeResults, }; diff --git a/crates/re_query/src/range/query.rs b/crates/re_query/src/range/query.rs index f04664b96c25..649aa7ef8700 100644 --- a/crates/re_query/src/range/query.rs +++ b/crates/re_query/src/range/query.rs @@ -8,8 +8,7 @@ use re_types_core::ComponentName; use re_types_core::SizeBytes; use crate::{ - CacheKey, CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeResults, - Caches, Promise, + CacheKey, Caches, Promise, RangeComponentResults, RangeComponentResultsInner, RangeResults, }; // --- @@ -17,7 +16,7 @@ use crate::{ impl Caches { /// Queries for the given `component_names` using range semantics. /// - /// See [`CachedRangeResults`] for more information about how to handle the results. + /// See [`RangeResults`] for more information about how to handle the results. /// /// This is a cached API -- data will be lazily cached upon access. pub fn range( @@ -26,10 +25,10 @@ impl Caches { query: &RangeQuery, entity_path: &EntityPath, component_names: impl IntoIterator, - ) -> CachedRangeResults { + ) -> RangeResults { re_tracing::profile_function!(entity_path.to_string()); - let mut results = CachedRangeResults::new(query.clone()); + let mut results = RangeResults::new(query.clone()); for component_name in component_names { let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); @@ -61,7 +60,7 @@ pub struct RangeCache { /// All temporal data, organized by _data_ time. /// /// Query time is irrelevant for range queries. - pub per_data_time: CachedRangeComponentResults, + pub per_data_time: RangeComponentResults, /// Everything greater than or equal to this timestamp has been asynchronously invalidated. /// @@ -78,7 +77,7 @@ impl RangeCache { pub fn new(cache_key: CacheKey) -> Self { Self { cache_key, - per_data_time: CachedRangeComponentResults::default(), + per_data_time: RangeComponentResults::default(), pending_invalidation: None, } } @@ -149,7 +148,7 @@ impl RangeCache { query: &RangeQuery, entity_path: &EntityPath, component_name: ComponentName, - ) -> CachedRangeComponentResults { + ) -> RangeComponentResults { re_tracing::profile_scope!("range", format!("{query:?}")); let RangeCache { @@ -232,7 +231,7 @@ impl RangeCache { // --- -impl CachedRangeComponentResultsInner { +impl RangeComponentResultsInner { /// How many _indices_ across this entire cache? #[inline] pub fn num_indices(&self) -> u64 { diff --git a/crates/re_query/src/range/results.rs b/crates/re_query/src/range/results.rs index 5f9bc83e6255..3c88d173abb2 100644 --- a/crates/re_query/src/range/results.rs +++ b/crates/re_query/src/range/results.rs @@ -13,25 +13,25 @@ use re_log_types::{RowId, TimeInt, TimeRange}; use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes}; use crate::{ - CachedLatestAtComponentResults, ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, + ErasedFlatVecDeque, FlatVecDeque, LatestAtComponentResults, Promise, PromiseResolver, PromiseResult, }; // --- -/// Cached results for a range query. +/// results for a range query. /// /// The data is both deserialized and resolved/converted. /// -/// Use [`CachedRangeResults::get`], [`CachedRangeResults::get_required`] and -/// [`CachedRangeResults::get_or_empty`] in order to access the results for each individual component. +/// Use [`RangeResults::get`], [`RangeResults::get_required`] and +/// [`RangeResults::get_or_empty`] in order to access the results for each individual component. #[derive(Debug)] -pub struct CachedRangeResults { +pub struct RangeResults { pub query: RangeQuery, - pub components: IntMap, + pub components: IntMap, } -impl CachedRangeResults { +impl RangeResults { #[inline] pub(crate) fn new(query: RangeQuery) -> Self { Self { @@ -45,23 +45,20 @@ impl CachedRangeResults { self.components.contains_key(&component_name.into()) } - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// Returns the [`RangeComponentResults`] for the specified [`Component`]. #[inline] - pub fn get( - &self, - component_name: impl Into, - ) -> Option<&CachedRangeComponentResults> { + pub fn get(&self, component_name: impl Into) -> Option<&RangeComponentResults> { self.components.get(&component_name.into()) } - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// Returns the [`RangeComponentResults`] for the specified [`Component`]. /// /// Returns an error if the component is not present. #[inline] pub fn get_required( &self, component_name: impl Into, - ) -> crate::Result<&CachedRangeComponentResults> { + ) -> crate::Result<&RangeComponentResults> { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { Ok(component) @@ -74,27 +71,24 @@ impl CachedRangeResults { } } - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// Returns the [`RangeComponentResults`] for the specified [`Component`]. /// /// Returns empty results if the component is not present. #[inline] - pub fn get_or_empty( - &self, - component_name: impl Into, - ) -> &CachedRangeComponentResults { + pub fn get_or_empty(&self, component_name: impl Into) -> &RangeComponentResults { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { component } else { - CachedRangeComponentResults::empty() + RangeComponentResults::empty() } } } -impl CachedRangeResults { +impl RangeResults { #[doc(hidden)] #[inline] - pub fn add(&mut self, component_name: ComponentName, cached: CachedRangeComponentResults) { + pub fn add(&mut self, component_name: ComponentName, cached: RangeComponentResults) { self.components.insert(component_name, cached); } } @@ -111,17 +105,17 @@ thread_local! { /// Lazily cached results for a particular component when using a cached range query. #[derive(Debug)] -pub struct CachedRangeComponentResults { +pub struct RangeComponentResults { /// The [`TimeRange`] of the query that was used in order to retrieve these results in the /// first place. /// /// The "original" copy in the cache just stores [`TimeRange::EMPTY`]. It's meaningless. pub(crate) time_range: TimeRange, - pub(crate) inner: Arc>, + pub(crate) inner: Arc>, } -impl CachedRangeComponentResults { +impl RangeComponentResults { /// Clones the results while making sure to stamp them with the [`TimeRange`] of the associated query. #[inline] pub(crate) fn clone_at(&self, time_range: TimeRange) -> Self { @@ -132,15 +126,15 @@ impl CachedRangeComponentResults { } } -impl CachedRangeComponentResults { +impl RangeComponentResults { #[inline] pub fn empty() -> &'static Self { - static EMPTY: OnceLock = OnceLock::new(); - EMPTY.get_or_init(CachedRangeComponentResults::default) + static EMPTY: OnceLock = OnceLock::new(); + EMPTY.get_or_init(RangeComponentResults::default) } } -impl re_types_core::SizeBytes for CachedRangeComponentResults { +impl re_types_core::SizeBytes for RangeComponentResults { #[inline] fn heap_size_bytes(&self) -> u64 { // NOTE: it's all on the heap past this point. @@ -148,18 +142,18 @@ impl re_types_core::SizeBytes for CachedRangeComponentResults { } } -impl Default for CachedRangeComponentResults { +impl Default for RangeComponentResults { #[inline] fn default() -> Self { Self { time_range: TimeRange::EMPTY, - inner: Arc::new(RwLock::new(CachedRangeComponentResultsInner::empty())), + inner: Arc::new(RwLock::new(RangeComponentResultsInner::empty())), } } } -impl std::ops::Deref for CachedRangeComponentResults { - type Target = RwLock; +impl std::ops::Deref for RangeComponentResults { + type Target = RwLock; #[inline] fn deref(&self) -> &Self::Target { @@ -208,7 +202,7 @@ impl<'a, T: 'static> std::ops::Deref for Data<'a, T> { } } -pub struct CachedRangeData<'a, T> { +pub struct RangeData<'a, T> { // NOTE: Options so we can represent an empty result without having to somehow conjure a mutex // guard out of thin air. // @@ -230,14 +224,14 @@ pub struct CachedRangeData<'a, T> { reentering: &'static std::thread::LocalKey>, } -impl<'a, C: Component> CachedRangeData<'a, C> { +impl<'a, C: Component> RangeData<'a, C> { /// Useful to abstract over latest-at and ranged results. #[inline] pub fn from_latest_at( resolver: &PromiseResolver, - results: &'a CachedLatestAtComponentResults, + results: &'a LatestAtComponentResults, ) -> Self { - let CachedLatestAtComponentResults { + let LatestAtComponentResults { index, promise: _, cached_dense, @@ -256,7 +250,7 @@ impl<'a, C: Component> CachedRangeData<'a, C> { } } -impl<'a, T> Drop for CachedRangeData<'a, T> { +impl<'a, T> Drop for RangeData<'a, T> { #[inline] fn drop(&mut self) { self.reentering @@ -264,7 +258,7 @@ impl<'a, T> Drop for CachedRangeData<'a, T> { } } -impl<'a, T: 'static> CachedRangeData<'a, T> { +impl<'a, T: 'static> RangeData<'a, T> { /// Returns the current status on both ends of the range. /// /// E.g. it is possible that the front-side of the range is still waiting for pending data while @@ -343,7 +337,7 @@ impl<'a, T: 'static> CachedRangeData<'a, T> { } } -impl CachedRangeComponentResults { +impl RangeComponentResults { /// Returns the component data as a dense vector. /// /// Returns an error if the component is missing or cannot be deserialized. @@ -351,7 +345,7 @@ impl CachedRangeComponentResults { /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of /// deserializing the data into a single one, if you don't need the extra flexibility. #[inline] - pub fn to_dense(&self, resolver: &PromiseResolver) -> CachedRangeData<'_, C> { + pub fn to_dense(&self, resolver: &PromiseResolver) -> RangeData<'_, C> { // It's tracing the deserialization of an entire range query at once -- it's fine. re_tracing::profile_function!(); @@ -361,7 +355,7 @@ impl CachedRangeComponentResults { // Manufactured empty result. if self.time_range == TimeRange::EMPTY { - return CachedRangeData { + return RangeData { indices: None, data: None, time_range: TimeRange::EMPTY, @@ -584,7 +578,7 @@ impl CachedRangeComponentResults { .unwrap() }); - CachedRangeData { + RangeData { indices: Some(Indices::Cached(indices)), data: Some(Data::Cached(data)), time_range: self.time_range, @@ -598,7 +592,7 @@ impl CachedRangeComponentResults { // --- /// Lazily cached results for a particular component when using a cached range query. -pub struct CachedRangeComponentResultsInner { +pub struct RangeComponentResultsInner { pub(crate) indices: VecDeque<(TimeInt, RowId)>, /// All the pending promises that must resolved in order to fill the missing data on the @@ -626,7 +620,7 @@ pub struct CachedRangeComponentResultsInner { pub(crate) cached_dense: Option>, } -impl SizeBytes for CachedRangeComponentResultsInner { +impl SizeBytes for RangeComponentResultsInner { #[inline] fn heap_size_bytes(&self) -> u64 { let Self { @@ -647,7 +641,7 @@ impl SizeBytes for CachedRangeComponentResultsInner { } } -impl std::fmt::Debug for CachedRangeComponentResultsInner { +impl std::fmt::Debug for RangeComponentResultsInner { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { indices, @@ -676,7 +670,7 @@ impl std::fmt::Debug for CachedRangeComponentResultsInner { } } -impl CachedRangeComponentResultsInner { +impl RangeComponentResultsInner { #[inline] pub const fn empty() -> Self { Self { diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 671248628e0a..2325aa3b2868 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -1,6 +1,6 @@ use re_data_store::LatestAtQuery; use re_entity_db::{ - external::re_query::{CachedLatestAtResults, PromiseResult, ToArchetype}, + external::re_query::{LatestAtResults, PromiseResult, ToArchetype}, EntityDb, }; use re_log_types::EntityPath; @@ -46,7 +46,7 @@ pub fn query_space_view_sub_archetype( query: &LatestAtQuery, ) -> (PromiseResult>, EntityPath) where - CachedLatestAtResults: ToArchetype, + LatestAtResults: ToArchetype, { let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); ( @@ -63,7 +63,7 @@ pub fn query_space_view_sub_archetype_or_default( query: &LatestAtQuery, ) -> (A, EntityPath) where - CachedLatestAtResults: ToArchetype, + LatestAtResults: ToArchetype, { let (arch, path) = query_space_view_sub_archetype(space_view_id, blueprint_db, query); (arch.ok().flatten().unwrap_or_default(), path) diff --git a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs index ec00b93d87c1..b274db0b8b97 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs @@ -220,7 +220,7 @@ impl VisualizerSystem for Arrows2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs index d82e6f86b883..cf59264e9401 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs @@ -223,7 +223,7 @@ impl VisualizerSystem for Arrows3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/assets3d.rs b/crates/re_space_view_spatial/src/visualizers/assets3d.rs index 9ac4c27c3b13..77d22a2a4d93 100644 --- a/crates/re_space_view_spatial/src/visualizers/assets3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/assets3d.rs @@ -143,7 +143,7 @@ impl VisualizerSystem for Asset3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs index f03073e31d8f..dc4588ff9746 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs @@ -216,7 +216,7 @@ impl VisualizerSystem for Boxes2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs index 894c318d2bb2..2dfcd63d95cf 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs @@ -206,7 +206,7 @@ impl VisualizerSystem for Boxes3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index d4edecab423c..6b5c39bf70ed 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -2,7 +2,7 @@ use itertools::Either; use re_data_store::{LatestAtQuery, RangeQuery}; use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::{EntityPath, TimeInt, Timeline}; -use re_query::{CachedResults, ExtraQueryHistory}; +use re_query::{ExtraQueryHistory, Results}; use re_renderer::DepthOffset; use re_space_view::query_visual_history; use re_types::Archetype; @@ -46,7 +46,7 @@ pub fn query_archetype_with_history( time: &TimeInt, history: &ExtraQueryHistory, entity_path: &EntityPath, -) -> CachedResults { +) -> Results { let visible_history = match timeline.typ() { re_log_types::TimeType::Time => history.nanos, re_log_types::TimeType::Sequence => history.sequences, @@ -96,7 +96,7 @@ where &EntityPath, &EntityProperties, &SpatialSceneEntityContext<'_>, - &CachedResults, + &Results, ) -> Result<(), SpaceViewSystemExecutionError>, { let transforms = view_ctx.get::()?; diff --git a/crates/re_space_view_spatial/src/visualizers/images.rs b/crates/re_space_view_spatial/src/visualizers/images.rs index a26468b15fa7..54fc1a9919e6 100644 --- a/crates/re_space_view_spatial/src/visualizers/images.rs +++ b/crates/re_space_view_spatial/src/visualizers/images.rs @@ -855,7 +855,7 @@ impl ImageVisualizer { |ctx, entity_path, entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/lines2d.rs b/crates/re_space_view_spatial/src/visualizers/lines2d.rs index 24968114f67d..bbddd23851d6 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines2d.rs @@ -205,7 +205,7 @@ impl VisualizerSystem for Lines2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/lines3d.rs b/crates/re_space_view_spatial/src/visualizers/lines3d.rs index abbaded57525..e4da2c12ce24 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines3d.rs @@ -214,7 +214,7 @@ impl VisualizerSystem for Lines3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/meshes.rs b/crates/re_space_view_spatial/src/visualizers/meshes.rs index 55b8f0fc3bec..5ac9b2a3a48b 100644 --- a/crates/re_space_view_spatial/src/visualizers/meshes.rs +++ b/crates/re_space_view_spatial/src/visualizers/meshes.rs @@ -168,7 +168,7 @@ impl VisualizerSystem for Mesh3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/mod.rs b/crates/re_space_view_spatial/src/visualizers/mod.rs index 98e205ec4ab7..62745ee750f2 100644 --- a/crates/re_space_view_spatial/src/visualizers/mod.rs +++ b/crates/re_space_view_spatial/src/visualizers/mod.rs @@ -22,7 +22,7 @@ pub use images::{ImageVisualizer, ViewerImage}; pub use spatial_view_visualizer::SpatialViewVisualizerData; pub use transform3d_arrows::{add_axis_arrows, Transform3DArrowsVisualizer}; -pub(crate) use self::results_ext::CachedRangeResultsExt; +pub(crate) use self::results_ext::RangeResultsExt; // --- diff --git a/crates/re_space_view_spatial/src/visualizers/points2d.rs b/crates/re_space_view_spatial/src/visualizers/points2d.rs index b25d3a4b1041..3ac152c1184e 100644 --- a/crates/re_space_view_spatial/src/visualizers/points2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points2d.rs @@ -224,7 +224,7 @@ impl VisualizerSystem for Points2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/points3d.rs b/crates/re_space_view_spatial/src/visualizers/points3d.rs index 252e9fbe6a6c..98e2ce7da604 100644 --- a/crates/re_space_view_spatial/src/visualizers/points3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points3d.rs @@ -215,7 +215,7 @@ impl VisualizerSystem for Points3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/results_ext.rs b/crates/re_space_view_spatial/src/visualizers/results_ext.rs index fb068cee4c8b..1b03697315b6 100644 --- a/crates/re_space_view_spatial/src/visualizers/results_ext.rs +++ b/crates/re_space_view_spatial/src/visualizers/results_ext.rs @@ -1,7 +1,4 @@ -use re_query::{ - CachedLatestAtResults, CachedRangeData, CachedRangeResults, CachedResults, PromiseResolver, - PromiseResult, -}; +use re_query::{LatestAtResults, PromiseResolver, PromiseResult, RangeData, RangeResults, Results}; use re_types::Component; // --- @@ -10,46 +7,46 @@ use re_types::Component; /// /// Also turns all results into range results, so that views only have to worry about the ranged /// case. -pub trait CachedRangeResultsExt { +pub trait RangeResultsExt { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>>; + ) -> Option>>; fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query::Result>; + ) -> re_query::Result>; } -impl CachedRangeResultsExt for CachedResults { +impl RangeResultsExt for Results { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { match self { - CachedResults::LatestAt(_, results) => results.get_dense(resolver), - CachedResults::Range(_, results) => results.get_dense(resolver), + Results::LatestAt(_, results) => results.get_dense(resolver), + Results::Range(_, results) => results.get_dense(resolver), } } fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query::Result> { + ) -> re_query::Result> { match self { - CachedResults::LatestAt(_, results) => results.get_or_empty_dense(resolver), - CachedResults::Range(_, results) => results.get_or_empty_dense(resolver), + Results::LatestAt(_, results) => results.get_or_empty_dense(resolver), + Results::Range(_, results) => results.get_or_empty_dense(resolver), } } } -impl CachedRangeResultsExt for CachedRangeResults { +impl RangeResultsExt for RangeResults { #[inline] fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?.to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? @@ -70,7 +67,7 @@ impl CachedRangeResultsExt for CachedRangeResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query::Result> { + ) -> re_query::Result> { let results = self.get_or_empty(C::name()).to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? @@ -88,14 +85,14 @@ impl CachedRangeResultsExt for CachedRangeResults { } } -impl CachedRangeResultsExt for CachedLatestAtResults { +impl RangeResultsExt for LatestAtResults { #[inline] fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?; - let data = CachedRangeData::from_latest_at(resolver, results); + let data = RangeData::from_latest_at(resolver, results); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); @@ -115,9 +112,9 @@ impl CachedRangeResultsExt for CachedLatestAtResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query::Result> { + ) -> re_query::Result> { let results = self.get_or_empty(C::name()); - let data = CachedRangeData::from_latest_at(resolver, results); + let data = RangeData::from_latest_at(resolver, results); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); diff --git a/crates/re_space_view_tensor/src/visualizer_system.rs b/crates/re_space_view_tensor/src/visualizer_system.rs index a40414c63458..c0f0bfb05018 100644 --- a/crates/re_space_view_tensor/src/visualizer_system.rs +++ b/crates/re_space_view_tensor/src/visualizer_system.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query::CachedLatestAtMonoResult, EntityPath}; +use re_entity_db::{external::re_query::LatestAtMonoResult, EntityPath}; use re_log_types::RowId; use re_types::{archetypes::Tensor, components::TensorData, tensor_data::DecodedTensor}; use re_viewer_context::{ @@ -56,7 +56,7 @@ impl TensorSystem { &mut self, ctx: &ViewerContext<'_>, ent_path: &EntityPath, - tensor: CachedLatestAtMonoResult, + tensor: LatestAtMonoResult, ) { let row_id = tensor.row_id(); match ctx diff --git a/crates/re_space_view_text_log/src/visualizer_system.rs b/crates/re_space_view_text_log/src/visualizer_system.rs index 1940f5c314d0..642a4a023309 100644 --- a/crates/re_space_view_text_log/src/visualizer_system.rs +++ b/crates/re_space_view_text_log/src/visualizer_system.rs @@ -1,7 +1,7 @@ use re_data_store::TimeRange; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query::{clamped_zip_1x2, range_zip_1x2, CachedRangeData, PromiseResult}; +use re_query::{clamped_zip_1x2, range_zip_1x2, PromiseResult, RangeData}; use re_types::{ archetypes::TextLog, components::{Color, Text, TextLogLevel}, @@ -127,7 +127,7 @@ impl VisualizerSystem for TextLogSystem { // TODO(#5607): what should happen if the promise is still pending? #[inline] -fn check_range<'a, C: Component>(results: &'a CachedRangeData<'a, C>) -> re_query::Result<()> { +fn check_range<'a, C: Component>(results: &'a RangeData<'a, C>) -> re_query::Result<()> { let (front_status, back_status) = results.status(); match front_status { PromiseResult::Pending => return Ok(()), diff --git a/crates/re_types_builder/src/codegen/rust/to_archetype.rs b/crates/re_types_builder/src/codegen/rust/to_archetype.rs index d588f1aafe90..af38e603a5d8 100644 --- a/crates/re_types_builder/src/codegen/rust/to_archetype.rs +++ b/crates/re_types_builder/src/codegen/rust/to_archetype.rs @@ -68,7 +68,7 @@ fn generate_impls( use re_types_core::{Archetype, Loggable as _}; - use crate::{CachedLatestAtResults, PromiseResolver, PromiseResult}; + use crate::{LatestAtResults, PromiseResolver, PromiseResult}; }; for obj in objects.ordered_objects(Some(ObjectKind::Archetype)) { @@ -237,7 +237,7 @@ fn quote_to_archetype_impl(objects: &Objects, obj: &Object) -> TokenStream { }); quote! { - impl crate::ToArchetype<#quoted_arch_fqname> for CachedLatestAtResults { + impl crate::ToArchetype<#quoted_arch_fqname> for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index 133d95d8ed01..756870c051ea 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query::CachedLatestAtComponentResults, EntityDb, EntityPath}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb, EntityPath}; use re_log_types::DataCell; use re_types::{components::InstanceKey, ComponentName, Loggable as _}; @@ -40,7 +40,7 @@ type ComponentUiCallback = Box< &LatestAtQuery, &EntityDb, &EntityPath, - &CachedLatestAtComponentResults, + &LatestAtComponentResults, &InstanceKey, ) + Send + Sync, @@ -55,7 +55,7 @@ type ComponentEditCallback = Box< &EntityDb, &EntityPath, &EntityPath, - &CachedLatestAtComponentResults, + &LatestAtComponentResults, &InstanceKey, ) + Send + Sync, @@ -120,7 +120,7 @@ impl ComponentUiRegistry { query: &LatestAtQuery, db: &EntityDb, entity_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &InstanceKey, ) { let Some(component_name) = component.component_name(db.resolver()) else { @@ -163,7 +163,7 @@ impl ComponentUiRegistry { db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &InstanceKey, ) { let Some(component_name) = component.component_name(db.resolver()) else { diff --git a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs index acb442037850..07ef8f083bde 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs @@ -38,7 +38,7 @@ impl re_types::Archetype for ColorArchetype { } } -impl re_query::ToArchetype for re_query::CachedLatestAtResults { +impl re_query::ToArchetype for re_query::LatestAtResults { #[inline] fn to_archetype( &self, From 63302223090b519fe5b773a0b36d6d4ac43735ef Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 24 Apr 2024 16:28:55 +0200 Subject: [PATCH 6/9] port the entire latest-at test suite --- crates/re_query/src/latest_at/results.rs | 2 +- crates/re_query/src/range/results.rs | 2 +- crates/re_query/tests/latest_at.rs | 1091 ++++++++++++---------- 3 files changed, 578 insertions(+), 517 deletions(-) diff --git a/crates/re_query/src/latest_at/results.rs b/crates/re_query/src/latest_at/results.rs index a14ff7d2afb8..0360a02c1a40 100644 --- a/crates/re_query/src/latest_at/results.rs +++ b/crates/re_query/src/latest_at/results.rs @@ -11,7 +11,7 @@ use crate::{ // --- -/// results for a latest-at query. +/// Results for a latest-at query. /// /// The data is both deserialized and resolved/converted. /// diff --git a/crates/re_query/src/range/results.rs b/crates/re_query/src/range/results.rs index 3c88d173abb2..cff3abcceabc 100644 --- a/crates/re_query/src/range/results.rs +++ b/crates/re_query/src/range/results.rs @@ -19,7 +19,7 @@ use crate::{ // --- -/// results for a range query. +/// Results for a range query. /// /// The data is both deserialized and resolved/converted. /// diff --git a/crates/re_query/tests/latest_at.rs b/crates/re_query/tests/latest_at.rs index b16caa84c495..b5df7aca1826 100644 --- a/crates/re_query/tests/latest_at.rs +++ b/crates/re_query/tests/latest_at.rs @@ -1,12 +1,8 @@ -//! Contains: -//! - A 1:1 port of the tests in `crates/re_query/tests/archetype_query_tests.rs`, with caching enabled. -//! - Invalidation tests. - use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; use re_log_types::{ build_frame_nr, example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, + DataRow, EntityPath, RowId, TimeInt, TimePoint, }; use re_query::Caches; use re_query::PromiseResolver; @@ -15,514 +11,579 @@ use re_types_core::{components::InstanceKey, Loggable as _}; // --- -// TODO +#[test] +fn simple_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); -// #[test] -// fn simple_query() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path = "point"; -// let timepoint = [build_frame_nr(123)]; -// -// // Create some positions with implicit instances -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// // Assign one of them a color with an explicit instance -// let color_instances = vec![InstanceKey(1)]; -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = DataRow::from_cells2_sized( -// RowId::new(), -// entity_path, -// timepoint, -// 1, -// (color_instances, colors), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// } -// -// #[test] -// fn static_query() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path = "point"; -// let timepoint = [build_frame_nr(123)]; -// -// // Create some positions with implicit instances -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// // Assign one of them a color with an explicit instance.. statically! -// let color_instances = vec![InstanceKey(1)]; -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = DataRow::from_cells2_sized( -// RowId::new(), -// entity_path, -// TimePoint::default(), -// 1, -// (color_instances, colors), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// } -// -// #[test] -// fn no_instance_join_query() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path = "point"; -// let timepoint = [build_frame_nr(123)]; -// -// // Create some positions with an implicit instance -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// // Assign them colors with explicit instances -// let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; -// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// } -// -// #[test] -// fn missing_column_join_query() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path = "point"; -// let timepoint = [build_frame_nr(123)]; -// -// // Create some positions with an implicit instance -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// } -// -// #[test] -// fn splatted_query() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path = "point"; -// let timepoint = [build_frame_nr(123)]; -// -// // Create some positions with implicit instances -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// // Assign all of them a color via splat -// let color_instances = vec![InstanceKey::SPLAT]; -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = DataRow::from_cells2_sized( -// RowId::new(), -// entity_path, -// timepoint, -// 1, -// (color_instances, colors), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// } -// -// #[test] -// fn invalidation() { -// let entity_path = "point"; -// -// let test_invalidation = |query: LatestAtQuery, -// present_data_timepoint: TimePoint, -// past_data_timepoint: TimePoint, -// future_data_timepoint: TimePoint| { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// // Create some positions with implicit instances -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// present_data_timepoint.clone(), -// 2, -// positions, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// // Assign one of them a color with an explicit instance -// let color_instances = vec![InstanceKey(1)]; -// let colors = vec![MyColor::from_rgb(1, 2, 3)]; -// let row = DataRow::from_cells2_sized( -// RowId::new(), -// entity_path, -// present_data_timepoint.clone(), -// 1, -// (color_instances, colors), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // --- Modify present --- -// -// // Modify the PoV component -// let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// present_data_timepoint.clone(), -// 2, -// positions, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // Modify the optional component -// let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// present_data_timepoint, -// 2, -// colors, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // --- Modify past --- -// -// // Modify the PoV component -// let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// past_data_timepoint.clone(), -// 2, -// positions, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // Modify the optional component -// let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, past_data_timepoint, 2, colors) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // --- Modify future --- -// -// // Modify the PoV component -// let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// future_data_timepoint.clone(), -// 2, -// positions, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // Modify the optional component -// let colors = vec![MyColor::from_rgb(16, 17, 18)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// }; -// -// let timeless = TimePoint::default(); -// let frame_122 = build_frame_nr(122); -// let frame_123 = build_frame_nr(123); -// let frame_124 = build_frame_nr(124); -// -// test_invalidation( -// LatestAtQuery::new(frame_123.0, frame_123.1), -// [frame_123].into(), -// [frame_122].into(), -// [frame_124].into(), -// ); -// -// test_invalidation( -// LatestAtQuery::new(frame_123.0, frame_123.1), -// [frame_123].into(), -// timeless, -// [frame_124].into(), -// ); -// } -// -// // Test the following scenario: -// // ```py -// // rr.log("points", rr.Points3D([1, 2, 3]), static=True) -// // -// // # Do first query here: LatestAt(+inf) -// // # Expected: points=[[1,2,3]] colors=[] -// // -// // rr.set_time(2) -// // rr.log_components("points", rr.components.MyColor(0xFF0000)) -// // -// // # Do second query here: LatestAt(+inf) -// // # Expected: points=[[1,2,3]] colors=[0xFF0000] -// // -// // rr.set_time(3) -// // rr.log_components("points", rr.components.MyColor(0x0000FF)) -// // -// // # Do third query here: LatestAt(+inf) -// // # Expected: points=[[1,2,3]] colors=[0x0000FF] -// // -// // rr.set_time(3) -// // rr.log_components("points", rr.components.MyColor(0x00FF00)) -// // -// // # Do fourth query here: LatestAt(+inf) -// // # Expected: points=[[1,2,3]] colors=[0x00FF00] -// // ``` -// #[test] -// fn invalidation_of_future_optionals() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path = "points"; -// -// let timeless = TimePoint::default(); -// let frame2 = [build_frame_nr(2)]; -// let frame3 = [build_frame_nr(3)]; -// -// let query_time = [build_frame_nr(9999)]; -// -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// let color_instances = vec![InstanceKey::SPLAT]; -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = DataRow::from_cells2_sized( -// RowId::new(), -// entity_path, -// frame2, -// 1, -// (color_instances, colors), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// let color_instances = vec![InstanceKey::SPLAT]; -// let colors = vec![MyColor::from_rgb(0, 0, 255)]; -// let row = DataRow::from_cells2_sized( -// RowId::new(), -// entity_path, -// frame3, -// 1, -// (color_instances, colors), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// let color_instances = vec![InstanceKey::SPLAT]; -// let colors = vec![MyColor::from_rgb(0, 255, 0)]; -// let row = DataRow::from_cells2_sized( -// RowId::new(), -// entity_path, -// frame3, -// 1, -// (color_instances, colors), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// } -// -// #[test] -// fn static_invalidation() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path = "points"; -// -// let timeless = TimePoint::default(); -// -// let query_time = [build_frame_nr(9999)]; -// -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// let color_instances = vec![InstanceKey::SPLAT]; -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = DataRow::from_cells2_sized( -// RowId::new(), -// entity_path, -// timeless.clone(), -// 1, -// (color_instances, colors), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// let color_instances = vec![InstanceKey::SPLAT]; -// let colors = vec![MyColor::from_rgb(0, 0, 255)]; -// let row = DataRow::from_cells2_sized( -// RowId::new(), -// entity_path, -// timeless, -// 1, -// (color_instances, colors), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// } -// -// // --- -// -// fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { -// caches.on_events(&[store.insert_row(row).unwrap()]); -// } -// -// fn query_and_compare( -// caches: &Caches, -// store: &DataStore, -// query: &LatestAtQuery, -// entity_path: &EntityPath, -// ) { -// re_log::setup_logging(); -// -// let resolver = PromiseResolver::default(); -// -// for _ in 0..3 { -// let cached = caches.latest_at( -// store, -// query, -// entity_path, -// MyPoints::all_components().iter().copied(), -// ); -// -// let cached_points = cached.get_required(MyPoint::name()).unwrap(); -// let cached_point_data = cached_points -// .to_dense::(&resolver) -// .flatten() -// .unwrap(); -// -// let cached_colors = cached.get_or_empty(MyColor::name()); -// let cached_color_data = cached_colors -// .to_dense::(&resolver) -// .flatten() -// .unwrap(); -// -// let expected = re_query::latest_at( -// store, -// query, -// entity_path, -// MyPoints::all_components().iter().copied(), -// ); -// -// let expected_points = expected.get_required(MyPoint::name()).unwrap(); -// let expected_point_data = expected_points -// .to_dense::(&resolver) -// .flatten() -// .unwrap(); -// -// let expected_colors = expected.get_or_empty(MyColor::name()); -// let expected_color_data = expected_colors -// .to_dense::(&resolver) -// .flatten() -// .unwrap(); -// -// // eprintln!("{}", store.to_data_table().unwrap()); -// -// similar_asserts::assert_eq!(expected.compound_index, cached.compound_index); -// similar_asserts::assert_eq!(expected_point_data, cached_point_data); -// similar_asserts::assert_eq!(expected_color_data, cached_color_data); -// } -// } + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + let expected_compound_index = (TimeInt::new_temporal(123), row.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +#[test] +fn static_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + TimePoint::default(), + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + let expected_compound_index = (TimeInt::new_temporal(123), row1.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +#[test] +fn invalidation() { + let entity_path = "point"; + + let test_invalidation = |query: LatestAtQuery, + present_data_timepoint: TimePoint, + past_data_timepoint: TimePoint, + future_data_timepoint: TimePoint| { + let past_timestamp = past_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + let present_timestamp = present_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let colors = vec![MyColor::from_rgb(1, 2, 3)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_compound_index = (present_timestamp, row2.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // --- Modify present --- + + // Modify the PoV component + let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_compound_index = (present_timestamp, row3.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; + let row4 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let expected_compound_index = (present_timestamp, row4.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // --- Modify past --- + + // Modify the PoV component + let points_past = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; + let row5 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + points_past.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row5); + + let expected_compound_index = (present_timestamp, row4.row_id()); + let expected_points = if past_timestamp.is_static() { + &points_past + } else { + &points + }; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors_past = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; + let row6 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint, + 2, + colors_past.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row6); + + let (expected_compound_index, expected_colors) = if past_timestamp.is_static() { + ((past_timestamp, row6.row_id()), &colors_past) + } else { + ((present_timestamp, row4.row_id()), &colors) + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // --- Modify future --- + + // Modify the PoV component + let points_future = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; + let row7 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint.clone(), + 2, + points_future.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row7); + + let (expected_compound_index, expected_points) = if past_timestamp.is_static() { + ((past_timestamp, row6.row_id()), &points_past) + } else { + ((present_timestamp, row4.row_id()), &points) + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors_future = vec![MyColor::from_rgb(16, 17, 18)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint, + 1, + colors_future, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let (expected_compound_index, expected_colors) = if past_timestamp.is_static() { + ((past_timestamp, row6.row_id()), &colors_past) + } else { + ((present_timestamp, row4.row_id()), &colors) + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + }; + + let static_ = TimePoint::default(); + let frame_122 = build_frame_nr(122); + let frame_123 = build_frame_nr(123); + let frame_124 = build_frame_nr(124); + + test_invalidation( + LatestAtQuery::new(frame_123.0, frame_123.1), + [frame_123].into(), + [frame_122].into(), + [frame_124].into(), + ); + + test_invalidation( + LatestAtQuery::new(frame_123.0, frame_123.1), + [frame_123].into(), + static_, + [frame_124].into(), + ); +} + +// Test the following scenario: +// ```py +// rr.log("points", rr.Points3D([1, 2, 3]), static=True) +// +// # Do first query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[] +// +// rr.set_time(2) +// rr.log_components("points", rr.components.MyColor(0xFF0000)) +// +// # Do second query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0xFF0000] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x0000FF)) +// +// # Do third query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x0000FF] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x00FF00)) +// +// # Do fourth query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x00FF00] +// ``` +#[test] +fn invalidation_of_future_optionals() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let static_ = TimePoint::default(); + let frame2 = [build_frame_nr(2)]; + let frame3 = [build_frame_nr(3)]; + + let query_time = [build_frame_nr(9999)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = + DataRow::from_cells1_sized(RowId::new(), entity_path, static_, 2, points.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row1.row_id()); + let expected_points = &points; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::new_temporal(2), row2.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::new_temporal(3), row3.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(0, 255, 0)]; + let row4 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::new_temporal(3), row4.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +#[test] +fn static_invalidation() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + + let query_time = [build_frame_nr(9999)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 2, + points.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row1.row_id()); + let expected_points = &points; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row2.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row3.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +// --- + +fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { + caches.on_events(&[store.insert_row(row).unwrap()]); +} + +fn query_and_compare( + caches: &Caches, + store: &DataStore, + query: &LatestAtQuery, + entity_path: &EntityPath, + expected_compound_index: (TimeInt, RowId), + expected_points: &[MyPoint], + expected_colors: &[MyColor], +) { + re_log::setup_logging(); + + let resolver = PromiseResolver::default(); + + for _ in 0..3 { + let cached = caches.latest_at( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let cached_points = cached.get_required(MyPoint::name()).unwrap(); + let cached_points = cached_points + .to_dense::(&resolver) + .flatten() + .unwrap(); + + let cached_colors = cached.get_or_empty(MyColor::name()); + let cached_colors = cached_colors + .to_dense::(&resolver) + .flatten() + .unwrap(); + + // eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!(expected_compound_index, cached.compound_index); + similar_asserts::assert_eq!(expected_points, cached_points); + similar_asserts::assert_eq!(expected_colors, cached_colors); + } +} From 5c343a4430144fa7282b780585a5e3af114be0de Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 24 Apr 2024 16:29:00 +0200 Subject: [PATCH 7/9] port the entire range test suite --- crates/re_query/tests/range.rs | 1412 +++++++++++++++++++------------- 1 file changed, 838 insertions(+), 574 deletions(-) diff --git a/crates/re_query/tests/range.rs b/crates/re_query/tests/range.rs index 4cdccf88c626..615e48005d29 100644 --- a/crates/re_query/tests/range.rs +++ b/crates/re_query/tests/range.rs @@ -1,4 +1,4 @@ -use itertools::{izip, Itertools as _}; +use itertools::Itertools as _; use re_data_store::{DataStore, RangeQuery, StoreSubscriber as _, TimeInt, TimeRange}; use re_log_types::{ @@ -12,577 +12,841 @@ use re_types_core::Loggable as _; // --- -// TODO +#[test] +fn simple_range() -> anyhow::Result<()> { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); -// #[test] -// fn simple_range() -> anyhow::Result<()> { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path: EntityPath = "point".into(); -// -// let timepoint1 = [build_frame_nr(123)]; -// { -// let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; -// insert_and_react(&mut store, &mut caches, &row); -// -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; -// insert_and_react(&mut store, &mut caches, &row); -// } -// -// let timepoint2 = [build_frame_nr(223)]; -// { -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; -// insert_and_react(&mut store, &mut caches, &row); -// } -// -// let timepoint3 = [build_frame_nr(323)]; -// { -// let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; -// insert_and_react(&mut store, &mut caches, &row); -// } -// -// // --- First test: `(timepoint1, timepoint3]` --- -// -// let query = re_data_store::RangeQuery::new( -// timepoint1[0].0, -// TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), -// ); -// -// query_and_compare(&caches, &store, &query, &entity_path); -// -// // --- Second test: `[timepoint1, timepoint3]` --- -// -// let query = re_data_store::RangeQuery::new( -// timepoint1[0].0, -// TimeRange::new(timepoint1[0].1, timepoint3[0].1), -// ); -// -// query_and_compare(&caches, &store, &query, &entity_path); -// -// Ok(()) -// } -// -// #[test] -// fn static_range() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path: EntityPath = "point".into(); -// -// let timepoint1 = [build_frame_nr(123)]; -// { -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path.clone(), -// timepoint1, -// 1, -// colors.clone(), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// // Insert statically too! -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path.clone(), -// TimePoint::default(), -// 1, -// colors, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// } -// -// let timepoint2 = [build_frame_nr(223)]; -// { -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path.clone(), -// timepoint2, -// 1, -// colors.clone(), -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// // Insert statically too! -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path.clone(), -// TimePoint::default(), -// 1, -// colors, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// } -// -// let timepoint3 = [build_frame_nr(323)]; -// { -// // Create some Positions with implicit instances -// let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// } -// -// // --- First test: `(timepoint1, timepoint3]` --- -// -// let query = re_data_store::RangeQuery::new( -// timepoint1[0].0, -// TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), -// ); -// -// query_and_compare(&caches, &store, &query, &entity_path); -// -// // --- Second test: `[timepoint1, timepoint3]` --- -// -// // The inclusion of `timepoint1` means latest-at semantics will fall back to timeless data! -// -// let query = re_data_store::RangeQuery::new( -// timepoint1[0].0, -// TimeRange::new(timepoint1[0].1, timepoint3[0].1), -// ); -// -// query_and_compare(&caches, &store, &query, &entity_path); -// -// // --- Third test: `[-inf, +inf]` --- -// -// let query = -// re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); -// -// query_and_compare(&caches, &store, &query, &entity_path); -// } -// -// #[test] -// fn simple_splatted_range() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path: EntityPath = "point".into(); -// -// let timepoint1 = [build_frame_nr(123)]; -// { -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// // Assign one of them a color with an explicit instance -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// } -// -// let timepoint2 = [build_frame_nr(223)]; -// { -// let colors = vec![MyColor::from_rgb(0, 255, 0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// } -// -// let timepoint3 = [build_frame_nr(323)]; -// { -// let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// } -// -// // --- First test: `(timepoint1, timepoint3]` --- -// -// let query = re_data_store::RangeQuery::new( -// timepoint1[0].0, -// TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), -// ); -// -// query_and_compare(&caches, &store, &query, &entity_path); -// -// // --- Second test: `[timepoint1, timepoint3]` --- -// -// let query = re_data_store::RangeQuery::new( -// timepoint1[0].0, -// TimeRange::new(timepoint1[0].1, timepoint3[0].1), -// ); -// -// query_and_compare(&caches, &store, &query, &entity_path); -// } -// -// #[test] -// fn invalidation() { -// let entity_path = "point"; -// -// let test_invalidation = |query: RangeQuery, -// present_data_timepoint: TimePoint, -// past_data_timepoint: TimePoint, -// future_data_timepoint: TimePoint| { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// present_data_timepoint.clone(), -// 2, -// positions, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// let colors = vec![MyColor::from_rgb(1, 2, 3)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// present_data_timepoint.clone(), -// 1, -// colors, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // --- Modify present --- -// -// // Modify the PoV component -// let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// present_data_timepoint.clone(), -// 2, -// positions, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // Modify the optional component -// let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// present_data_timepoint, -// 2, -// colors, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // --- Modify past --- -// -// // Modify the PoV component -// let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// past_data_timepoint.clone(), -// 2, -// positions, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // Modify the optional component -// let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// past_data_timepoint.clone(), -// 2, -// colors, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // --- Modify future --- -// -// // Modify the PoV component -// let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; -// let row = DataRow::from_cells1_sized( -// RowId::new(), -// entity_path, -// future_data_timepoint.clone(), -// 2, -// positions, -// ) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// // Modify the optional component -// let colors = vec![MyColor::from_rgb(16, 17, 18)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// }; -// -// let timeless = TimePoint::default(); -// let frame_122 = build_frame_nr(122); -// let frame_123 = build_frame_nr(123); -// let frame_124 = build_frame_nr(124); -// -// test_invalidation( -// RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), -// [frame_123].into(), -// [frame_122].into(), -// [frame_124].into(), -// ); -// -// test_invalidation( -// RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), -// [frame_123].into(), -// timeless, -// [frame_124].into(), -// ); -// } -// -// // Test the following scenario: -// // ```py -// // rr.log("points", rr.Points3D([1, 2, 3]), static=True) -// // -// // # Do first query here: LatestAt(+inf) -// // # Expected: points=[[1,2,3]] colors=[] -// // -// // rr.set_time(2) -// // rr.log_components("points", rr.components.MyColor(0xFF0000)) -// // -// // # Do second query here: LatestAt(+inf) -// // # Expected: points=[[1,2,3]] colors=[0xFF0000] -// // -// // rr.set_time(3) -// // rr.log_components("points", rr.components.MyColor(0x0000FF)) -// // -// // # Do third query here: LatestAt(+inf) -// // # Expected: points=[[1,2,3]] colors=[0x0000FF] -// // -// // rr.set_time(3) -// // rr.log_components("points", rr.components.MyColor(0x00FF00)) -// // -// // # Do fourth query here: LatestAt(+inf) -// // # Expected: points=[[1,2,3]] colors=[0x00FF00] -// // ``` -// #[test] -// fn invalidation_of_future_optionals() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path = "points"; -// -// let timeless = TimePoint::default(); -// let frame2 = [build_frame_nr(2)]; -// let frame3 = [build_frame_nr(3)]; -// -// let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); -// -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// let colors = vec![MyColor::from_rgb(0, 0, 255)]; -// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// let colors = vec![MyColor::from_rgb(0, 255, 0)]; -// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// } -// -// #[test] -// fn invalidation_static() { -// let mut store = DataStore::new( -// re_log_types::StoreId::random(re_log_types::StoreKind::Recording), -// InstanceKey::name(), -// Default::default(), -// ); -// let mut caches = Caches::new(&store); -// -// let entity_path = "points"; -// -// let timeless = TimePoint::default(); -// -// let frame0 = [build_frame_nr(TimeInt::ZERO)]; -// let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); -// -// let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; -// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) -// .unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// let colors = vec![MyColor::from_rgb(255, 0, 0)]; -// let row = -// DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 1, colors).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// -// let colors = vec![MyColor::from_rgb(0, 0, 255)]; -// let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors).unwrap(); -// insert_and_react(&mut store, &mut caches, &row); -// -// query_and_compare(&caches, &store, &query, &entity_path.into()); -// } -// -// // --- -// -// fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { -// caches.on_events(&[store.insert_row(row).unwrap()]); -// } -// -// fn query_and_compare( -// caches: &Caches, -// store: &DataStore, -// query: &RangeQuery, -// entity_path: &EntityPath, -// ) { -// re_log::setup_logging(); -// -// let resolver = PromiseResolver::default(); -// -// for _ in 0..3 { -// let cached = caches.range( -// store, -// query, -// entity_path, -// MyPoints::all_components().iter().copied(), -// ); -// -// let cached_all_points = cached -// .get_required(MyPoint::name()) -// .unwrap() -// .to_dense::(&resolver); -// assert!(matches!( -// cached_all_points.status(), -// (PromiseResult::Ready(()), PromiseResult::Ready(())), -// )); -// let cached_all_points_indexed = cached_all_points.range_indexed(); -// -// let cached_all_colors = cached -// .get_or_empty(MyColor::name()) -// .to_dense::(&resolver); -// assert!(matches!( -// cached_all_colors.status(), -// (PromiseResult::Ready(()), PromiseResult::Ready(())), -// )); -// let cached_all_colors_indexed = cached_all_colors.range_indexed(); -// -// let expected = re_query::range( -// store, -// query, -// entity_path, -// MyPoints::all_components().iter().copied(), -// ); -// -// let expected_all_points = expected.get_required(MyPoint::name()).unwrap(); -// let expected_all_points_indices = expected_all_points.indices(); -// let expected_all_points_data = expected_all_points -// .to_dense::(&resolver) -// .into_iter() -// .map(|batch| batch.flatten().unwrap()) -// .collect_vec(); -// let expected_all_points_indexed = -// izip!(expected_all_points_indices, expected_all_points_data); -// -// let expected_all_colors = expected.get_or_empty(MyColor::name()); -// let expected_all_colors_indices = expected_all_colors.indices(); -// let expected_all_colors_data = expected_all_colors -// .to_dense::(&resolver) -// .into_iter() -// .map(|batch| batch.flatten().unwrap()) -// .collect_vec(); -// let expected_all_colors_indexed = -// izip!(expected_all_colors_indices, expected_all_colors_data); -// -// eprintln!("{query:?}"); -// eprintln!("{}", store.to_data_table().unwrap()); -// -// similar_asserts::assert_eq!( -// expected_all_points_indexed -// .map(|(index, data)| (*index, data)) -// .collect_vec(), -// cached_all_points_indexed -// .map(|(index, data)| (*index, data.to_vec())) -// .collect_vec(), -// ); -// -// similar_asserts::assert_eq!( -// expected_all_colors_indexed -// .map(|(index, data)| (*index, data)) -// .collect_vec(), -// cached_all_colors_indexed -// .map(|(index, data)| (*index, data.to_vec())) -// .collect_vec(), -// ); -// } -// } + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1_1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 2, + points1.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row1_1); + let colors1 = vec![MyColor::from_rgb(255, 0, 0)]; + let row1_2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 1, + colors1.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row1_2); + + let timepoint2 = [build_frame_nr(223)]; + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint2, + 1, + colors2.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row2); + + let timepoint3 = [build_frame_nr(323)]; + let points3 = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint3, + 2, + points3.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row3); + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ( + (TimeInt::new_temporal(223), row2.row_id()), + colors2.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + // --- Second test: `[timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(123), row1_1.row_id()), + points1.as_slice(), + ), // + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ( + (TimeInt::new_temporal(123), row1_2.row_id()), + colors1.as_slice(), + ), // + ( + (TimeInt::new_temporal(223), row2.row_id()), + colors2.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + Ok(()) +} + +#[test] +fn static_range() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1_1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 2, + points1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1_1); + let colors1 = vec![MyColor::from_rgb(255, 0, 0)]; + let row1_2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 1, + colors1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1_2); + // Insert statically too! + let row1_3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + TimePoint::default(), + 1, + colors1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1_3); + + let timepoint2 = [build_frame_nr(223)]; + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2_1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint2, + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2_1); + // Insert statically too! + let row2_2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + TimePoint::default(), + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2_2); + + let timepoint3 = [build_frame_nr(323)]; + // Create some Positions with implicit instances + let points3 = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint3, + 2, + points3.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ((TimeInt::STATIC, row2_2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + // --- Second test: `[timepoint1, timepoint3]` --- + + // The inclusion of `timepoint1` means latest-at semantics will fall back to timeless data! + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(123), row1_1.row_id()), + points1.as_slice(), + ), // + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ((TimeInt::STATIC, row2_2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + // --- Third test: `[-inf, +inf]` --- + + let query = + re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); + + // same expectations + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); +} + +#[test] +fn invalidation() { + let entity_path = "point"; + + let test_invalidation = |query: RangeQuery, + present_data_timepoint: TimePoint, + past_data_timepoint: TimePoint, + future_data_timepoint: TimePoint| { + let past_timestamp = past_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + let present_timestamp = present_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + let future_timestamp = future_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let colors2 = vec![MyColor::from_rgb(1, 2, 3)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_points = &[ + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ]; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // --- Modify present --- + + // Modify the PoV component + let points3 = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points3.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_points = &[ + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ]; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors4 = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; + let row4 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint, + 2, + colors4.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let expected_points = &[ + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ]; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // --- Modify past --- + + // Modify the PoV component + let points5 = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; + let row5 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + points5.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row5); + + let expected_points1 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ] as &[_]; + let expected_points2 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ] as &[_]; + let expected_points = if past_data_timepoint.is_static() { + expected_points1 + } else { + expected_points2 + }; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors6 = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; + let row6 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + colors6.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row6); + + let expected_colors1 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ] as &[_]; + let expected_colors2 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ] as &[_]; + let expected_colors = if past_data_timepoint.is_static() { + expected_colors1 + } else { + expected_colors2 + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // --- Modify future --- + + // Modify the PoV component + let points7 = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; + let row7 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint.clone(), + 2, + points7.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row7); + + let expected_points1 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ] as &[_]; + let expected_points2 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ((future_timestamp, row7.row_id()), points7.as_slice()), // + ] as &[_]; + let expected_points = if past_data_timepoint.is_static() { + expected_points1 + } else { + expected_points2 + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors8 = vec![MyColor::from_rgb(16, 17, 18)]; + let row8 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint, + 1, + colors8.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row8); + + let expected_colors1 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ] as &[_]; + let expected_colors2 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ((future_timestamp, row8.row_id()), colors8.as_slice()), // + ] as &[_]; + let expected_colors = if past_data_timepoint.is_static() { + expected_colors1 + } else { + expected_colors2 + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + }; + + let timeless = TimePoint::default(); + let frame_122 = build_frame_nr(122); + let frame_123 = build_frame_nr(123); + let frame_124 = build_frame_nr(124); + + test_invalidation( + RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), + [frame_123].into(), + [frame_122].into(), + [frame_124].into(), + ); + + test_invalidation( + RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), + [frame_123].into(), + timeless, + [frame_124].into(), + ); +} + +// Test the following scenario: +// ```py +// rr.log("points", rr.Points3D([1, 2, 3]), static=True) +// +// # Do first query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[] +// +// rr.set_time(2) +// rr.log_components("points", rr.components.MyColor(0xFF0000)) +// +// # Do second query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0xFF0000] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x0000FF)) +// +// # Do third query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x0000FF] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x00FF00)) +// +// # Do fourth query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x00FF00] +// ``` +#[test] +fn invalidation_of_future_optionals() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + let frame2 = [build_frame_nr(2)]; + let frame3 = [build_frame_nr(3)]; + + let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); + + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, points1.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let expected_points = &[ + ((TimeInt::STATIC, row1.row_id()), points1.as_slice()), // + ]; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors2.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_colors = &[ + ( + (TimeInt::new_temporal(2), row2.row_id()), + colors2.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors3 = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors3.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_colors = &[ + ( + (TimeInt::new_temporal(2), row2.row_id()), + colors2.as_slice(), + ), // + ( + (TimeInt::new_temporal(3), row3.row_id()), + colors3.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors4 = vec![MyColor::from_rgb(0, 255, 0)]; + let row4 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors4.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let expected_colors = &[ + ( + (TimeInt::new_temporal(2), row2.row_id()), + colors2.as_slice(), + ), // + ( + (TimeInt::new_temporal(3), row3.row_id()), + colors3.as_slice(), + ), // + ( + (TimeInt::new_temporal(3), row4.row_id()), + colors4.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); +} + +#[test] +fn invalidation_static() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + + let frame0 = [build_frame_nr(TimeInt::ZERO)]; + let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); + + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 2, + points1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let expected_points = &[ + ((TimeInt::STATIC, row1.row_id()), points1.as_slice()), // + ]; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_colors = &[ + ((TimeInt::STATIC, row2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors3 = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors3.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_colors = &[ + ((TimeInt::STATIC, row3.row_id()), colors3.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); +} + +// --- + +fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { + caches.on_events(&[store.insert_row(row).unwrap()]); +} + +fn query_and_compare( + caches: &Caches, + store: &DataStore, + query: &RangeQuery, + entity_path: &EntityPath, + expected_all_points_indexed: &[((TimeInt, RowId), &[MyPoint])], + expected_all_colors_indexed: &[((TimeInt, RowId), &[MyColor])], +) { + re_log::setup_logging(); + + let resolver = PromiseResolver::default(); + + for _ in 0..3 { + let cached = caches.range( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let cached_all_points = cached + .get_required(MyPoint::name()) + .unwrap() + .to_dense::(&resolver); + assert!(matches!( + cached_all_points.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())), + )); + let cached_all_points_indexed = cached_all_points.range_indexed(); + + let cached_all_colors = cached + .get_or_empty(MyColor::name()) + .to_dense::(&resolver); + assert!(matches!( + cached_all_colors.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())), + )); + let cached_all_colors_indexed = cached_all_colors.range_indexed(); + + // eprintln!("{query:?}"); + // eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!( + expected_all_points_indexed, + cached_all_points_indexed + .map(|(index, data)| (*index, data)) + .collect_vec(), + ); + + similar_asserts::assert_eq!( + expected_all_colors_indexed, + cached_all_colors_indexed + .map(|(index, data)| (*index, data)) + .collect_vec(), + ); + } +} From 1bd6cd70ee5748bd70e3965e40829fce69922ab3 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 24 Apr 2024 16:33:48 +0200 Subject: [PATCH 8/9] no need for lint bypass anymore --- scripts/lint.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/lint.py b/scripts/lint.py index 60584707c615..5cf77fb98bd2 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -979,9 +979,6 @@ def lint_file(filepath: str, args: Any) -> int: def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: """Make sure ARCHITECTURE.md talks about every single crate we have.""" - # These crates will replace existing ones and won't ever be published as-is. - tmp_crates = ["re_query"] - crates_dir = Path("crates") architecture_md_file = Path("ARCHITECTURE.md") @@ -1002,9 +999,6 @@ def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: if crate_name in listed_crates: del listed_crates[crate_name] - if should_ignore(crate) or crate.name in tmp_crates: - continue - if not re.search(r"\b" + crate_name + r"\b", architecture_md): print(f"{architecture_md_file}: missing documentation for crate {crate.name}") error_count += 1 From bbabfbfd031d4fd20e607fbce24bb45b889ca610 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 12:46:16 +0200 Subject: [PATCH 9/9] post-rebase codegen --- .../src/latest_at/to_archetype/background.rs | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 crates/re_query/src/latest_at/to_archetype/background.rs diff --git a/crates/re_query/src/latest_at/to_archetype/background.rs b/crates/re_query/src/latest_at/to_archetype/background.rs new file mode 100644 index 000000000000..319228ffb294 --- /dev/null +++ b/crates/re_query/src/latest_at/to_archetype/background.rs @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] + +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for LatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::blueprint::components::BackgroundKind; + let kind = match self.get_required(::name()) { + Ok(kind) => kind, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let kind = match kind.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Color; + let color = if let Some(color) = self.get(::name()) { + match color.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::blueprint::archetypes::Background { kind, color }; + + PromiseResult::Ready(Ok(arch)) + } +}