@@ -9,41 +9,30 @@ use arrow::array::{
9
9
use arrow:: datatypes:: { DataType , Field , Schema , TimeUnit } ;
10
10
use datafusion:: prelude:: SessionContext ;
11
11
use nohash_hasher:: IntSet ;
12
- use re_chunk_store:: Chunk ;
13
- use re_chunk_store:: external:: re_chunk:: external:: re_byte_size:: SizeBytes as _;
14
- use re_entity_db:: EntityDb ;
15
- use re_entity_db:: external:: re_query:: StorageEngine ;
12
+ use tokio_stream:: StreamExt as _;
13
+ use tonic:: { Code , Status } ;
14
+
15
+ use re_byte_size:: SizeBytes as _;
16
+ use re_chunk_store:: { Chunk , ChunkStore , ChunkStoreConfig , ChunkStoreHandle } ;
16
17
use re_log_encoding:: codec:: wire:: { decoder:: Decode as _, encoder:: Encode as _} ;
17
- use re_log_types:: external:: re_types_core:: { ChunkId , Loggable as _} ;
18
18
use re_log_types:: { EntityPath , EntryId , StoreId , StoreKind } ;
19
- use re_protos:: cloud:: v1alpha1:: ext:: GetChunksRequest ;
20
- use re_protos:: cloud:: v1alpha1:: {
21
- EntryDetails , GetChunksResponse , GetDatasetSchemaResponse , GetPartitionTableSchemaResponse ,
22
- QueryDatasetResponse , ScanPartitionTableResponse , ScanTableResponse ,
23
- } ;
24
- use re_protos:: headers:: RerunHeadersExtractorExt as _;
25
- use re_protos:: { cloud:: v1alpha1:: RegisterWithDatasetResponse , common:: v1alpha1:: ext:: PartitionId } ;
26
19
use re_protos:: {
27
- cloud:: v1alpha1:: ext,
28
- cloud:: v1alpha1:: ext:: {
29
- CreateDatasetEntryResponse , ReadDatasetEntryResponse , ReadTableEntryResponse ,
30
- } ,
31
- } ;
32
- use re_protos:: {
33
- cloud:: v1alpha1:: rerun_cloud_service_server:: RerunCloudService ,
34
20
cloud:: v1alpha1:: {
35
- FetchTaskOutputRequest , FetchTaskOutputResponse , QueryTasksOnCompletionRequest ,
36
- QueryTasksRequest , QueryTasksResponse ,
21
+ DeleteEntryResponse , EntryDetails , EntryKind , FetchTaskOutputRequest ,
22
+ FetchTaskOutputResponse , GetChunksResponse , GetDatasetSchemaResponse ,
23
+ GetPartitionTableSchemaResponse , QueryDatasetResponse , QueryTasksOnCompletionRequest ,
24
+ QueryTasksRequest , QueryTasksResponse , RegisterTableRequest , RegisterTableResponse ,
25
+ RegisterWithDatasetResponse , ScanPartitionTableResponse , ScanTableResponse ,
26
+ ext:: {
27
+ self , CreateDatasetEntryResponse , GetChunksRequest , ReadDatasetEntryResponse ,
28
+ ReadTableEntryResponse ,
29
+ } ,
30
+ rerun_cloud_service_server:: RerunCloudService ,
37
31
} ,
32
+ common:: v1alpha1:: ext:: { IfDuplicateBehavior , PartitionId } ,
33
+ headers:: RerunHeadersExtractorExt as _,
38
34
} ;
39
- use re_protos:: {
40
- cloud:: v1alpha1:: {
41
- DeleteEntryResponse , EntryKind , RegisterTableRequest , RegisterTableResponse ,
42
- } ,
43
- common:: v1alpha1:: ext:: IfDuplicateBehavior ,
44
- } ;
45
- use tokio_stream:: StreamExt as _;
46
- use tonic:: { Code , Status } ;
35
+ use re_types_core:: { ChunkId , Loggable as _} ;
47
36
48
37
use crate :: store:: { Dataset , InMemoryStore , Table } ;
49
38
@@ -111,7 +100,7 @@ impl RerunCloudHandler {
111
100
& self ,
112
101
dataset_id : EntryId ,
113
102
mut partition_ids : Vec < PartitionId > ,
114
- ) -> Result < Vec < ( PartitionId , StorageEngine ) > , tonic:: Status > {
103
+ ) -> Result < Vec < ( PartitionId , ChunkStoreHandle ) > , tonic:: Status > {
115
104
let store = self . store . read ( ) . await ;
116
105
let dataset = store. dataset ( dataset_id) . ok_or_else ( || {
117
106
tonic:: Status :: not_found ( format ! ( "Entry with ID {dataset_id} not found" ) )
@@ -125,19 +114,13 @@ impl RerunCloudHandler {
125
114
. into_iter ( )
126
115
. map ( |partition_id| {
127
116
dataset
128
- . partition ( & partition_id)
117
+ . partition_store_handle ( & partition_id)
129
118
. ok_or_else ( || {
130
119
tonic:: Status :: not_found ( format ! (
131
120
"Partition with ID {partition_id} not found"
132
121
) )
133
122
} )
134
- . map ( |partition| {
135
- #[ expect( unsafe_code) ]
136
- // Safety: no viewer is running, and we've locked the store for the duration
137
- // of the handler already.
138
- unsafe { partition. storage_engine_raw ( ) } . clone ( )
139
- } )
140
- . map ( |storage_engine| ( partition_id, storage_engine) )
123
+ . map ( |store_handle| ( partition_id, store_handle. clone ( ) ) )
141
124
} )
142
125
. collect :: < Result < Vec < _ > , _ > > ( )
143
126
}
@@ -560,7 +543,7 @@ impl RerunCloudService for RerunCloudHandler {
560
543
561
544
let mut request = request. into_inner ( ) ;
562
545
563
- let mut entity_dbs = HashMap :: new ( ) ;
546
+ let mut chunk_stores = HashMap :: new ( ) ;
564
547
565
548
while let Some ( chunk_msg) = request. next ( ) . await {
566
549
let chunk_msg = chunk_msg?;
@@ -589,16 +572,15 @@ impl RerunCloudService for RerunCloudHandler {
589
572
tonic:: Status :: internal ( format ! ( "error decoding chunk from record batch: {err:#}" ) )
590
573
} ) ?) ;
591
574
592
- entity_dbs
575
+ chunk_stores
593
576
. entry ( partition_id. clone ( ) )
594
577
. or_insert_with ( || {
595
- EntityDb :: new ( StoreId :: new (
596
- StoreKind :: Recording ,
597
- entry_id. to_string ( ) ,
598
- partition_id. id ,
599
- ) )
578
+ ChunkStore :: new (
579
+ StoreId :: new ( StoreKind :: Recording , entry_id. to_string ( ) , partition_id. id ) ,
580
+ ChunkStoreConfig :: CHANGELOG_DISABLED ,
581
+ )
600
582
} )
601
- . add_chunk ( & chunk)
583
+ . insert_chunk ( & chunk)
602
584
. map_err ( |err| {
603
585
tonic:: Status :: internal ( format ! ( "error adding chunk to store: {err:#}" ) )
604
586
} ) ?;
@@ -610,8 +592,8 @@ impl RerunCloudService for RerunCloudHandler {
610
592
} ;
611
593
612
594
#[ expect( clippy:: iter_over_hash_type) ]
613
- for ( entity_path, entity_db ) in entity_dbs {
614
- dataset. add_partition ( entity_path, entity_db ) ;
595
+ for ( entity_path, chunk_store ) in chunk_stores {
596
+ dataset. add_partition ( entity_path, ChunkStoreHandle :: new ( chunk_store ) ) ;
615
597
}
616
598
617
599
Ok ( tonic:: Response :: new (
@@ -767,9 +749,8 @@ impl RerunCloudService for RerunCloudHandler {
767
749
let storage_engines = self . get_storage_engines ( entry_id, partition_ids) . await ?;
768
750
769
751
let stream = futures:: stream:: iter ( storage_engines. into_iter ( ) . map (
770
- move |( partition_id, storage_engine) | {
771
- let storage_read = storage_engine. read ( ) ;
772
- let chunk_store = storage_read. store ( ) ;
752
+ move |( partition_id, store_handle) | {
753
+ let chunk_store = store_handle. read ( ) ;
773
754
let num_rows = chunk_store. num_chunks ( ) ;
774
755
775
756
let mut chunk_partition_id = Vec :: with_capacity ( num_rows) ;
@@ -940,21 +921,20 @@ impl RerunCloudService for RerunCloudHandler {
940
921
let storage_engines = self . get_storage_engines ( entry_id, partition_ids) . await ?;
941
922
942
923
let stream = futures:: stream:: iter ( storage_engines. into_iter ( ) . map (
943
- move |( partition_id, storage_engine ) | {
924
+ move |( partition_id, store_handle ) | {
944
925
let compression = re_log_encoding:: Compression :: Off ;
945
926
let store_id = StoreId :: new (
946
927
StoreKind :: Recording ,
947
928
entry_id. to_string ( ) ,
948
929
partition_id. id . as_str ( ) ,
949
930
) ;
950
931
951
- let arrow_msgs: Result < Vec < _ > , _ > = storage_engine
932
+ let arrow_msgs: Result < Vec < _ > , _ > = store_handle
952
933
// NOTE: ⚠️This is super cursed ⚠️The underlying lock is synchronous: the only
953
934
// reason this doesn't deadlock is because we collect() at the end of this mapping,
954
935
// before the overarching stream ever gets a chance to yield.
955
936
// Make sure it stays that way.
956
937
. read ( )
957
- . store ( )
958
938
. iter_chunks ( )
959
939
. filter ( |chunk| {
960
940
entity_paths. is_empty ( ) || entity_paths. contains ( chunk. entity_path ( ) )
@@ -1036,7 +1016,7 @@ impl RerunCloudService for RerunCloudHandler {
1036
1016
1037
1017
// get storage engines only for the partitions we actually need
1038
1018
let store = self . store . read ( ) . await ;
1039
- let storage_engines : std:: collections:: HashMap < _ , _ > = store
1019
+ let store_handles : std:: collections:: HashMap < _ , _ > = store
1040
1020
. iter_datasets ( )
1041
1021
. flat_map ( |dataset| {
1042
1022
let dataset_id = dataset. id ( ) ;
@@ -1046,13 +1026,9 @@ impl RerunCloudService for RerunCloudHandler {
1046
1026
. iter ( )
1047
1027
. any ( |( _, pid) | pid == & partition_id)
1048
1028
{
1049
- dataset. partition ( & partition_id) . map ( |partition| {
1050
- #[ expect( unsafe_code) ]
1051
- // Safety: no viewer is running, and we've locked the store for the duration
1052
- // of the handler already.
1053
- let storage_engine = unsafe { partition. storage_engine_raw ( ) } . clone ( ) ;
1054
- ( partition_id, ( dataset_id, storage_engine) )
1055
- } )
1029
+ dataset
1030
+ . partition_store_handle ( & partition_id)
1031
+ . map ( |store_handle| ( partition_id, ( dataset_id, store_handle. clone ( ) ) ) )
1056
1032
} else {
1057
1033
None
1058
1034
}
@@ -1065,15 +1041,13 @@ impl RerunCloudService for RerunCloudHandler {
1065
1041
let compression = re_log_encoding:: Compression :: Off ;
1066
1042
1067
1043
for ( chunk_id, partition_id) in chunk_partition_pairs {
1068
- let ( dataset_id, storage_engine) =
1069
- storage_engines. get ( & partition_id) . ok_or_else ( || {
1070
- tonic:: Status :: internal ( format ! (
1071
- "Storage engine not found for partition {partition_id}"
1072
- ) )
1073
- } ) ?;
1044
+ let ( dataset_id, store_handle) = store_handles. get ( & partition_id) . ok_or_else ( || {
1045
+ tonic:: Status :: internal ( format ! (
1046
+ "Storage engine not found for partition {partition_id}"
1047
+ ) )
1048
+ } ) ?;
1074
1049
1075
- let storage_read = storage_engine. read ( ) ;
1076
- let chunk_store = storage_read. store ( ) ;
1050
+ let chunk_store = store_handle. read ( ) ;
1077
1051
1078
1052
if let Some ( chunk) = chunk_store. chunk ( & chunk_id) {
1079
1053
let store_id = StoreId :: new (
0 commit comments