Reliable writer keeps sending messages when reader application is restarted

2 posts / 0 new
Last post
Offline
Last seen: 4 years 8 months ago
Joined: 05/21/2014
Posts: 46
Reliable writer keeps sending messages when reader application is restarted

I have an application with a reliable reader and writer.

Whenever I restart the reader, the reader reads messages it already receieved so if the reader recieved a message to restart the application it is now in a restart loop due to the restart message being read every restart.

I was under the impression that these messages would be acknolwdged and not resent if already recieved before application restart. Why am I recieving messages I thus have already read on application restart of the reader?

Francisco Porcel's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 11/07/2016
Posts: 24

Hi Jason,

From the description you provided, I guess your situation is the following (let me know if I am wrong):

  1. You start DataReader. 
  2. The DataReader takes the data. 
  3. You restart the DataReader. 
  4. The DataReader takes the data which had already been taken.

If the situation above is the one you are facing, then the behavior you are observing is expected. Although you do not have Persistence Service running, you must have the Durability QoS policy set to something different than VOLATILE_DURABILITY_QOS for both the DataWriter and the DataReader. Then, the situation is the following:

  1. You start your DataReader. 
  2. The DataWriter is sending samples which it stores for late-joiner DataReaders (because of having durability set to something different than VOLATILE_DURABILITY_QOS). 
  3. The DataReader takes the samples. 
  4. The DataReader is restarted (therefore, it is considered a late-joiner DataReader). 
  5. Since it is a late-joiner DataReader, the DataWriter resends the samples it has stored. 
  6. Your DataReader takes the same samples the old DataReader had taken.

So this is why your new DataReader takes the same samples that the old DataReader had already taken. If you do not want samples to be resent to late-joiner DataReaders, you can use VOLATILE_DURABILITY_QOS. As you can see in section '6.3.13.2 Durability QoS and Required Subscriptions', you can specify to either not make the DDS samples available for late-joiners with DDS_VOLATILE_DURABILITY_QOS or make them available with DDS_TRANSIENT_LOCAL_DURABILITY_QOS, DDS_TRANSIENT_DURABILITY_QOS or DDS_PERSISTENT_DURABILITY_QOS. This is why the behavior you are experiencing is expected.

If you still want late-joiner DataReaders to receive previously sent samples but you do not want the scenario described above, you can use 'Required Subscriptions'. You can find information about this feature in section '6.3.13 Required Subscriptions' of the User's Manual. I will quickly summarize what Required Subscriptions consist of.

Required Subscriptions will make the application decide if it should send stored samples to certain late-joiners. Required Subscriptions are related to the DataReaders' role_name. Imagine that the Required Subscription is related to the role_name = 'roleDataReader' and quorum_count = 1. If the DataWriter has been sending samples to a DataReader with role_name = 'roleDataReader' and the DataReader is restarted with the same role_name, samples will not be resent to it. If there is a late-joiner DataReader with a different role_name, samples will be resent to it.

For your use case, you should set the same role_name for both DataReaders (the one before restarting and the one after restarting) if you want already read samples not to be "resent" to the second DataReader.

Following the above example, you should set the following in your DataWriter QoS:

<datawriter_qos>
    <availability> 
        <enable_required_subscriptions>true</enable_required_subscriptions> 
        <required_matched_endpoint_groups> 
            <element> 
                <role_name>roleDataReader</role_name> 
                <quorum_count>1</quorum_count> 
            </element> 
        </required_matched_endpoint_groups> 
    </availability> 
</datawriter_qos>

This way, you will be activating Required Subscriptions with the first field. With quorum_count you will control how many DataReaders are Required Subscriptions. For your DataReaders, you should set something like:

<datareader_qos>
    <subscription_name>
        <role_name>roleDataReader</role_name>
    </subscription_name>
</datareader_qos>

So that your DataReaders will have the same role_name as in the Required Subscription.

Please, let me know if this helps.

-Fran