Skip to main content

History QoS Policy

The History policy controls how many samples are kept in the writer/reader queue.

Values

ValueDescriptionMemory
KeepLast(N)Keep only the N most recent samples per instanceBounded
KeepAllKeep all samples until acknowledgedUnbounded*

*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

ScenarioRecommended Depth
Real-time control (1 kHz+)1-5
Periodic status (10 Hz)10-50
Event notifications100+ or KeepAll
Configuration data1
Logs/auditKeepAll

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

HistoryReliabilityBehavior
KeepLast(1)BestEffortFastest, may lose samples
KeepLast(N)ReliableRetransmit from last N samples
KeepAllReliableFull reliability, memory grows

History + Durability

HistoryDurabilityCache for Late Joiners
KeepLast(N)TransientLocalLast N samples
KeepAllTransientLocalAll cached samples
KeepLast(N)PersistentLast 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:

  • KeepLast depth must be > 0
  • KeepAll requires ResourceLimits to be set
  • max_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

  1. Use KeepLast(1) for real-time control loops
  2. Match writer/reader depths to avoid overflow
  3. Set ResourceLimits with KeepAll to prevent OOM
  4. Monitor queue sizes in production

Next Steps