AutobahnCpp async RPC

#1

Hi Tobias,
I have another question regarding RPCs that can take some time to execute (DB procedure for example). It would be nice to implement those kind of RPCs as asynchronous, so that the calee would not be stuck executing a single RPC. It looks like theer is a way to register async RPC (provide_f, provide_fm, etc). But there seem to be no way to call the RPC registered this way. It seems to me that there must be call_f call_fm, etc corresponding methods. Please confirm that my understanding is correct.

Thanks,

Rosa

0 Likes

#2

Hi Tobias,
I have another question regarding RPCs that can take some time to
execute (DB procedure for example). It would be nice to implement those
kind of RPCs as asynchronous, so that the calee would not be stuck
executing a single RPC. It looks like theer is a way to register async

Yes. And you don't need shared registrations for that. What you want is an _asynchronous database client library_ that integrates with the event loop (Boost/ASIO).

The problem is: most database client libraries are blocking (not async).

E.g. the Oracle database client library is blocking by nature. PostgreSQL is also blocking by default (though it has a feature that allows for async).

The way this is usually solved (e.g. in Twisted's database support) is by executing database stuff on a background worker thread pool.

In pseudocode:

Future f = db.run_query("select count(*) from mytab");

Under the hood, it'll run the query on a background thread, and when the result comes back, wake up the Future f.

In AutobahnCpp you could use that for implementing a procedure ("provide" .. since "register" is a C++ keyword) and simply return the future as a result.

RPC (provide_f, provide_fm, etc). But there seem to be no way to call
the RPC registered this way. It seems to me that there must be call_f
call_fm, etc corresponding methods. Please confirm that my understanding

Not sure what you mean .. you can "provide" a function to be callable from a remote client. A function "provided" in that way is _also_ callable from within the same client that provides the function. In this case, the call will travel to the router and come back again (if there is no shared registration).

You cannot magically make a database client library non-blocking by any combination of "provide"/"call".

If your C++ program runs on a single thread, and you make that thread enter a blocking database client library, that thread will be blocked until the DB lib comes back. No WAMP stuff will be processed in the meantime, and your client will appear being non-responsive from the router perspective.

You can use shared registrations to work around the blocking nature of DB libs, but that's not what shared registrations are really intended for. Since if you do that, your (single-threaded) WAMP component will look unresponsive from outside (to the router), and the router e.g. won't be able to interrupt a call into your component (since the code therein is "busy" sitting and waiting for the DB to return).

To work around blocking DB libs in an asynch context, the usual pattern is to not block the main thread running the event loop and execute any blocking stuff on a background thread pool.

nodejs works like this. Twisted and asyncio work like this.

Also: do you really need to do the DB access from C++?

You could encapsulate DB access in a WAMP component written in a more friendly language (better: a language that has already solved blocking DB libs and async). And then just call into the former component from your C++ component.

WAMP is about making an app out of decoupled components - potentially written in multiple languages. Having "data access" separated into a component used by other sounds fine for me. And you can use the polyglot power of WAMP here .. don't bother with C++ heavy artillery if you don't have to;)

···

Am 31.03.2015 um 16:31 schrieb Rosa Lisin:

===

Contrast:

async programming is great if your code would otherwise just sit and wait (like for I/O).

If you run CPU intensive stuff, your code is actually doing useful work (not just waiting). And this is where shared registrations come in.

Hopefully I am not triggering more questsions than answering ones;)

Cheers,
/Tobias

is correct.

Thanks,
Rosa

--
You received this message because you are subscribed to the Google
Groups "Autobahn" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to autobahnws+...@googlegroups.com
<mailto:autobahnws+...@googlegroups.com>.
To post to this group, send email to autob...@googlegroups.com
<mailto:autob...@googlegroups.com>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/autobahnws/8af04765-ed53-4c96-87a6-ef2a621e3931%40googlegroups.com
<https://groups.google.com/d/msgid/autobahnws/8af04765-ed53-4c96-87a6-ef2a621e3931%40googlegroups.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.

0 Likes

#3

Hi Tobias,
I actually used DB call as an example, and it turned out to be not a good one. I realize C++ is not the best choise when dealing with DB.

Suppose the Remote Procedure has to establish connection with some network endpoint, so most of the time the RP will do nothing but wait for response. So the natural way to go, it seems, is to use an async remote procedure.

But when I tried to run a simple test registering function by calee:

future my_func (const anyvec& myvec, const anymap& mymap) {

return boost::async(boost::bind(do_something,args,kwargs));

}

session.provide_f(“com.myapp.cpp.my_func”, &my_func );

But when the caller actually calls it:

session.call(“com.myapp.cpp.my_func”, somevec,somemap);

The calee experiences the following error:

FIX ME INVOCATION

St8functionIFN5boost3anyERKSt6vectorIS1_SaIS1_EERKSt3mapISsS1_St4lessISsESaISt4pairIKSsS1_EEEEE

St8functionIFN5boost6futureINS0_3anyEEERKSt6vectorIS2_SaIS2_EERKSt3mapISsS2_St4lessISsESaISt4pairIKSsS2_EEEEE

Am I doing something wrong?

Thanks,

Rosa

···

On Tuesday, March 31, 2015 at 11:15:04 AM UTC-4, Tobias Oberstein wrote:

Am 31.03.2015 um 16:31 schrieb Rosa Lisin:

Hi Tobias,

I have another question regarding RPCs that can take some time to

execute (DB procedure for example). It would be nice to implement those

kind of RPCs as asynchronous, so that the calee would not be stuck

executing a single RPC. It looks like theer is a way to register async

Yes. And you don’t need shared registrations for that. What you want is
an asynchronous database client library that integrates with the event
loop (Boost/ASIO).

The problem is: most database client libraries are blocking (not async).

E.g. the Oracle database client library is blocking by nature.
PostgreSQL is also blocking by default (though it has a feature that
allows for async).

The way this is usually solved (e.g. in Twisted’s database support) is
by executing database stuff on a background worker thread pool.

In pseudocode:

Future f = db.run_query(“select count(*) from mytab”);

Under the hood, it’ll run the query on a background thread, and when the
result comes back, wake up the Future f.

In AutobahnCpp you could use that for implementing a procedure
(“provide” … since “register” is a C++ keyword) and simply return the
future as a result.

RPC (provide_f, provide_fm, etc). But there seem to be no way to call

the RPC registered this way. It seems to me that there must be call_f

call_fm, etc corresponding methods. Please confirm that my understanding

Not sure what you mean … you can “provide” a function to be callable
from a remote client. A function “provided” in that way is also
callable from within the same client that provides the function. In this
case, the call will travel to the router and come back again (if there
is no shared registration).

You cannot magically make a database client library non-blocking by any
combination of “provide”/“call”.

If your C++ program runs on a single thread, and you make that thread
enter a blocking database client library, that thread will be blocked
until the DB lib comes back. No WAMP stuff will be processed in the
meantime, and your client will appear being non-responsive from the
router perspective.

You can use shared registrations to work around the blocking nature of
DB libs, but that’s not what shared registrations are really intended
for. Since if you do that, your (single-threaded) WAMP component will
look unresponsive from outside (to the router), and the router e.g.
won’t be able to interrupt a call into your component (since the code
therein is “busy” sitting and waiting for the DB to return).

To work around blocking DB libs in an asynch context, the usual pattern
is to not block the main thread running the event loop and execute any
blocking stuff on a background thread pool.

nodejs works like this. Twisted and asyncio work like this.

Also: do you really need to do the DB access from C++?

You could encapsulate DB access in a WAMP component written in a more
friendly language (better: a language that has already solved blocking
DB libs and async). And then just call into the former component from
your C++ component.

WAMP is about making an app out of decoupled components - potentially
written in multiple languages. Having “data access” separated into a
component used by other sounds fine for me. And you can use the polyglot
power of WAMP here … don’t bother with C++ heavy artillery if you don’t
have to;)

===

Contrast:

async programming is great if your code would otherwise just sit and
wait (like for I/O).

If you run CPU intensive stuff, your code is actually doing useful work
(not just waiting). And this is where shared registrations come in.

Hopefully I am not triggering more questsions than answering ones;)

Cheers,

/Tobias

is correct.

Thanks,

Rosa

You received this message because you are subscribed to the Google

Groups “Autobahn” group.

To unsubscribe from this group and stop receiving emails from it, send

an email to autobahnws+...@googlegroups.com

mailto:autobahnws+unsub...@googlegroups.com.

To post to this group, send email to auto...@googlegroups.com

mailto:autob...@googlegroups.com.

To view this discussion on the web visit

https://groups.google.com/d/msgid/autobahnws/8af04765-ed53-4c96-87a6-ef2a621e3931%40googlegroups.com

<https://groups.google.com/d/msgid/autobahnws/8af04765-ed53-4c96-87a6-ef2a621e3931%40googlegroups.com?utm_medium=email&utm_source=footer>.

For more options, visit https://groups.google.com/d/optout.

0 Likes