jhelovuo / RustDDS

Rust implementation of Data Distribution Service

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Sample source timestamp not preserved for separate domain participants

samcarey opened this issue · comments

I am trying to read the original source timestamp of a sample written from from a different participant than the reader. Unfortunately, this only seems to work if both reader and writer are created from the same participant.

Failing test:

use anyhow::Result;
use rustdds::{
    policy::{Durability, History, Reliability},
    DomainParticipant, QosPolicyBuilder, Timestamp, TopicKind,
};
use std::{thread, time::Duration};

#[derive(serde::Serialize, serde::Deserialize, Debug)]
struct TestType;

#[test]
fn timestamp() -> Result<()> {
    let participant = DomainParticipant::new(0)?;
    let qos = QosPolicyBuilder::new()
        .history(History::KeepAll)
        .reliability(Reliability::Reliable {
            max_blocking_time: Duration::from_secs(0).into(),
        })
        .durability(Durability::TransientLocal)
        .build();
    let writer = participant
        .create_publisher(&qos)?
        .create_datawriter_no_key_cdr::<TestType>(
            &participant.create_topic(
                "test".to_string(),
                "TestType".to_string(),
                &qos,
                TopicKind::NoKey,
            )?,
            None,
        )?;
    let participant2 = DomainParticipant::new(0)?;
    let mut reader = participant2
        .create_subscriber(&qos)?
        .create_datareader_no_key_cdr::<TestType>(
            &participant.create_topic(
                "test".to_string(),
                "TestType".to_string(),
                &qos,
                TopicKind::NoKey,
            )?,
            None,
        )?;
    let timestamp = Timestamp::now();
    writer.write(TestType, Some(timestamp))?;
    thread::sleep(Duration::from_secs(3));
    loop {
        if let Ok(Some(sample)) = reader.take_next_sample() {
            assert_eq!(timestamp, sample.sample_info().source_timestamp().unwrap());
            break;
        }
        thread::sleep(Duration::from_millis(100));
    }
    Ok(())
}

Result:

panicked at 'assertion failed: `(left == right)`
  left: `Timestamp { seconds: 1696274132, fraction: 1145457469 }`,
 right: `Timestamp { seconds: 1696274135, fraction: 1936904837 }`

As you can see, the resulting "source_timestamp" is reported to be just over 3 seconds after the original, which is the amount of time we slept between writing and reading (and it always nearly matches for different durations). This suggests that the source_timestamp is actually being set at the time of reading instead of writing.

If you replace

participant2
        .create_subscriber(&qos)?`

with

participant
        .create_subscriber(&qos)?`

in the above test, such that both reader and writer are from the same domain participant, it will pass.

Is this a bug?

Yes, that was a good catch!

The processing path for DATA retransmits always inserted the current (retransmit) time as source timestamp, instead of the timestamp specified by the application. There was even a todo-marker indicating a missing bit of implementation in the code.

Please check out the latest master version and see it fixes the problem for you.

Is it ok to you to include your test case into RustDDS unit tests?

Fixed in version 0.8.6.