make RPC call from outside factory

#1

Hi,

When using PubSub, I am able to publish a message from outside my WampClientProtocol definition using:

self.factory.dispatch(TOPIC_URI + ‘event’, json.loads(body))

I’m trying to do the same thing with RPC but the above doesn’t work. Any help would be greatly appreciated.

Thanks,

Gerald

0 Likes

#2

Hi,

When using PubSub, I am able to publish a message from outside my
WampClientProtocol definition using:

self.factory.dispatch(TOPIC_URI + 'event', json.loads(body))

I'm trying to do the same thing with RPC but the above doesn't work. Any
help would be greatly appreciated.

In general, dispatch() is intended to be used on peers that act as message brokers.

For peers acting as publishers, there is publish().

IOW: you should arrange stuff so you can call "publish()" and "call()" on the protocol instance from somewhere else in your app.

Your problem is more a general Twisted usage one: for a connected client, there is a Twisted protocol instance for this connection (in your case, a WampClientProtocol instance which derives from the Twisted base protocol class), and a Twisted client factory that has a lifetime longer than the connection. And then you have stuff outside of both and want to "get into the protocol instance".

One solution is to override buildProtocol on the client factory and store the client protocol instance created there somewhere reachable from where you want to call it, and remove (set None) the reference when the client connection is lost.

Here are a couple of examples that show how to wire up different parts. Probably not totally easy to follow.

https://github.com/oberstet/scratchbox/tree/master/python/gephi
https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws
https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus

Hope this gets you started,
Tobias

···

Am 19.06.2013 22:23, schrieb Gerald Manipon:

Thanks,

Gerald

--
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.
For more options, visit https://groups.google.com/groups/opt_out.

0 Likes

#3

Thanks for the pointers, Tobias. The following factory definition did it:

class MyServerFactory(WampServerFactory):

protocol = MyServerProtocol

def init(self, url, debugWamp=False):

WampServerFactory.init(self, url, debugWamp)

self.pika_consumer = PikaConsumer(self)

def buildProtocol(self, addr):

p = self.protocol()

p.factory = self

self.my_protocol = p

return p

def clientConnectionLost(self, connector, reason):

self.my_protocol = None

And from the self.pika_consumer object I can call:

self.factory.my_protocol.call(TOPIC_URI + ‘event’, json.loads(body)).addCallback(self.testCallback)

to make the RPC call to the client.

However when I have multiple clients connected, the RPC call is made only to the most recently connected client. I would like to be able to specify which client to send it to. Is there a way to do that using symmetric RPC? Will I have to do my own bookkeeping?

Thanks,

Gerald

···

On Wednesday, June 19, 2013 2:24:53 PM UTC-7, Tobias Oberstein wrote:

Am 19.06.2013 22:23, schrieb Gerald Manipon:

Hi,

When using PubSub, I am able to publish a message from outside my

WampClientProtocol definition using:

self.factory.dispatch(TOPIC_URI + ‘event’, json.loads(body))

I’m trying to do the same thing with RPC but the above doesn’t work. Any

help would be greatly appreciated.

In general, dispatch() is intended to be used on peers that act as
message brokers.

For peers acting as publishers, there is publish().

IOW: you should arrange stuff so you can call “publish()” and “call()”
on the protocol instance from somewhere else in your app.

Your problem is more a general Twisted usage one: for a connected
client, there is a Twisted protocol instance for this connection (in
your case, a WampClientProtocol instance which derives from the Twisted
base protocol class), and a Twisted client factory that has a lifetime
longer than the connection. And then you have stuff outside of both and
want to “get into the protocol instance”.

One solution is to override buildProtocol on the client factory and
store the client protocol instance created there somewhere reachable
from where you want to call it, and remove (set None) the reference when
the client connection is lost.

Here are a couple of examples that show how to wire up different parts.
Probably not totally easy to follow.

https://github.com/oberstet/scratchbox/tree/master/python/gephi

https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws

https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus

Hope this gets you started,

Tobias

Thanks,

Gerald

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.

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

0 Likes

#4

However when I have multiple clients connected, the RPC call is made
only to the most recently connected client. I would like to be able to
specify which client to send it to. Is there a way to do that using
symmetric RPC? Will I have to do my own bookkeeping?

Not sure I get what you a trying to do. Multiple concurrently connected clients will involve multiple client factories. This may seem a little counterintuitive at first glance, but thats how Twisted works. A server factory produces protocol instances for multiple (concurrent) connections, whereas a client factory produces a single protocol instance only (unless you are reconnecting).

···

Thanks,

Gerald

On Wednesday, June 19, 2013 2:24:53 PM UTC-7, Tobias Oberstein wrote:

    Am 19.06.2013 22:23, schrieb Gerald Manipon:
     > Hi,
     >
     > When using PubSub, I am able to publish a message from outside my
     > WampClientProtocol definition using:
     >
     > self.factory.dispatch(TOPIC_URI + 'event', json.loads(body))
     >
     > I'm trying to do the same thing with RPC but the above doesn't
    work. Any
     > help would be greatly appreciated.

    In general, dispatch() is intended to be used on peers that act as
    message brokers.

    For peers acting as publishers, there is publish().

    IOW: you should arrange stuff so you can call "publish()" and "call()"
    on the protocol instance from somewhere else in your app.

    Your problem is more a general Twisted usage one: for a connected
    client, there is a Twisted protocol instance for this connection (in
    your case, a WampClientProtocol instance which derives from the Twisted
    base protocol class), and a Twisted client factory that has a lifetime
    longer than the connection. And then you have stuff outside of both and
    want to "get into the protocol instance".

    One solution is to override buildProtocol on the client factory and
    store the client protocol instance created there somewhere reachable
    from where you want to call it, and remove (set None) the reference
    when
    the client connection is lost.

    Here are a couple of examples that show how to wire up different parts.
    Probably not totally easy to follow.

    https://github.com/oberstet/scratchbox/tree/master/python/gephi
    <https://github.com/oberstet/scratchbox/tree/master/python/gephi>
    https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws
    <https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws>

    https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus
    <https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus>

    Hope this gets you started,
    Tobias

     >
     > Thanks,
     >
     > Gerald
     >
     > --
     > 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 autobah...@googlegroups.com <javascript:>.
     > For more options, visit https://groups.google.com/groups/opt_out
    <https://groups.google.com/groups/opt_out>.
     >

--
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.
For more options, visit https://groups.google.com/groups/opt_out.

0 Likes

#5

However when I have multiple clients connected, the RPC call is made

only to the most recently connected client. I would like to be able to

specify which client to send it to. Is there a way to do that using

symmetric RPC? Will I have to do my own bookkeeping?

Not sure I get what you a trying to do. Multiple concurrently connected
clients will involve multiple client factories. This may seem a little
counterintuitive at first glance, but thats how Twisted works. A server
factory produces protocol instances for multiple (concurrent)
connections, whereas a client factory produces a single protocol
instance only (unless you are reconnecting).

I have a RabbitMQ queue that the server is consuming messages off of and based on the content of that message, would like to make an RPC call to a specific client. From what you described, every client that connects to my server is spawning up a protocol instance that is looking at the same RabbitMQ queue. I think I’m going down the wrong path.

I guess my question should be then what’s the best way to setup symmetric RPC where both the server and client are consuming from a rabbitmq queue on their respective machine? We’re using the queues to signal events to the running process to make a certain RPC call to the other side.

Thanks,

Gerald

···

On Thursday, June 20, 2013 10:45:56 AM UTC-7, Tobias Oberstein wrote:

Thanks,

Gerald

On Wednesday, June 19, 2013 2:24:53 PM UTC-7, Tobias Oberstein wrote:

Am 19.06.2013 22:23, schrieb Gerald Manipon:
 > Hi,
 >
 > When using PubSub, I am able to publish a message from outside my
 > WampClientProtocol definition using:
 >
 > self.factory.dispatch(TOPIC_URI + 'event', json.loads(body))
 >
 > I'm trying to do the same thing with RPC but the above doesn't
work. Any
 > help would be greatly appreciated.
In general, dispatch() is intended to be used on peers that act as
message brokers.
For peers acting as publishers, there is publish().
IOW: you should arrange stuff so you can call "publish()" and "call()"
on the protocol instance from somewhere else in your app.
Your problem is more a general Twisted usage one: for a connected
client, there is a Twisted protocol instance for this connection (in
your case, a WampClientProtocol instance which derives from the Twisted
base protocol class), and a Twisted client factory that has a lifetime
longer than the connection. And then you have stuff outside of both and
want to "get into the protocol instance".
One solution is to override buildProtocol on the client factory and
store the client protocol instance created there somewhere reachable
from where you want to call it, and remove (set None) the reference
when
the client connection is lost.
Here are a couple of examples that show how to wire up different parts.
Probably not totally easy to follow.
[https://github.com/oberstet/scratchbox/tree/master/python/gephi](https://github.com/oberstet/scratchbox/tree/master/python/gephi)
<[https://github.com/oberstet/scratchbox/tree/master/python/gephi](https://github.com/oberstet/scratchbox/tree/master/python/gephi)>
[https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws](https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws)
<[https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws](https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws)>
[https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus](https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus)
<[https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus](https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus)>
Hope this gets you started,
Tobias
 >
 > Thanks,
 >
 > Gerald
 >
 >
 > --
 > 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 <javascript:>.
 > For more options, visit [https://groups.google.com/groups/opt_out](https://groups.google.com/groups/opt_out)
<[https://groups.google.com/groups/opt_out](https://groups.google.com/groups/opt_out)>.
 >
 >

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.

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

0 Likes

#6

     > However when I have multiple clients connected, the RPC call is made
     > only to the most recently connected client. I would like to be
    able to
     > specify which client to send it to. Is there a way to do that using
     > symmetric RPC? Will I have to do my own bookkeeping?

    Not sure I get what you a trying to do. Multiple concurrently connected
    clients will involve multiple client factories. This may seem a little
    counterintuitive at first glance, but thats how Twisted works. A server
    factory produces protocol instances for multiple (concurrent)
    connections, whereas a client factory produces a single protocol
    instance only (unless you are reconnecting).

I have a RabbitMQ queue that the server is consuming messages off of and
based on the content of that message, would like to make an RPC call to
a specific client. From what you described, every client that connects
to my server is spawning up a protocol instance that is looking at the
same RabbitMQ queue. I think I'm going down the wrong path.

Obviously, you are trying somethign non-trivial, and I'm not sure if I understand correctly. Also, I take as given that you want to use RabbitMQ for message brokering, not Autobahn, which also provides this functionality.

Here is what I would try:

On your server app, have a client (singleton) "BC1" that connects to RabbitMQ. The RabbitMQ client receives messages from the broker.

Within each message, there is some info that can be used to map to a WAMP/WebSocket frontend client. Hence you need a app-wide map "M" (singleton) for that, and the frontend clients need to identify themselfes in a persistent way (when a frontend client reconnects, it needs to be identified again).

A frontend client "C" connects to your server app. Each connected client is represented via an instance of WampServerProtocol. You can call RPC endpoints exposed on those frontend clients from "BC1" via "M" which should map to the "C"s.

Thus, you need to do some bookkeeping.

Currently, you can only call client RPC endpoints from a WampServerProtocol instance.

In upcoming version of Autobahn, you will be able to call RPC endpoints from WampServerFactory. The factory will know which client has exported what endpoints under what URI and dispatch accordingly. Obviously, clients cannot have colliding URIs registered, and the URIs would contain some persistent client identifier. Hence, that will spare you some bookkeeping.

E.g. client 1 registers RPC endpoint:

http://example.com/sensor1/configure

and client2:

http://example.com/sensor2/configure

Calling "http://example.com/sensor2/configure" on WampServerFactory will dispatch that to the WampServerProtocol instance for the connected client2 (_if_ that client _is_ connected, otherwise the RPC would fail .. unknow endpoint).

I guess my question should be then what's the best way to setup
symmetric RPC where both the server and client are consuming from a
rabbitmq queue on their respective machine? We're using the queues to

Sorry, I don't understand.

signal events to the running process to make a certain RPC call to the
other side.

Hope that helps,

/Tobias

···

Am 20.06.2013 21:45, schrieb Gerald Manipon:

On Thursday, June 20, 2013 10:45:56 AM UTC-7, Tobias Oberstein wrote:

Thanks,

Gerald

     >
     > Thanks,
     >
     > Gerald
     >
     > On Wednesday, June 19, 2013 2:24:53 PM UTC-7, Tobias Oberstein > wrote:
     >
     > Am 19.06.2013 22:23, schrieb Gerald Manipon:
     > > Hi,
     > >
     > > When using PubSub, I am able to publish a message from
    outside my
     > > WampClientProtocol definition using:
     > >
     > > self.factory.dispatch(TOPIC_URI + 'event', json.loads(body))
     > >
     > > I'm trying to do the same thing with RPC but the above
    doesn't
     > work. Any
     > > help would be greatly appreciated.
     >
     > In general, dispatch() is intended to be used on peers that
    act as
     > message brokers.
     >
     > For peers acting as publishers, there is publish().
     >
     > IOW: you should arrange stuff so you can call "publish()" and
    "call()"
     > on the protocol instance from somewhere else in your app.
     >
     > Your problem is more a general Twisted usage one: for a
    connected
     > client, there is a Twisted protocol instance for this
    connection (in
     > your case, a WampClientProtocol instance which derives from
    the Twisted
     > base protocol class), and a Twisted client factory that has a
    lifetime
     > longer than the connection. And then you have stuff outside
    of both and
     > want to "get into the protocol instance".
     >
     > One solution is to override buildProtocol on the client
    factory and
     > store the client protocol instance created there somewhere
    reachable
     > from where you want to call it, and remove (set None) the
    reference
     > when
     > the client connection is lost.
     >
     > Here are a couple of examples that show how to wire up
    different parts.
     > Probably not totally easy to follow.
     >
     > https://github.com/oberstet/scratchbox/tree/master/python/gephi
    <https://github.com/oberstet/scratchbox/tree/master/python/gephi>
     >
    <https://github.com/oberstet/scratchbox/tree/master/python/gephi
    <https://github.com/oberstet/scratchbox/tree/master/python/gephi>>
     >
    https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws
    <https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws>

     >
    <https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws
    <https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/serial2ws>>

     >
    https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus
    <https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus>

     >
    <https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus
    <https://github.com/tavendo/AutobahnPython/tree/master/examples/wamp/dbus>>

     >
     > Hope this gets you started,
     > Tobias
     >
     > >
     > > Thanks,
     > >
     > > Gerald
     > >
     > > --
     > > 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 autobah...@googlegroups.com <javascript:>.
     > > For more options, visit
    https://groups.google.com/groups/opt_out
    <https://groups.google.com/groups/opt_out>
     > <https://groups.google.com/groups/opt_out
    <https://groups.google.com/groups/opt_out>>.
     > >
     >
     > --
     > 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 autobah...@googlegroups.com <javascript:>.
     > For more options, visit https://groups.google.com/groups/opt_out
    <https://groups.google.com/groups/opt_out>.
     >

--
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.
For more options, visit https://groups.google.com/groups/opt_out.

0 Likes