Skip to content

Commit 32f3090

Browse files
authored
Make last updated timestamp robust (#11807)
1 parent 130db76 commit 32f3090

File tree

10 files changed

+338
-63
lines changed

10 files changed

+338
-63
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9381,6 +9381,7 @@ dependencies = [
93819381
"re_types",
93829382
"re_types_core",
93839383
"tempfile",
9384+
"tokio",
93849385
"tonic",
93859386
"url",
93869387
]

crates/store/re_protos/src/v1alpha1/rerun.cloud.v1alpha1.ext.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ impl From<EntryDetails> for crate::cloud::v1alpha1::EntryDetails {
572572

573573
// --- DatasetDetails ---
574574

575-
#[derive(Debug, Clone, Default)]
575+
#[derive(Debug, Clone, Default, PartialEq, Eq)]
576576
pub struct DatasetDetails {
577577
pub blueprint_dataset: Option<EntryId>,
578578
pub default_blueprint: Option<PartitionId>,

crates/store/re_redap_tests/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ insta.workspace = true
4343
itertools.workspace = true
4444
prost-types.workspace = true
4545
tempfile.workspace = true
46+
tokio.workspace = true
4647
tonic.workspace = true
4748
url.workspace = true
4849

crates/store/re_redap_tests/src/tests/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ define_redap_tests! {
9494
register_partition::register_and_scan_simple_dataset_with_properties,
9595
register_partition::register_and_scan_simple_dataset_with_properties_out_of_order,
9696
register_partition::register_with_prefix,
97+
register_partition::register_partition_bumps_timestamp,
9798
update_entry::update_entry_tests,
99+
update_entry::update_entry_bumps_timestamp,
98100
write_table::write_table
99101
}

crates/store/re_redap_tests/src/tests/register_partition.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,89 @@ pub async fn register_and_scan_empty_dataset(service: impl RerunCloudService) {
313313
scan_dataset_manifest_and_snapshot(&service, dataset_name, "empty").await;
314314
}
315315

316+
pub async fn register_partition_bumps_timestamp(service: impl RerunCloudService) {
317+
async fn get_dataset_updated_at_nanos(
318+
service: &impl RerunCloudService,
319+
dataset_name: &str,
320+
) -> i64 {
321+
service
322+
.read_dataset_entry(
323+
tonic::Request::new(ReadDatasetEntryRequest {})
324+
.with_entry_name(dataset_name)
325+
.unwrap(),
326+
)
327+
.await
328+
.unwrap()
329+
.into_inner()
330+
.dataset
331+
.unwrap()
332+
.details
333+
.as_ref()
334+
.unwrap()
335+
.updated_at
336+
.as_ref()
337+
.map(|ts| ts.seconds * 1_000_000_000 + ts.nanos as i64)
338+
.unwrap()
339+
}
340+
341+
let dataset_name = "timestamp_test_dataset";
342+
343+
//
344+
// Create a dataset
345+
//
346+
347+
service.create_dataset_entry_with_name(dataset_name).await;
348+
349+
let initial_updated_at_nanos = get_dataset_updated_at_nanos(&service, dataset_name).await;
350+
351+
// Small delay to ensure timestamp difference
352+
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
353+
354+
//
355+
// Register a partition - this should update the timestamp
356+
//
357+
358+
let data_sources_def = DataSourcesDefinition::new_with_tuid_prefix(
359+
1,
360+
[LayerDefinition::simple("partition1", &["my/entity"])],
361+
);
362+
363+
service
364+
.register_with_dataset_name(dataset_name, data_sources_def.to_data_sources())
365+
.await;
366+
367+
let after_register_updated_at_nanos =
368+
get_dataset_updated_at_nanos(&service, dataset_name).await;
369+
370+
assert!(
371+
after_register_updated_at_nanos > initial_updated_at_nanos,
372+
"Timestamp should be updated after registering partition. Initial: {initial_updated_at_nanos}, After register: {after_register_updated_at_nanos}"
373+
);
374+
375+
// Small delay to ensure timestamp difference
376+
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
377+
378+
//
379+
// Register another layer to the same partition - this should also update the timestamp
380+
//
381+
382+
let layer_data_sources_def = DataSourcesDefinition::new_with_tuid_prefix(
383+
2,
384+
[LayerDefinition::simple("partition1", &["another/entity"]).layer_name("layer2")],
385+
);
386+
387+
service
388+
.register_with_dataset_name(dataset_name, layer_data_sources_def.to_data_sources())
389+
.await;
390+
391+
let after_layer_updated_at_nanos = get_dataset_updated_at_nanos(&service, dataset_name).await;
392+
393+
assert!(
394+
after_layer_updated_at_nanos > after_register_updated_at_nanos,
395+
"Timestamp should be updated after adding a layer. After register: {after_register_updated_at_nanos}, After layer: {after_layer_updated_at_nanos}"
396+
);
397+
}
398+
316399
// ---
317400

318401
async fn scan_partition_table_and_snapshot(

crates/store/re_redap_tests/src/tests/update_entry.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,71 @@ pub async fn update_entry_tests(service: impl RerunCloudService) {
179179
);
180180
}
181181

182+
pub async fn update_entry_bumps_timestamp(service: impl RerunCloudService) {
183+
//
184+
// Create a dataset
185+
//
186+
187+
let dataset_name = "timestamp_test_dataset";
188+
let dataset_entry = create_dataset_entry(&service, dataset_name).await.unwrap();
189+
190+
let dataset_id = dataset_entry.details.id;
191+
let initial_updated_at = dataset_entry.details.updated_at;
192+
193+
// Small delay to ensure timestamp difference
194+
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
195+
196+
//
197+
// Rename the dataset - this should update the timestamp
198+
//
199+
200+
let new_name = "renamed_dataset";
201+
let response = update_entry(
202+
&service,
203+
UpdateEntryRequest {
204+
id: dataset_id,
205+
entry_details_update: EntryDetailsUpdate {
206+
name: Some(new_name.to_owned()),
207+
},
208+
},
209+
)
210+
.await
211+
.unwrap();
212+
213+
let after_rename_updated_at = response.entry_details.updated_at;
214+
215+
assert!(
216+
after_rename_updated_at > initial_updated_at,
217+
"Timestamp should be updated after rename. Initial: {initial_updated_at:?}, After rename: {after_rename_updated_at:?}"
218+
);
219+
220+
// Small delay to ensure timestamp difference
221+
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
222+
223+
//
224+
// Rename to the same name
225+
//
226+
227+
let response2 = update_entry(
228+
&service,
229+
UpdateEntryRequest {
230+
id: dataset_id,
231+
entry_details_update: EntryDetailsUpdate {
232+
name: Some(new_name.to_owned()),
233+
},
234+
},
235+
)
236+
.await
237+
.unwrap();
238+
239+
let after_second_rename_updated_at = response2.entry_details.updated_at;
240+
241+
assert_eq!(
242+
after_second_rename_updated_at, after_rename_updated_at,
243+
"Timestamp should NOT be updated when renaming to the same name. After first rename: {after_rename_updated_at:?}, After second rename: {after_second_rename_updated_at:?}"
244+
);
245+
}
246+
182247
// ---
183248

184249
async fn create_dataset_entry(

0 commit comments

Comments
 (0)