Skip to content

Partitions filter which retained samples a late joiner replays

Rule 20 · applies to publishers and subscribers · Back to all rules

Wastes effort. Retained history is replayed only within the matching partition, so a late joiner in a different partition gets nothing.

If you set Durability = TRANSIENT_LOCAL or stronger together with Partition names are set (non-empty)
Wastes resources
  • Settings involved: Partition and Durability
  • What QoS Guard checks: [DURABL ≥ TRAN_LOCAL] ∧ [PART.names ≠ ∅]

Example

A latched topic retains data in partition A. A late reader in partition B matches nothing and receives no history.

How to fix it

Make sure late joiners share the publisher's partition when you rely on durable replay.

Why this rule is flagged

What the DDS specification says

OMG DDS § QoS policy Standard statement
§2.2.3.13 PARTITION A DataWriter and a DataReader communicate only when they have at least one partition name in common. Failure to match partitions is not considered an incompatible QoS.

What the engine source code shows

Both engines gate endpoint matching through partition compatibility. When partitions do not match, the endpoints remain unmatched, so a TRANSIENT_LOCAL writer has no matched reader to replay historical samples to.

Fast DDS implementation evidence

// EDP::valid_matching: partition mismatch is a matching failure.
if (!matched) //Different partitions
{
    logWarning(RTPS_EDP,
            "INCOMPATIBLE QOS (topic: " << rdata->topicName()
            << "): Different Partitions");
    reason.set(MatchingFailureMask::partitions);
}
return matched;

Cyclone DDS implementation evidence

// q_qosmatch.c: partition mismatch prevents endpoint matching.
if ((mask & QP_PARTITION) && !partitions_match_p(rd_qos, wr_qos))
{
    *reason = DDS_PARTITION_QOS_POLICY_ID;
    return false;
}
Item Value
Dataset Download CSV
Fixed QoS setting None
Tested variable PARTITION, DURABL.kind
Tested values PART ∈ {empty, A}, DURABL ∈ {VOLATILE, TRANSIENT_LOCAL}
Rule-relevant case PART = empty vs PART = A under the same DURABL.kind
Tested engines / versions Fast DDS 2.6.11 (Humble), Fast DDS 2.14.6 (Jazzy), Cyclone DDS 0.10.5
Network setting RTT = 1 ms, loss = 0%, PP = 50 ms, message size = 256 B
Engine Tested setting Observed behavior
Fast DDS 2.6.11 (Humble) PART ∈ {empty, A}, DURABL ∈ {VOLATILE, TRANSIENT_LOCAL} PART = A matched, delivered, and recovered late-join samples; PART = empty did not match, deliver, or recover
Fast DDS 2.14.6 (Jazzy) PART ∈ {empty, A}, DURABL ∈ {VOLATILE, TRANSIENT_LOCAL} PART = A matched, delivered, and recovered late-join samples; PART = empty did not match, deliver, or recover
Cyclone DDS 0.10.5 PART ∈ {empty, A}, DURABL ∈ {VOLATILE, TRANSIENT_LOCAL} PART = A matched, delivered, and recovered late-join samples; PART = empty did not match, deliver, or recover

What you'll see when you run it

QoS Guard flags this as an operational conflict:

[OPERATIONAL] [map_sub] [SUB] DURABL≥TRANSIENT_LOCAL <-> PART.names≠Ø

At runtime durable history is replayed only to readers that match the writer, and partition matching decides who matches. A late joiner sitting in a different partition never matches the writer, so it receives none of the retained samples even though the topic is the same. The effort of retaining transient-local history is wasted for any reader outside the writer's partition.