History QoS Policy
The History policy controls how many samples are kept in the writer/reader queue.
Values
| Value | Description | Memory |
|---|---|---|
KeepLast(N) | Keep only the N most recent samples per instance | Bounded |
KeepAll | Keep all samples until acknowledged | Unbounded* |
*Bounded by ResourceLimits
Keep Last
Maintains a fixed-size queue of the N most recent samples per instance.
use hdds::prelude::*;
// Keep last 10 samples
let qos = DataWriterQos::default()
.history(History::KeepLast { depth: 10 });
Behavior:
- When queue is full, oldest sample is replaced
- No blocking on write (unless reliable + buffer full)
- Memory usage is predictable:
depth × sample_size × instances
Use cases:
- Sensor data (latest reading matters most)
- State updates (only current state needed)
- High-frequency data with bounded memory
Keep All
Maintains all samples until delivered and acknowledged.
use hdds::prelude::*;
// Keep all samples (bounded by resource limits)
let qos = DataWriterQos::default()
.history(History::KeepAll)
.resource_limits(ResourceLimits {
max_samples: 100_000,
max_instances: 1,
max_samples_per_instance: 100_000,
max_quota_bytes: 100 * 1024 * 1024, // 100 MB
});
Behavior:
- Samples accumulate until read/acknowledged
- Memory grows with unread samples
- Must configure ResourceLimits to prevent OOM
- Writer blocks when limits reached (if reliable)
Use cases:
- Command queues (every command matters)
- Event logs (no sample loss)
- Reliable data transfer
Depth Selection Guidelines
| Scenario | Recommended Depth |
|---|---|
| Real-time control (1 kHz+) | 1-5 |
| Periodic status (10 Hz) | 10-50 |
| Event notifications | 100+ or KeepAll |
| Configuration data | 1 |
| Logs/audit | KeepAll |
Writer vs Reader History
Both writers and readers have History policies:
Writer History
Controls retransmission buffer for reliable communication:
// Writer keeps 100 samples for retransmission
let writer_qos = DataWriterQos::default()
.reliability(Reliability::Reliable {
max_blocking_time: Duration::from_secs(1),
})
.history(History::KeepLast { depth: 100 });
Reader History
Controls samples available for read() and take():
// Reader keeps 50 samples available
let reader_qos = DataReaderQos::default()
.history(History::KeepLast { depth: 50 });
Instance Behavior
For keyed topics, history is per instance:
// Topic: SensorReading with @key sensor_id
let qos = DataWriterQos::default()
.history(History::KeepLast { depth: 5 })
.resource_limits(ResourceLimits {
max_instances: 100,
max_samples_per_instance: 5,
max_samples: 500, // 100 × 5
..Default::default()
});
// Each sensor_id gets its own 5-sample queue:
// sensor_1: [s1, s2, s3, s4, s5]
// sensor_2: [s1, s2, s3, s4, s5]
// ...
Memory Calculation
Keep Last
Memory = depth × max_instances × avg_sample_size
Example:
- Depth: 10
- Instances: 100
- Sample size: 1 KB
- Memory: 1 MB
Keep All
Memory = max_samples × avg_sample_size
Example:
- Max samples: 100,000
- Sample size: 1 KB
- Memory: 100 MB
Interaction with Other Policies
History + Reliability
| History | Reliability | Behavior |
|---|---|---|
| KeepLast(1) | BestEffort | Fastest, may lose samples |
| KeepLast(N) | Reliable | Retransmit from last N samples |
| KeepAll | Reliable | Full reliability, memory grows |
History + Durability
| History | Durability | Cache for Late Joiners |
|---|---|---|
| KeepLast(N) | TransientLocal | Last N samples |
| KeepAll | TransientLocal | All cached samples |
| KeepLast(N) | Persistent | Last N on disk |
Examples
High-Frequency Sensor
// 1 kHz sensor, only latest value matters
let qos = DataWriterQos::default()
.reliability(Reliability::BestEffort)
.history(History::KeepLast { depth: 1 });
Command Queue
// All commands must be executed
let writer_qos = DataWriterQos::default()
.reliability(Reliability::Reliable {
max_blocking_time: Duration::from_secs(30),
})
.history(History::KeepAll)
.resource_limits(ResourceLimits {
max_samples: 10_000,
..Default::default()
});
State Synchronization
// Keep last 10 states per entity
let qos = DataWriterQos::default()
.durability(Durability::TransientLocal)
.reliability(Reliability::Reliable {
max_blocking_time: Duration::from_secs(1),
})
.history(History::KeepLast { depth: 10 });
Event Buffer
// Buffer events for slow readers
let writer_qos = DataWriterQos::default()
.reliability(Reliability::Reliable {
max_blocking_time: Duration::from_secs(5),
})
.history(History::KeepLast { depth: 1000 });
let reader_qos = DataReaderQos::default()
.reliability(Reliability::Reliable)
.history(History::KeepLast { depth: 100 });
Validation Rules
HDDS validates history configuration:
KeepLastdepth must be > 0KeepAllrequires ResourceLimits to be setmax_samples >= max_samples_per_instance × max_instances
// Invalid: depth 0
let qos = DataWriterQos::default()
.history(History::KeepLast { depth: 0 });
// Error: History depth must be > 0
Performance Tips
- Use KeepLast(1) for real-time control loops
- Match writer/reader depths to avoid overflow
- Set ResourceLimits with KeepAll to prevent OOM
- Monitor queue sizes in production
Next Steps
- Deadline - Update frequency requirements
- Reliability - Delivery guarantees