Does completion event available in Login stream?
According to the DeveloperGuide 10.1.6.3 - Event Handler Restrictions,
The multi-threaded application must use completion events. The application should cancel all currently activerequests that were made with the instance of the client specified and wait for a completion event for each of thoserequests. While waiting for a completion event, an application might receive other events that close the stream(e.g. a status message that closes the stream) before the completion event arrives.
Whenever the isEventStreamClosed() function returns true (for either a completion event or some other streamclosing event), the application can delete the client instance.
Since I cannot see the completion event in my test, I am wondering if the above statement also apply to login stream?
Best Answer
-
Going back to your questions.
Not at all. Getting a simple RFA C++ example or one of our tutorials to print streaming prices is quick and easy, but to design a production strength app- takes thought, time and effort.
In that line of thought, in my opinion, this will not be sufficient. If planning to stay with RFA C++, would do 2 things:
Review RFA Developer guide for threading tips. It discusses all things one should avoid doing with threaded apps, as well as best practices. See "Event Distribution Usage Guidelines" and "Cleaning up". RFA will attempt, on destroy, to cleanup everything properly on behalf of the app, however, the best practice is to try to "for the application to clean up any resources that it has created, registered for, or acquired". In the order that is opposite to that of initialization.
Take a simple example, StarterConsumer that came with SDK is very popular and do full cleanup properly, observing and printing events and steps. Then integrate the same cleanup sequence into your custom app.
For example:
Print completion events separately to be more visible
void StarterConsumer::processEvent(const Event& event)
{
switch(event.getType())
{
case ConnectionEventEnum:
processConnectionEvent(static_cast<const ConnectionEvent&>(event));
break;
case OMMItemEventEnum:
processOMMItemEvent(static_cast<const OMMItemEvent&>(event));
break;
case OMMCmdErrorEventEnum:
processOMMCmdErrorEvent(static_cast<const OMMCmdErrorEvent&>(event));
break;
case LoggerNotifyEventEnum:
processLoggerNotifyEvent(static_cast<const LoggerNotifyEvent&>(event));
break;
case rfa::common::ComplEventEnum:
AppUtil::log(__LINE__, AppUtil::WARN, "****** Receive Completion Event"
...Register to receive completions per all streams
_pOMMConsumer = _pSession->createOMMConsumer(RFA_String(_appName, 0, false),true);
And modify cleanup per prod requirements. Test and observe, tune per your needs. Examples were written for simplicity,rather then completeness that is required for production strength apps. This is still a simplification, that may be a good as a starting point:
void StarterConsumer::cleanup()
{
AppUtil::log(__LINE__, AppUtil::TRACE, "::cleanup()");
// if(_pEventQueue)
// _pEventQueue->deactivate(); ZF
if (_pOMMConsumer)
{
if (_pLoginHandle)
{
_pOMMConsumer->unregisterClient(_pLoginHandle);
_pLoginHandle = 0;
}
if (_pOMMConnIntSpecHandle)
{
_pOMMConsumer->unregisterClient(_pOMMConnIntSpecHandle);
_pOMMConnIntSpecHandle = 0;
}
if (_pOMMErrIntSpecHandle)
{
_pOMMConsumer->unregisterClient(_pOMMErrIntSpecHandle);
_pOMMErrIntSpecHandle = 0;
}
_pOMMConsumer->destroy();
_pOMMConsumer = 0;
}
for (int i = 0; i < 10; i++) { //ZF
long dispatchReturn = _pEventQueue->dispatch(10);
Sleep(100);
}
if (_pEventQueue) //ZF
_pEventQueue->deactivate();
if(_pSession)
{
_pSession->release();
_pSession = 0;
}
if(_pAppLoggerMonitor && _pLoggerHandle)
{
_pAppLoggerMonitor->unregisterLoggerClient(_pLoggerHandle);
...As you have processing in other threads, completions become especially important to observe prior to the next step in uninit.
Further on question 2, destroy, yes, believe you can call consumer destroy separately, from a different thread, as long as the destruction sequence required is complete and sequencing is observed. However, since this is not a single step, but a compete proper sequence of cleanup is required, it is usually run as a sequence, each step building on the previous completing successfully, not taken from a different thread.
I hope this helps
0
Answers
-
Hello @kc.lam,
Apologies for the belated response.
As you mention that you can not see completion event in your test, like to ask you a couple of questions, so we may be sure to fully understand yours:
Have you tried testing with one of the standard examples that came with SDK, or this is your custom code that does not see the completion event?
If testing with one of the standard examples, out of the box they would not be receiving completions, for a couple of reasons.
I would test with one of the standard examples first, and modify, because they modify easily and concisely, and because with the custom code we cannot be sure what is happening, unless we review the custom code in-depth, and that can not be done within the framework of the discussion forums.
- Are you registering for the completion events, when creating consumer, as default is false?
virtual OMMConsumer* rfa::sessionLayer::Session::createOMMConsumer
(
const rfa::common::RFA_String &
name
bool
wCompEvents = false
)- Are you keeping the event queue alive, past unregister?
- Are you continuing to dispatch events past unregister?
- Are you waiting some, past unregister, and prior to the rest of uninit, so you could receive the completion?
Let me know if my questions make sense, or are confusing?
1 -
Hi @zoya.farberov,
Thanks for your reply, I can get the completion event after enabling it in the OMM Consumer constructor. Sorry for asking this stupid question, but now I got another question concerning the proper shutdown procedure.
We are running in single-thread callback mode. During program termination, the SIGTERM signal is caught in another thread to perform cleanup in the following sequence:- Unregister the login stream, as to close al other open interests as well
- Destroy the OMMConsumer
- Release the RFA session and then un-initialize RFA context
Then my questions are:
- Should we wait for the completion event between step 1 and 2? In the future, we may want to change to dual-thread callback mode, would it cause any difference?
- I can't find the thread-safety remarks for destroy() in API manual, so in step 2), is it safe for us to call ommConsumer->destroy in another thread?
Thanks in advance!!
0 -
Hello @kc.lam,
For a new application, I would seriously consider Elektron Suite of API over RFA C++.
At present, RFA C++ is a fully supported, feature-complete API. Elektron Message API C++ will have all the new features, and it's an actively developed, new API. It will also take significantly less time and effort for you to develop a custom consumer per requirements. If you need the low level access- Elektron Transport API can be used.
0 -
zoya.farberov, thanks for the detailed explanation. Our application runs without using event queue, so it is pretty much the same as your example code.
0
Categories
- All Categories
- 6 AHS
- 37 Alpha
- 161 App Studio
- 4 Block Chain
- 4 Bot Platform
- 16 Connected Risk APIs
- 47 Data Fusion
- 30 Data Model Discovery
- 608 Datastream
- 1.3K DSS
- 577 Eikon COM
- 4.9K Eikon Data APIs
- 7 Electronic Trading
- Generic FIX
- 7 Local Bank Node API
- Trading API
- 2.7K Elektron
- 1.3K EMA
- 236 ETA
- 519 WebSocket API
- 33 FX Venues
- 10 FX Market Data
- 1 FX Post Trade
- 1 FX Trading - Matching
- 12 FX Trading – RFQ Maker
- 5 Intelligent Tagging
- 2 Legal One
- 20 Messenger Bot
- 2 Messenger Side by Side
- 9 ONESOURCE
- 7 Indirect Tax
- 59 Open Calais
- 264 Open PermID
- 39 Entity Search
- 2 Org ID
- PAM
- PAM - Logging
- 8.4K Private Comments
- 6 Product Insight
- Project Tracking
- ProView
- ProView Internal
- 20 RDMS
- 1.4K Refinitiv Data Platform
- 367 Refinitiv Data Platform Libraries
- 3 Refinitiv Due Diligence
- LSEG Due Diligence Portal API
- 3 Refinitiv Due Dilligence Centre
- Rose's Space
- 1.1K Screening
- 18 Qual-ID API
- 13 Screening Deployed
- 23 Screening Online
- 10 World-Check Customer Risk Screener
- 990 World-Check One
- 44 World-Check One Zero Footprint
- 45 Side by Side Integration API
- Test Space
- 3 Thomson One Smart
- 1.2K TR Internal
- Global Hackathon 2015
- 2 Specialists Who Code
- 10 TR Knowledge Graph
- 150 Transactions
- 142 REDI API
- 1.7K TREP APIs
- 4 CAT
- 21 DACS Station
- 117 Open DACS
- 1.1K RFA
- 103 UPA
- 172 TREP Infrastructure
- 224 TRKD
- 886 TRTH
- 5 Velocity Analytics
- 5 Wealth Management Web Services
- 59 Workspace SDK
- 9 Element Framework
- 5 Grid
- 13 World-Check Data File
- Yield Book Analytics
- 46 中文论坛