RpcProxy inside method

Hi,

I have a collection of sub-services that I want to spawn from a master
service, they all share a common prefix in the method name. For example
`import-a`, `import-b`, etc

So I was thinking something along the lines of instantiating the RpcProxy
instance at runtime, inside the master service method. But I can't figure
out the 'right' way to do it.

So for example (and I know this won't work):

from nameko.rpc import rpc, RpcProxy

class Importer:
    name = "import"

    @rpc
    def run(self, servicename, value):
        r = RpcProxy('{}-{}'.format(self.name, servicename))
        return r.run(value)

class ImportA:
    name = "import-a"

    @rpc
    def run(self, value):
        return '{} ran with {}'.format(self.name, value)

class ImportB:
    name = "import-b"

    @rpc
    def run(self, value):
        return '{} ran with {}'.format(self.name, value)

Then later, I could write and start an `import-c` service, and nothing else
needs to change.

Any thoughts?

Geoff

We have more or less the same problematic, and we solved it with an
extension that spawn ServiceProxy.

Here's a snippet

from nameko.extensions import DependencyProvider
from nameko.rpc import ServiceProxy, ReplyListener

class RpcProxyFactory(object):

    def __init__(self, worker_ctx, reply_listener):
        self.worker_ctx = worker_ctx
        self.reply_listener = reply_listener

    def __call__(self, target_service):
        return ServiceProxy(self.worker_ctx, target_service,
self.reply_listener)

class DynamicRpcProxy(DependencyProvider):
    rpc_reply_listener = ReplyListener()

    def get_dependency(self, worker_ctx):
return RpcProxyFactory(worker_ctx, self.rpc_reply_listener)

class Service(object):
    dynamic_rpc_proxy = DynamicRpcProxy()

    def run(self, value):
        sub_service_a = dynamic_rpc_proxy("sub_service_a")
        sub_service_a.run("hello")  # returns "sub_service_a-hello"

class SubServiceA(object):
    name = "sub_service_a"

    def run(self, value):
        return "{}-{}".format(self.name, value)

Hope this helps.
Also, I'm not too sure what I'm doing here. Therefore, any comment on this
snippet is most welcome.

Manfred

···

2017-10-18 0:08 GMT+02:00 <jukowitz@gmail.com>:

Hi,

I have a collection of sub-services that I want to spawn from a master
service, they all share a common prefix in the method name. For example
`import-a`, `import-b`, etc

So I was thinking something along the lines of instantiating the RpcProxy
instance at runtime, inside the master service method. But I can't figure
out the 'right' way to do it.

So for example (and I know this won't work):

from nameko.rpc import rpc, RpcProxy

class Importer:
    name = "import"

    @rpc
    def run(self, servicename, value):
        r = RpcProxy('{}-{}'.format(self.name, servicename))
        return r.run(value)

class ImportA:
    name = "import-a"

    @rpc
    def run(self, value):
        return '{} ran with {}'.format(self.name, value)

class ImportB:
    name = "import-b"

    @rpc
    def run(self, value):
        return '{} ran with {}'.format(self.name, value)

Then later, I could write and start an `import-c` service, and nothing
else needs to change.

Any thoughts?

Geoff

--
You received this message because you are subscribed to the Google Groups
"nameko-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to nameko-dev+unsubscribe@googlegroups.com.
To post to this group, send email to nameko-dev@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/
msgid/nameko-dev/407ee317-fbbf-41ce-b619-b67d062a64e4%40googlegroups.com
<https://groups.google.com/d/msgid/nameko-dev/407ee317-fbbf-41ce-b619-b67d062a64e4%40googlegroups.com?utm_medium=email&utm_source=footer&gt;
.
For more options, visit https://groups.google.com/d/optout\.

--
* Manfred Chebli*
Ingénieur Logiciel

04 78 18 75 38 | manfred.chebli@forcity.io

  <https://www.linkedin.com/company/forcity&gt;
<https://twitter.com/forcity_co&gt; <http://www.forcity.com>
<http://www.forcity.com/forcity-start-en-hyper-croissance-laureate-du-pass-french-tech/&gt;

I thought I'd follow up on myself here.

Manfred's solution worked well for me. But I didn't run with it.

After further thought, I realized that I could achieve the same result far
more effectively using the Events system. So rather than sending a task to
a specific process, I publish the task in a way that includes details on
'who' should run it. Then all the interested processes receive and act
accordingly. This gave me what I ultimately required, which is the ability
to add more services that could act upon the task.

I'm finding (quite often) that if I can't do something obviously in Nameko,
I'm probably thinking about it wrong :slight_smile:

Awesome!

This is pretty much the simplest implementation of a "dynamic RPC proxy"
possible, because it reuses so much of the built-in extension. I think it's
a neat way to solve exactly the problem Geoff describes.

···

On Wednesday, October 18, 2017 at 8:17:37 AM UTC+1, Manfred Chebli wrote:

We have more or less the same problematic, and we solved it with an
extension that spawn ServiceProxy.

Here's a snippet

from nameko.extensions import DependencyProvider
from nameko.rpc import ServiceProxy, ReplyListener

class RpcProxyFactory(object):

    def __init__(self, worker_ctx, reply_listener):
        self.worker_ctx = worker_ctx
        self.reply_listener = reply_listener

    def __call__(self, target_service):
        return ServiceProxy(self.worker_ctx, target_service, 
self.reply_listener)

class DynamicRpcProxy(DependencyProvider):
    rpc_reply_listener = ReplyListener()

    def get_dependency(self, worker_ctx):
return RpcProxyFactory(worker_ctx, self.rpc_reply_listener)

class Service(object):
    dynamic_rpc_proxy = DynamicRpcProxy()

    def run(self, value):
        sub_service_a = dynamic_rpc_proxy("sub_service_a")
        sub_service_a.run("hello")  # returns "sub_service_a-hello"

class SubServiceA(object):
    name = "sub_service_a"

    def run(self, value):
        return "{}-{}".format(self.name, value)

Hope this helps.
Also, I'm not too sure what I'm doing here. Therefore, any comment on this
snippet is most welcome.

Manfred

2017-10-18 0:08 GMT+02:00 <jukowitz@gmail.com>:

Hi,

I have a collection of sub-services that I want to spawn from a master
service, they all share a common prefix in the method name. For example
`import-a`, `import-b`, etc

So I was thinking something along the lines of instantiating the RpcProxy
instance at runtime, inside the master service method. But I can't figure
out the 'right' way to do it.

So for example (and I know this won't work):

from nameko.rpc import rpc, RpcProxy

class Importer:
    name = "import"

    @rpc
    def run(self, servicename, value):
        r = RpcProxy('{}-{}'.format(self.name, servicename))
        return r.run(value)

class ImportA:
    name = "import-a"

    @rpc
    def run(self, value):
        return '{} ran with {}'.format(self.name, value)

class ImportB:
    name = "import-b"

    @rpc
    def run(self, value):
        return '{} ran with {}'.format(self.name, value)

Then later, I could write and start an `import-c` service, and nothing
else needs to change.

Any thoughts?

Geoff

--
You received this message because you are subscribed to the Google Groups
"nameko-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to nameko-dev+unsubscribe@googlegroups.com.
To post to this group, send email to nameko-dev@googlegroups.com.
To view this discussion on the web, visit
https://groups.google.com/d/msgid/nameko-dev/407ee317-fbbf-41ce-b619-b67d062a64e4%40googlegroups.com
<https://groups.google.com/d/msgid/nameko-dev/407ee317-fbbf-41ce-b619-b67d062a64e4%40googlegroups.com?utm_medium=email&utm_source=footer&gt;
.
For more options, visit https://groups.google.com/d/optout\.

--
* Manfred Chebli*
Ingénieur Logiciel

04 78 18 75 38 | manfred.chebli@forcity.io
  
  <https://www.linkedin.com/company/forcity&gt;
<https://twitter.com/forcity_co&gt; <http://www.forcity.com>
<http://www.forcity.com/forcity-start-en-hyper-croissance-laureate-du-pass-french-tech/&gt;

Thanks Manfred! This is extremely useful

···

On Wednesday, October 18, 2017 at 12:17:37 AM UTC-7, Manfred Chebli wrote:

We have more or less the same problematic, and we solved it with an
extension that spawn ServiceProxy.

Here's a snippet

from nameko.extensions import DependencyProvider
from nameko.rpc import ServiceProxy, ReplyListener

class RpcProxyFactory(object):

    def __init__(self, worker_ctx, reply_listener):
        self.worker_ctx = worker_ctx
        self.reply_listener = reply_listener

    def __call__(self, target_service):
        return ServiceProxy(self.worker_ctx, target_service, 
self.reply_listener)

class DynamicRpcProxy(DependencyProvider):
    rpc_reply_listener = ReplyListener()

    def get_dependency(self, worker_ctx):
return RpcProxyFactory(worker_ctx, self.rpc_reply_listener)

class Service(object):
    dynamic_rpc_proxy = DynamicRpcProxy()

    def run(self, value):
        sub_service_a = dynamic_rpc_proxy("sub_service_a")
        sub_service_a.run("hello")  # returns "sub_service_a-hello"

class SubServiceA(object):
    name = "sub_service_a"

    def run(self, value):
        return "{}-{}".format(self.name, value)

Hope this helps.
Also, I'm not too sure what I'm doing here. Therefore, any comment on this
snippet is most welcome.

Manfred

2017-10-18 0:08 GMT+02:00 <juko...@gmail.com <javascript:>>:

Hi,

I have a collection of sub-services that I want to spawn from a master
service, they all share a common prefix in the method name. For example
`import-a`, `import-b`, etc

So I was thinking something along the lines of instantiating the RpcProxy
instance at runtime, inside the master service method. But I can't figure
out the 'right' way to do it.

So for example (and I know this won't work):

from nameko.rpc import rpc, RpcProxy

class Importer:
    name = "import"

    @rpc
    def run(self, servicename, value):
        r = RpcProxy('{}-{}'.format(self.name, servicename))
        return r.run(value)

class ImportA:
    name = "import-a"

    @rpc
    def run(self, value):
        return '{} ran with {}'.format(self.name, value)

class ImportB:
    name = "import-b"

    @rpc
    def run(self, value):
        return '{} ran with {}'.format(self.name, value)

Then later, I could write and start an `import-c` service, and nothing
else needs to change.

Any thoughts?

Geoff

--
You received this message because you are subscribed to the Google Groups
"nameko-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to nameko-dev+...@googlegroups.com <javascript:>.
To post to this group, send email to namek...@googlegroups.com
<javascript:>.
To view this discussion on the web, visit
https://groups.google.com/d/msgid/nameko-dev/407ee317-fbbf-41ce-b619-b67d062a64e4%40googlegroups.com
<https://groups.google.com/d/msgid/nameko-dev/407ee317-fbbf-41ce-b619-b67d062a64e4%40googlegroups.com?utm_medium=email&utm_source=footer&gt;
.
For more options, visit https://groups.google.com/d/optout\.

--
* Manfred Chebli*
Ingénieur Logiciel

04 78 18 75 38 | manfred...@forcity.io <javascript:>
  
  <https://www.linkedin.com/company/forcity&gt;
<https://twitter.com/forcity_co&gt; <http://www.forcity.com>
<http://www.forcity.com/forcity-start-en-hyper-croissance-laureate-du-pass-french-tech/&gt;