Ariticle

Introduction to Refinitiv Real-Time SDK Warm Standby Feature 

Author:

Jirapongse Phuriphanvichai
Developer Advocate Developer Advocate

Introduction to Refinitiv Real-Time SDK Warm Standby Feature 

Fault tolerance refers to the property of a system that can continue operating properly without interruption in the event of the failure of one or more of its components. It is an important thing that we must consider when designing an application used in the market data system. The failure of a component in the market data system can affect a lot of users and cause a company to lose a lot of profit.

In reality, no one can guarantee that a system can run smoothly 24x7 without a problem because many factors, such as hardware, software, network, and people can trigger problems in the system. However, we can design a system that can perform recovery as fast as possible when a problem occurs.

This article introduces the warm standby feature added in the Refinitiv Real-Time C/C++ SDK 2.0.4.L1 and Refinitiv Real-Time SDK Java 2.0.7.L1. This feature allows a consumer to failover to a standby connection when a primary connection fails or a service is down.  For more information regarding how to run Refinitiv Real-Time SDK C/C++ Warm Standby examples, please refer to the How to Run Refinitiv Real-Time SDK C/C++ Warm Standby Examples article. 

Warm Standby Feature

A warm standby feature was first introduced in Robust Foundation API (RFA) 8 and it was added in the Refinitiv Real-Time C/C++ SDK 2.0.4.L1 and Refinitiv Real-Time SDK Java 2.0.7.L1.. In the Refinitiv Real-Time SDK, the Warm Standby feature is implemented at the Value Add Watchlist layer of Enterprise Transport API (ETA) and made available via Enterprise Message API with configurations.

This client-side feature provides the application with the capability to failover from an active to one or more standby server(s) if the active server fails. Users must prepare and configure an active server and standby server(s) to use this API feature. The following configuration must be added to the ADS configuration file to enable Warm Standby on the consumer side.

    	
            *ads*supportWarmStandby : True
        
        
    

Note: Refinitiv Real-Time Optimized (RTO) also supports the Warm Standby feature.

With this feature, a consumer establishes connections to an active server and standby servers and requests administrative domains (login, source directory, and dictionary domains). A server qualifies to be a standby server only if it advertises support for Warm Standby, supports similar features over login, and offers an identical service (supported domains, quality of service, etc.) as the active server. Then, the consumer sends messages to the standby servers to change the servers’ modes to Standby. Next, the consumer sends item requests to all servers. The active server responds with refresh and update messages that contain data in the payload while the standby servers respond with blank/empty refresh messages. When the primary server fails or the subscribed service is down, the consumer notifies the next server in the standby list to be active. The new active server responds with refresh messages as needed and resumes updates for all open items.

Because the standby server is already aware of items an application has subscribed for, during a failover APIs don't need to re-subscribe items to the standby server. Therefore, Warm Standby not only reduces overall recovery time but also network traffic by not inducing a “packet storm” with a burst of re-request messages. Moreover, this process is transparent to the application. To use this feature, please refer to the EMA 470_MP_WarmStandby or ETA WatchlistConsumer example. 

Two types of warm standby modes are supported:

·        Login-based Warm Standby

·        Service-based Warm Standby

Login based Warm Standby

The login-based warm standby uses the connection lost event to switch from a primary server to a standby server from the standby server list. The following figure illustrates the sequence of events when using the Login Based Warm Standby feature with an active server and a standby server.  The purple color indicates that the server is in active mode while the grey color indicates that the server is in standby mode. A consumer in the picture is a consumer application developed with Refinitiv Real-Time SDK C/C++ 2.0.4.L1 or above. 

Figure 1: Login-Based Warm Standby Mode

The steps are explained below.

1.      A consumer establishes connections to both an active server a standby server. However, the connection establishments don’t happen at the same time. First, a consumer establishes a connection to an active server. Then, it connects to a standby server.

2.      A consumer sends login requests to the servers. The servers respond with the login refresh messages and the value of the SupportStandby element entry is one. This indicates that the servers support the warm standby functionality. 

    	
            

<refreshMsg domainType="RSSL_DMT_LOGIN" streamId="1" containerType="RSSL_DT_NO_DATA" flags="0x168 (RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_SOLICITED|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_CLEAR_CACHE)" groupId="0" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="Login accepted by host replablinux4."  dataSize="0">

    <key  flags="0x26 (RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE|RSSL_MKF_HAS_ATTRIB)"  name="U8009686" nameType="1" attribContainerType="RSSL_DT_ELEMENT_LIST">

        <attrib>

            <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                <elementEntry name="AllowSuspectData" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="ApplicationId" dataType="RSSL_DT_ASCII_STRING" data="256"/>

                <elementEntry name="ApplicationName" dataType="RSSL_DT_ASCII_STRING" data="ADS"/>

                <elementEntry name="Position" dataType="RSSL_DT_ASCII_STRING" data="127.0.0.1/net"/>

                <elementEntry name="ProvidePermissionExpressions" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="ProvidePermissionProfile" dataType="RSSL_DT_UINT" data="0"/>

                <elementEntry name="SingleOpen" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportEnhancedSymbolList" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportOMMPost" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportPauseResume" dataType="RSSL_DT_UINT" data="0"/>

                <elementEntry name="SupportStandby" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportBatchRequests" dataType="RSSL_DT_UINT" data="7"/>

                <elementEntry name="SupportViewRequests" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportOptimizedPauseResume" dataType="RSSL_DT_UINT" data="0"/>

            </elementList>

        </attrib>

    </key>

    <dataBody>

    </dataBody>

</refreshMsg>

3.      A consumer sends login generic messages to the servers to inform their roles in a Warm Standby group.

        The login generic message sent to the active server is:

    	
            

<genericMsg domainType="RSSL_DMT_LOGIN" streamId="1" containerType="RSSL_DT_MAP" flags="0x4 (RSSL_GNMF_HAS_MSG_KEY)" dataSize="47">

    <key  flags="0x2 (RSSL_MKF_HAS_NAME)"  name="ConsumerConnectionStatus"/>

    <dataBody>

        <map flags="0x0" countHint="0" keyPrimitiveType="RSSL_DT_ASCII_STRING" containerType="RSSL_DT_ELEMENT_LIST" >

            <mapEntry flags="0x0" action="RSSL_MPEA_ADD_ENTRY" key="WarmStandbyInfo" >

                <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                    <elementEntry name="WarmStandbyMode" dataType="RSSL_DT_UINT" data="0"/>

                </elementList>

            </mapEntry>

        </map>

    </dataBody>

</genericMsg>

       The login generic message sent to a standby server is:

    	
            

<genericMsg domainType="RSSL_DMT_LOGIN" streamId="1" containerType="RSSL_DT_MAP" flags="0x4 (RSSL_GNMF_HAS_MSG_KEY)" dataSize="47">

    <key  flags="0x2 (RSSL_MKF_HAS_NAME)"  name="ConsumerConnectionStatus"/>

    <dataBody>

        <map flags="0x0" countHint="0" keyPrimitiveType="RSSL_DT_ASCII_STRING" containerType="RSSL_DT_ELEMENT_LIST" >

            <mapEntry flags="0x0" action="RSSL_MPEA_ADD_ENTRY" key="WarmStandbyInfo" >

                <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                    <elementEntry name="WarmStandbyMode" dataType="RSSL_DT_UINT" data="1"/>

                </elementList>

            </mapEntry>

        </map>

    </dataBody>

</genericMsg>

        The generic message contains the WarmStandbyMode element entry. The value of 0 informs the server to be an active server. The value of 1 informs the server to be a standby server.

4.      A consumer handles the source directory domain and retrieves services available on the servers. The services on the servers must have the same attributes, such as service names, service IDs, quality of services, and capabilities.

5.      A consumer requests the data dictionary domain from the servers. This step is optional. A consumer can load the data dictionary from local files.

6.      A consumer sends an item request to both an active server and a standby server.

    	
            

<requestMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="4" containerType="RSSL_DT_NO_DATA" flags="0x44 (RSSL_RQMF_STREAMING|RSSL_RQMF_HAS_QOS)" qosDynamic="0" qosRate="1" qosTimeliness="1" dataSize="0">

    <key  flags="0x3 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME)"  serviceId="4594" name="JPY="/>

    <dataBody>

    </dataBody>

</requestMsg>

7.       An active server responds with an item refresh message that contains data in its payload.

    	
            

<refreshMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="4" containerType="RSSL_DT_FIELD_LIST" flags="0x1FA (RSSL_RFMF_HAS_PERM_DATA|RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_HAS_SEQ_NUM|RSSL_RFMF_SOLICITED|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_HAS_QOS|RSSL_RFMF_CLEAR_CACHE)" groupId="1" seqNum="48798" permData="0308 4252 6C" qosDynamic="0" qosRate="1" qosTimeliness="1" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="All is well"  dataSize="2090">

    <key  flags="0x7 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE)"  serviceId="4594" name="JPY=" nameType="1"/>

    <dataBody>

        <fieldList flags="0x9 (RSSL_FLF_HAS_FIELD_LIST_INFO|RSSL_FLF_HAS_STANDARD_DATA)" fieldListNum="99" dictionaryId="1">

            <fieldEntry fieldId="1" data="020E"/>

            <fieldEntry fieldId="2" data="99"/>

            <fieldEntry fieldId="3" data="4241 4E43 4120 414B 524F 5320 204D 494C"/>

            <fieldEntry fieldId="5" data="0A0F"/>

            <fieldEntry fieldId="11" data="0CEF"/>

            <fieldEntry fieldId="12" data="0C2E 7E"/>

            <fieldEntry fieldId="13" data="0C2E 4A"/>

            <fieldEntry fieldId="15" data="0188"/>

            <fieldEntry fieldId="17" data="1103 07E6"/>

            <fieldEntry fieldId="19" data="0C2E 5F"/>

            <fieldEntry fieldId="21" data="0C2E 60"/>

            <fieldEntry fieldId="22" data="0C2E 4F"/>

        On the other hand, a standby server responds with an item refresh that contains no data in its payload.

    	
            

<refreshMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="4" containerType="RSSL_DT_NO_DATA" flags="0x1FA (RSSL_RFMF_HAS_PERM_DATA|RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_HAS_SEQ_NUM|RSSL_RFMF_SOLICITED|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_HAS_QOS|RSSL_RFMF_CLEAR_CACHE)" groupId="1" seqNum="48798" permData="0308 4252 6C" qosDynamic="0" qosRate="1" qosTimeliness="1" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="All is well"  dataSize="0">

    <key  flags="0x7 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE)"  serviceId="4594" name="JPY=" nameType="1"/>

    <dataBody>

    </dataBody>

</refreshMsg>

8.      A consumer continues to receive update messages from an active server, but not from a standby server.

9.      A consumer detects a disconnection from an active server.

10.      A consumer sends a login generic message to a standby server to change its role to active.

    	
            

<genericMsg domainType="RSSL_DMT_LOGIN" streamId="1" containerType="RSSL_DT_MAP" flags="0x4 (RSSL_GNMF_HAS_MSG_KEY)" dataSize="47">

    <key  flags="0x2 (RSSL_MKF_HAS_NAME)"  name="ConsumerConnectionStatus"/>

    <dataBody>

        <map flags="0x0" countHint="0" keyPrimitiveType="RSSL_DT_ASCII_STRING" containerType="RSSL_DT_ELEMENT_LIST" >

            <mapEntry flags="0x0" action="RSSL_MPEA_ADD_ENTRY" key="WarmStandbyInfo" >

                <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                    <elementEntry name="WarmStandbyMode" dataType="RSSL_DT_UINT" data="0"/>

                </elementList>

            </mapEntry>

        </map>

    </dataBody>

</genericMsg>

           The generic message contains the WarmStandbyMode element entry. The value of 0 informs the server to be an active server. The value of 1 informs the server to be a standby server.

11.      A consumer receives a source directory update message from a new active server.

12      A consumer receives an unsolicited refresh message with data in its payload for subscribed items from an active server.

    	
            

<refreshMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="4" containerType="RSSL_DT_FIELD_LIST" flags="0x1DA (RSSL_RFMF_HAS_PERM_DATA|RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_HAS_SEQ_NUM|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_HAS_QOS|RSSL_RFMF_CLEAR_CACHE)" groupId="1" seqNum="51038" permData="0308 4252 6C" qosDynamic="0" qosRate="1" qosTimeliness="1" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="All is well"  dataSize="2090">

    <key  flags="0x7 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE)"  serviceId="4594" name="JPY=" nameType="1"/>

    <dataBody>

        <fieldList flags="0x9 (RSSL_FLF_HAS_FIELD_LIST_INFO|RSSL_FLF_HAS_STANDARD_DATA)" fieldListNum="99" dictionaryId="1">

            <fieldEntry fieldId="1" data="020E"/>

            <fieldEntry fieldId="2" data="99"/>

            <fieldEntry fieldId="3" data="4241 5243 4C41 5953 2020 2020 204C 4F4E"/>

            <fieldEntry fieldId="5" data="0A10"/>

            <fieldEntry fieldId="11" data="0CF0"/>

            <fieldEntry fieldId="12" data="0C2E 7E"/>

13.      A consumer continues to receive update messages from an active server.

14.      A consumer reconnects to a standby server.

15.      A consumer sends a login request to a standby server. The server responds with a login refresh message and the value of the SupportStandby element entry is one. This indicates that the server supports the warm standby functionality. 

    	
            

<refreshMsg domainType="RSSL_DMT_LOGIN" streamId="1" containerType="RSSL_DT_NO_DATA" flags="0x168 (RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_SOLICITED|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_CLEAR_CACHE)" groupId="0" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="Login accepted by host replablinux4."  dataSize="0">

    <key  flags="0x26 (RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE|RSSL_MKF_HAS_ATTRIB)"  name="U8009686" nameType="1" attribContainerType="RSSL_DT_ELEMENT_LIST">

        <attrib>

            <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                <elementEntry name="AllowSuspectData" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="ApplicationId" dataType="RSSL_DT_ASCII_STRING" data="256"/>

                <elementEntry name="ApplicationName" dataType="RSSL_DT_ASCII_STRING" data="ADS"/>

                <elementEntry name="Position" dataType="RSSL_DT_ASCII_STRING" data="127.0.0.1/net"/>

                <elementEntry name="ProvidePermissionExpressions" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="ProvidePermissionProfile" dataType="RSSL_DT_UINT" data="0"/>

                <elementEntry name="SingleOpen" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportEnhancedSymbolList" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportOMMPost" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportPauseResume" dataType="RSSL_DT_UINT" data="0"/>

                <elementEntry name="SupportStandby" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportBatchRequests" dataType="RSSL_DT_UINT" data="7"/>

                <elementEntry name="SupportViewRequests" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportOptimizedPauseResume" dataType="RSSL_DT_UINT" data="0"/>

            </elementList>

        </attrib>

    </key>

    <dataBody>

    </dataBody>

</refreshMsg>

16.      A consumer sends a login generic message to a server to inform a standby role in a Warm Standby group.

    	
            

<genericMsg domainType="RSSL_DMT_LOGIN" streamId="1" containerType="RSSL_DT_MAP" flags="0x4 (RSSL_GNMF_HAS_MSG_KEY)" dataSize="47">

    <key  flags="0x2 (RSSL_MKF_HAS_NAME)"  name="ConsumerConnectionStatus"/>

    <dataBody>

        <map flags="0x0" countHint="0" keyPrimitiveType="RSSL_DT_ASCII_STRING" containerType="RSSL_DT_ELEMENT_LIST" >

            <mapEntry flags="0x0" action="RSSL_MPEA_ADD_ENTRY" key="WarmStandbyInfo" >

                <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                    <elementEntry name="WarmStandbyMode" dataType="RSSL_DT_UINT" data="1"/>

                </elementList>

            </mapEntry>

        </map>

    </dataBody>

</genericMsg>

        The generic message contains the WarmStandbyMode element entry. The value of 0 informs the server to be an active server. The value of 1 informs the server to be a standby server.

17.      A consumer handles the source directory domain and retrieves services available on a standby server. The services on the servers must have the same attributes, such as service names, service IDs, quality of services, and capabilities.

18.      A consumer sends item requests to a standby server. 

    	
            

<requestMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="5" containerType="RSSL_DT_NO_DATA" flags="0x44 (RSSL_RQMF_STREAMING|RSSL_RQMF_HAS_QOS)" qosDynamic="0" qosRate="1" qosTimeliness="1" dataSize="0">

    <key  flags="0x3 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME)"  serviceId="4594" name="JPY="/>

    <dataBody>

    </dataBody>

</requestMsg>

19.        Because the server is a standby server, it responds with an item refresh that is no data in the payload.

    	
            

<refreshMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="5" containerType="RSSL_DT_NO_DATA" flags="0x1FA (RSSL_RFMF_HAS_PERM_DATA|RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_HAS_SEQ_NUM|RSSL_RFMF_SOLICITED|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_HAS_QOS|RSSL_RFMF_CLEAR_CACHE)" groupId="1" seqNum="53342" permData="0308 4252 6C" qosDynamic="0" qosRate="1" qosTimeliness="1" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="All is well"  dataSize="0">

    <key  flags="0x7 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE)"  serviceId="4594" name="JPY=" nameType="1"/>

    <dataBody>

    </dataBody>

</refreshMsg>

Now, a consumer gets updates from an active server and also subscribes an item to a standby server. 

The login-based warm standby uses the login domain to inform servers about their roles in a Warm Standby group. It fails over to a standby server when it can detect a disconnection from an active server. 

Service-based Warm Standby

The service-based warm standby uses the service down event or connection lost event to switch all subscribe items from a primary service to a standby service. The service-based warm standby mode offers better resiliency than the login-based mode as it can switch from primary to standby if an upstream service is down but the connection to both servers remains intact. A particular server may be the primary server for one service and standby for another service as a result. This ability to failover in the event of service down or channel down events makes the service-based warm standby the recommended mode.

The following figure illustrates the sequence of events when using the Service-Based Warm Standby feature with an active server and a standby server. The purple color indicates that the server is in active mode while the grey color indicates that the server is in standby mode. 

The steps are explained below.

1.      A consumer establishes connections to both an active server a standby server. However, the connection establishments don’t happen at the same time. First, a consumer establishes a connection to an active server. Then, it connects to a standby server.

2.     A consumer sends login requests to the servers. The servers respond with the login refresh messages and the value of the SupportStandby element entry is one. This indicates that the servers support the warm standby functionality.

    	
            

<refreshMsg domainType="RSSL_DMT_LOGIN" streamId="1" containerType="RSSL_DT_NO_DATA" flags="0x168 (RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_SOLICITED|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_CLEAR_CACHE)" groupId="0" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="Login accepted by host replablinux4."  dataSize="0">

    <key  flags="0x26 (RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE|RSSL_MKF_HAS_ATTRIB)"  name="U8009686" nameType="1" attribContainerType="RSSL_DT_ELEMENT_LIST">

        <attrib>

            <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                <elementEntry name="AllowSuspectData" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="ApplicationId" dataType="RSSL_DT_ASCII_STRING" data="256"/>

                <elementEntry name="ApplicationName" dataType="RSSL_DT_ASCII_STRING" data="ADS"/>

                <elementEntry name="Position" dataType="RSSL_DT_ASCII_STRING" data="127.0.0.1/net"/>

                <elementEntry name="ProvidePermissionExpressions" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="ProvidePermissionProfile" dataType="RSSL_DT_UINT" data="0"/>

                <elementEntry name="SingleOpen" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportEnhancedSymbolList" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportOMMPost" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportPauseResume" dataType="RSSL_DT_UINT" data="0"/>

                <elementEntry name="SupportStandby" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportBatchRequests" dataType="RSSL_DT_UINT" data="7"/>

                <elementEntry name="SupportViewRequests" dataType="RSSL_DT_UINT" data="1"/>

                <elementEntry name="SupportOptimizedPauseResume" dataType="RSSL_DT_UINT" data="0"/>

            </elementList>

        </attrib>

    </key>

    <dataBody>

    </dataBody>

</refreshMsg>

3.      A consumer handles the source directory domain and retrieves services available on the servers. The services on the servers must have the same attributes, such as service names, service IDs, quality of services, and capabilities.

4.      A consumer sends source directory generic messages to the servers to inform their roles in a Warm Standby group.  

         The source directory generic message sent to an active server is:

    	
            

<genericMsg domainType="RSSL_DMT_SOURCE" streamId="2" containerType="RSSL_DT_MAP" flags="0x4 (RSSL_GNMF_HAS_MSG_KEY)" dataSize="34">

    <key  flags="0x2 (RSSL_MKF_HAS_NAME)"  name="ConsumerStatus"/>

    <dataBody>

        <map flags="0x0" countHint="0" keyPrimitiveType="RSSL_DT_UINT" containerType="RSSL_DT_ELEMENT_LIST" >

            <mapEntry flags="0x0" action="RSSL_MPEA_ADD_ENTRY" key="4594" >

                <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                    <elementEntry name="WarmStandbyMode" dataType="RSSL_DT_UINT" data="0"/>

                </elementList>

            </mapEntry>

        </map>

    </dataBody>

</genericMsg>

         The source directory generic message sent to a standby server is:

    	
            

<genericMsg domainType="RSSL_DMT_SOURCE" streamId="2" containerType="RSSL_DT_MAP" flags="0x4 (RSSL_GNMF_HAS_MSG_KEY)" dataSize="34">

    <key  flags="0x2 (RSSL_MKF_HAS_NAME)"  name="ConsumerStatus"/>

    <dataBody>

        <map flags="0x0" countHint="0" keyPrimitiveType="RSSL_DT_UINT" containerType="RSSL_DT_ELEMENT_LIST" >

            <mapEntry flags="0x0" action="RSSL_MPEA_ADD_ENTRY" key="4594" >

                <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                    <elementEntry name="WarmStandbyMode" dataType="RSSL_DT_UINT" data="1"/>

                </elementList>

            </mapEntry>

        </map>

    </dataBody>

</genericMsg>

         The generic message contains the WarmStandbyMode element entry. The value of 0 informs the server to be an active server. The value of 1 informs the server to be a standby server.

5.      A consumer requests the data dictionary domain from the servers. This step is optional. A consumer can load the data dictionary from local files.

6.      A consumer sends an item request to both an active server and a standby server. 

    	
            

<requestMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="4" containerType="RSSL_DT_NO_DATA" flags="0x44 (RSSL_RQMF_STREAMING|RSSL_RQMF_HAS_QOS)" qosDynamic="0" qosRate="1" qosTimeliness="1" dataSize="0">

    <key  flags="0x3 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME)"  serviceId="4594" name="JPY="/>

    <dataBody>

    </dataBody>

</requestMsg>

7.      An active server responds with an item refresh that contains data in its payload. 

    	
            

<refreshMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="4" containerType="RSSL_DT_FIELD_LIST" flags="0x1FA (RSSL_RFMF_HAS_PERM_DATA|RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_HAS_SEQ_NUM|RSSL_RFMF_SOLICITED|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_HAS_QOS|RSSL_RFMF_CLEAR_CACHE)" groupId="1" seqNum="19902" permData="0311 F252 6C" qosDynamic="0" qosRate="1" qosTimeliness="1" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="All is well"  dataSize="2029">

    <key  flags="0x7 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE)"  serviceId="4594" name="JPY=" nameType="1"/>

    <dataBody>

        <fieldList flags="0x9 (RSSL_FLF_HAS_FIELD_LIST_INFO|RSSL_FLF_HAS_STANDARD_DATA)" fieldListNum="99" dictionaryId="1">

            <fieldEntry fieldId="1" data="020E"/>

            <fieldEntry fieldId="2" data="99"/>

            <fieldEntry fieldId="3" data="5341 4E54 414E 4445 5220 2020 2048 4B47"/>

            <fieldEntry fieldId="5" data="053A"/>

            <fieldEntry fieldId="11" data="0C76"/>

            <fieldEntry fieldId="12" data="0C30 25"/>

            <fieldEntry fieldId="13" data="0C2F A6"/>

            <fieldEntry fieldId="15" data="0188"/>

            <fieldEntry fieldId="17" data="1C03 07E6"/>

            <fieldEntry fieldId="19" data="0C2F A3"/>

            <fieldEntry fieldId="21" data="0C2F AE"/>

            <fieldEntry fieldId="22" data="0C30 24"/>

            <fieldEntry fieldId="23" data="0C30 24"/>

         On the other hand, a standby server responds with an item refresh that contains no data in its payload.

    	
            

<refreshMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="4" containerType="RSSL_DT_NO_DATA" flags="0x1FA (RSSL_RFMF_HAS_PERM_DATA|RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_HAS_SEQ_NUM|RSSL_RFMF_SOLICITED|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_HAS_QOS|RSSL_RFMF_CLEAR_CACHE)" groupId="1" seqNum="19966" permData="0311 F252 6C" qosDynamic="0" qosRate="1" qosTimeliness="1" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="All is well"  dataSize="0">

    <key  flags="0x7 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE)"  serviceId="4594" name="JPY=" nameType="1"/>

    <dataBody>

    </dataBody>

</refreshMsg>

8.      A consumer continues to receive update messages from an active server, but not from a standby server.

9.      A consumer receives a service down message from an active server.

    	
            

<updateMsg domainType="RSSL_DMT_SOURCE" streamId="2" containerType="RSSL_DT_MAP" flags="0x80 (RSSL_UPMF_DO_NOT_CONFLATE)" updateType="0 (RDM_UPD_EVENT_TYPE_UNSPECIFIED)" dataSize="72">

    <dataBody>

        <map flags="0x0" countHint="0" keyPrimitiveType="RSSL_DT_UINT" containerType="RSSL_DT_FILTER_LIST" >

            <mapEntry flags="0x0" action="RSSL_MPEA_UPDATE_ENTRY" key="4594" >

                <filterList containerType="RSSL_DT_ELEMENT_LIST" countHint="0" flags="0x0">

                    <filterEntry id="2" action="RSSL_FTEA_SET_ENTRY" flags="0x0" containerType="RSSL_DT_ELEMENT_LIST">

                        <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                            <elementEntry name="ServiceState" dataType="RSSL_DT_UINT" data="0"/>

                            <elementEntry name="AcceptingRequests" dataType="RSSL_DT_UINT" data="1"/>

                            <elementEntry name="Status" dataType="RSSL_DT_STATE" dataState="RSSL_DATA_SUSPECT" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="" />

                        </elementList>

                    </filterEntry>

                </filterList>

            </mapEntry>

        </map>

    </dataBody>

</updateMsg>

10.     A consumer sends source directory generic messages to the servers to change their roles.

          A consumer sends the following source directory generic message to an active server to change its role to standby. 

    	
            

<genericMsg domainType="RSSL_DMT_SOURCE" streamId="2" containerType="RSSL_DT_MAP" flags="0x4 (RSSL_GNMF_HAS_MSG_KEY)" dataSize="34">

    <key  flags="0x2 (RSSL_MKF_HAS_NAME)"  name="ConsumerStatus"/>

    <dataBody>

        <map flags="0x0" countHint="0" keyPrimitiveType="RSSL_DT_UINT" containerType="RSSL_DT_ELEMENT_LIST" >

            <mapEntry flags="0x0" action="RSSL_MPEA_ADD_ENTRY" key="4594" >

                <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                    <elementEntry name="WarmStandbyMode" dataType="RSSL_DT_UINT" data="1"/>

                </elementList>

            </mapEntry>

        </map>

    </dataBody>

</genericMsg>

         A consumer sends the following source directory generic message to a standby server to change its role to active.

    	
            

<genericMsg domainType="RSSL_DMT_SOURCE" streamId="2" containerType="RSSL_DT_MAP" flags="0x4 (RSSL_GNMF_HAS_MSG_KEY)" dataSize="34">

    <key  flags="0x2 (RSSL_MKF_HAS_NAME)"  name="ConsumerStatus"/>

    <dataBody>

        <map flags="0x0" countHint="0" keyPrimitiveType="RSSL_DT_UINT" containerType="RSSL_DT_ELEMENT_LIST" >

            <mapEntry flags="0x0" action="RSSL_MPEA_ADD_ENTRY" key="4894" >

                <elementList flags="0x8 (RSSL_ELF_HAS_STANDARD_DATA)">

                    <elementEntry name="WarmStandbyMode" dataType="RSSL_DT_UINT" data="0"/>

                </elementList>

            </mapEntry>

        </map>

    </dataBody>

</genericMsg>

         The generic message contains the WarmStandbyMode element entry. The value of 0 informs the server to be an active server. The value of 1 informs the server to be a standby server.

11.      A consumer receives a source directory update message from a new active server.

12.     A consumer receives an unsolicited refresh message with data in its payload for a subscribed item from a new active server. 

    	
            

<refreshMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="4" containerType="RSSL_DT_FIELD_LIST" flags="0x1DA (RSSL_RFMF_HAS_PERM_DATA|RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_HAS_SEQ_NUM|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_HAS_QOS|RSSL_RFMF_CLEAR_CACHE)" groupId="1" seqNum="51038" permData="0308 4252 6C" qosDynamic="0" qosRate="1" qosTimeliness="1" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="All is well"  dataSize="2090">

    <key  flags="0x7 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE)"  serviceId="4594" name="JPY=" nameType="1"/>

    <dataBody>

        <fieldList flags="0x9 (RSSL_FLF_HAS_FIELD_LIST_INFO|RSSL_FLF_HAS_STANDARD_DATA)" fieldListNum="99" dictionaryId="1">

            <fieldEntry fieldId="1" data="020E"/>

            <fieldEntry fieldId="2" data="99"/>

            <fieldEntry fieldId="3" data="4241 5243 4C41 5953 2020 2020 204C 4F4E"/>

            <fieldEntry fieldId="5" data="0A10"/>

            <fieldEntry fieldId="11" data="0CF0"/>

            <fieldEntry fieldId="12" data="0C2E 7E"/>

13.      A consumer continues to receive update messages from a new active server.

14.      When the service has been recovered on a standby server, a consumer receives the service up message.

15.      A consumer receives an item refresh with no data in the payload from a standby server.

    	
            

<refreshMsg domainType="RSSL_DMT_MARKET_PRICE" streamId="5" containerType="RSSL_DT_NO_DATA" flags="0x1FA (RSSL_RFMF_HAS_PERM_DATA|RSSL_RFMF_HAS_MSG_KEY|RSSL_RFMF_HAS_SEQ_NUM|RSSL_RFMF_SOLICITED|RSSL_RFMF_REFRESH_COMPLETE|RSSL_RFMF_HAS_QOS|RSSL_RFMF_CLEAR_CACHE)" groupId="1" seqNum="53342" permData="0308 4252 6C" qosDynamic="0" qosRate="1" qosTimeliness="1" dataState="RSSL_DATA_OK" streamState="RSSL_STREAM_OPEN" code="RSSL_SC_NONE" text="All is well"  dataSize="0">

    <key  flags="0x7 (RSSL_MKF_HAS_SERVICE_ID|RSSL_MKF_HAS_NAME|RSSL_MKF_HAS_NAME_TYPE)"  serviceId="4594" name="JPY=" nameType="1"/>

    <dataBody>

    </dataBody>

</refreshMsg>

Now, a consumer gets updates from an active server and also subscribes an item to a standby server. 

The service-based warm standby uses the source directory domain to inform servers about their roles in a Warm Standby group. It fails over to a standby server when it can detect either a service down or disconnection from an active server.

Summary

The client-side warm standby feature was first introduced in Robust Foundation API 8. Now, this feature is available in the Refinitiv Real-Time C/C++ SDK 2.0.4.L1. It is implemented in the ETA Reactor with watchlist enabled and made available in EMA via configurations. This feature provides a capability for consumers to failover from an active to one or more standby server(s) when the active server fails. Because the standby server is already aware of items subscribed by a consumer, during a failover, APIs don't need to re-subscribe items to the standby server. Therefore, Warm Standby can reduce overall recovery time and network traffic for item resubscriptions.

Refinitiv Real-Time C/C++ supports two types of warm standby modes. The login-based warm standby uses the connection lost event to switch from a primary server to a standby server from the standby server list. This mode uses a generic message of the login domain to inform servers about their roles in a Warm Standby group. The service-based warm standby uses the service down event or connection lost event to switch all subscribe items from a primary service to a standby service. This mode uses a generic message of the source directory domain to inform servers about their roles in a Warm Standby group. This ability to failover in the event of service down or channel down events makes the service-based warm standby the recommended mode.

References

1.      2021. Enterprise Message API C++ Developers Guide. [ebook] Refinitiv. Available at: <https://developers.refinitiv.com/en/api-catalog/refinitiv-real-time-opnsrc/rt-sdk-cc/documentation#message-api-c-development-guides> [Accessed 28 March 2022].

2.      2021. Enterprise Transport API C Developers Guide. [ebook] Refinitiv. Available at: <https://developers.refinitiv.com/en/api-catalog/refinitiv-real-time-opnsrc/rt-sdk-cc/documentation#enterprise-transport-api-c-edition-developer-guides> [Accessed 28 March 2022].

3.      2021. Refinitiv Advanced Distribution Server Software Installation Manual. [ebook] Refinitiv. Available at: <https://my.refinitiv.com/content/dam/myrefinitiv/products/9601/en/Technical/628187.pdf> [Accessed 28 March 2022].

Standby