Deadline QoS Policy
The Deadline policy specifies the maximum time between data updates.
Purpose
Deadline monitors data freshness:
- Writers commit to publishing within the deadline period
- Readers expect samples within the deadline period
- Violations trigger callbacks for handling
Configuration
use hdds::prelude::*;
use std::time::Duration;
// Writer commits to 100ms update rate
let writer_qos = DataWriterQos::default()
.deadline(Deadline::new(Duration::from_millis(100)));
// Reader expects updates within 100ms
let reader_qos = DataReaderQos::default()
.deadline(Deadline::new(Duration::from_millis(100)));
Default Value
Default is infinite (no deadline monitoring):
let qos = DataWriterQos::default();
// deadline = Duration::MAX (infinite)
Compatibility Rules
Writer deadline must be less than or equal to Reader deadline (writer must be faster):
| Writer | Reader | Match? |
|---|---|---|
| 100 ms | 200 ms | ✅ Yes |
| 100 ms | 100 ms | ✅ Yes |
| 200 ms | 100 ms | ❌ No |
| Infinite | 100 ms | ❌ No |
| 100 ms | Infinite | ✅ Yes |
Rule: Writer.deadline ≤ Reader.deadline
Deadline Tracking
Writer Side
The writer tracks time since last write() call:
let writer = publisher.create_writer_with_qos(&topic, writer_qos)?;
// Start deadline timer
writer.write(&sample)?;
// If no write within 100ms → deadline missed
Reader Side
The reader tracks time since last sample received per instance:
let reader = subscriber.create_reader_with_qos(&topic, reader_qos)?;
// Deadline timer starts when first sample received
// If no new sample within 100ms → deadline missed
Handling Violations
Listener Callbacks
use hdds::prelude::*;
struct MyListener;
impl DataWriterListener for MyListener {
fn on_offered_deadline_missed(
&mut self,
writer: &DataWriter<SensorData>,
status: OfferedDeadlineMissedStatus,
) {
eprintln!(
"Writer missed deadline! Total: {}, Change: {}",
status.total_count,
status.total_count_change
);
}
}
impl DataReaderListener for MyListener {
fn on_requested_deadline_missed(
&mut self,
reader: &DataReader<SensorData>,
status: RequestedDeadlineMissedStatus,
) {
eprintln!(
"Reader deadline missed for instance {:?}",
status.last_instance_handle
);
}
}
Status Polling
// Check deadline status manually
let status = writer.get_offered_deadline_missed_status()?;
if status.total_count_change > 0 {
println!("Missed {} deadlines", status.total_count_change);
}
Per-Instance Deadline
For keyed topics, deadline is tracked per instance:
// Topic: SensorReading with @key sensor_id
let reader_qos = DataReaderQos::default()
.deadline(Deadline::new(Duration::from_millis(500)));
// Each sensor_id has its own deadline timer:
// sensor_1: last_update=T1, deadline at T1+500ms
// sensor_2: last_update=T2, deadline at T2+500ms
Use Cases
Periodic Sensor Data
// Sensor publishes at 10 Hz, reader expects updates
let deadline = Duration::from_millis(100); // 10 Hz
let writer_qos = DataWriterQos::default()
.deadline(Deadline::new(deadline))
.reliability(Reliability::BestEffort);
let reader_qos = DataReaderQos::default()
.deadline(Deadline::new(deadline * 2)) // 200ms tolerance
.reliability(Reliability::BestEffort);
Heartbeat Monitoring
// Monitor node liveness with heartbeats
let heartbeat_period = Duration::from_secs(1);
let tolerance = Duration::from_secs(3);
let writer_qos = DataWriterQos::default()
.deadline(Deadline::new(heartbeat_period));
let reader_qos = DataReaderQos::default()
.deadline(Deadline::new(tolerance));
Control Loop
// Real-time control at 1 kHz
let control_period = Duration::from_micros(1000); // 1 ms
let writer_qos = DataWriterQos::default()
.deadline(Deadline::new(control_period))
.reliability(Reliability::BestEffort)
.history(History::KeepLast { depth: 1 });
Best Practices
- Set reader deadline >= writer deadline
- Add tolerance for network jitter (2-3× expected period)
- Use listeners for real-time alerting
- Monitor deadline statistics in production
// Good: Reader has tolerance
let writer_deadline = Duration::from_millis(100);
let reader_deadline = Duration::from_millis(150); // 50% tolerance
// Bad: Reader too strict
let writer_deadline = Duration::from_millis(100);
let reader_deadline = Duration::from_millis(100); // No tolerance!
Interaction with Other Policies
Deadline + Liveliness
Both monitor entity health, but differently:
| Policy | Monitors | Granularity |
|---|---|---|
| Deadline | Data updates | Per instance |
| Liveliness | Writer existence | Per writer |
// Combined monitoring
let qos = DataWriterQos::default()
.deadline(Deadline::new(Duration::from_millis(100))) // Data rate
.liveliness(Liveliness::ManualByTopic {
lease_duration: Duration::from_secs(10), // Writer alive
});
Deadline + Reliability
| Deadline | Reliability | Behavior |
|---|---|---|
| Set | BestEffort | Deadline may miss on network loss |
| Set | Reliable | Retransmissions help meet deadline |
Performance Notes
- Deadline checking adds minimal CPU overhead (~1 μs per sample)
- Per-instance tracking requires memory per active instance
- High-frequency deadlines (< 1ms) require careful tuning
Next Steps
- Liveliness - Writer health monitoring
- Overview - All QoS policies