Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An example of properly setting up queue topics #16

Open
atoi opened this issue Jan 2, 2016 · 2 comments
Open

An example of properly setting up queue topics #16

atoi opened this issue Jan 2, 2016 · 2 comments
Labels

Comments

@atoi
Copy link

atoi commented Jan 2, 2016

I'm playing around with the plugin to understand how to use it properly and to see if it suits my needs.
My goal is to build a microservice system with components talking to each other by sending messages to the queue.

Let's start from something simple:

const seneca = require('seneca');

seneca()
  .use('rabbitmq-transport')
  .add('role:test, cmd:ping', function(params, done) {
    done(null, { result: 'pong' });
  })
  .listen({ type: 'rabbitmq' });

seneca()
  .use('rabbitmq-transport')
  .client({ type: 'rabbitmq' })
  .act('role:test, cmd:ping', function() {
    console.log(arguments);
  });

Which results to:

  • Server listens to seneca_any_act topic and writes to seneca_any_res
  • Client listens to seneca_any_res topic and writes to seneca_any_act
  • We get our { result: 'pong' } response

Of course, this setup is not suitable for real usage, as each service looks for actions in the same topic. Let's change that, adding a pin option to server transport config:

const seneca = require('seneca');

seneca()
  .use('rabbitmq-transport')
  .add('role:test, cmd:ping', function(params, done) {
    done(null, { result: 'pong' });
  })
  .listen({ type: 'rabbitmq', pin: 'role:test' });

seneca()
  .use('rabbitmq-transport')
  .client({ type: 'rabbitmq' })
  .act('role:test, cmd:ping', function() {
    console.log(arguments);
  });

And the result is:

  • Server now listens to seneca_cmd_ping_role_test__act and writes to seneca_cmd_ping_role_test__res
  • Client still writes to seneca_any_act and listens to seneca_any_res
  • So, server never gets the action, never responds to it and client throws timeout error

Hmm, ok. Let's add a pin to client configuration as well, so it generates the same topic names as our server:

const seneca = require('seneca');

seneca()
  .use('rabbitmq-transport')
  .add('role:test, cmd:ping', function(params, done) {
    done(null, { result: 'pong' });
  })
  .listen({ type: 'rabbitmq', pin: 'role:test' });

seneca()
  .use('rabbitmq-transport')
  .client({ type: 'rabbitmq', pin: 'role:test' })
  .act('role:test, cmd:ping', function() {
    console.log(arguments);
  });

And we get somewhat unexpected result:

  • Server: seneca_cmd_ping_role_test__act / seneca_cmd_ping_role_test__res
  • Client: seneca_role_test__res / seneca_role_test__act
  • Action, obviously, fails again

Ok, let's scratch our head a little and try the following setup, which finally works:

const seneca = require('seneca');

seneca()
  .use('rabbitmq-transport')
  .add('role:test, cmd:ping', function(params, done) {
    done(null, { result: 'pong' });
  })
  .listen({ type: 'rabbitmq', pin: 'role:test' });

seneca()
  .use('rabbitmq-transport')
  .client({ type: 'rabbitmq', pin: 'role:test, cmd:*' })
  .act('role:test, cmd:ping', function() {
    console.log(arguments);
  });

So, the question is:
Do I really have to pin client like that? That seems like too much for me. Let's imagine our test microservice has not only cmd, but task, queue and some others types of actions. I would need to setup a client for each of them.

And another related question is:
In a case when we have multiple clients talking to the same server and calling the same function, they all listen to the same topic for responses. Is there a way to ensure a client gets a response that 'belongs' to its request and not some other's one? If not, is there a way to tell the server to write to different response topics (one for each client)?

@geek geek added the question label Jan 4, 2016
@geek
Copy link
Collaborator

geek commented Jan 4, 2016

The pattern matching in each service should avoid the issue you are pointing to in the first example, right? We may be acknowledging the message too quickly without validating that it matches a known pattern.

Did you try with multiple services and consumers?

@nfantone
Copy link

@atoi Take a look at seneca-amqp-transport. It should have the functionality that you need already implemented on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants