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

Duplex messaging between client and server #317

Open
georgolden opened this issue Jul 13, 2022 · 9 comments
Open

Duplex messaging between client and server #317

georgolden opened this issue Jul 13, 2022 · 9 comments

Comments

@georgolden
Copy link
Member

georgolden commented Jul 13, 2022

Is your feature request related to a problem? Please describe.

We now have only one way messaging via metacom,

// Client send message with rpc call
const result = await api.iterfaceName.method({ message });

// Server send message to a client
client.emit('iterfaceName/event', { message });

// Client receive messages
api.iterfaceName.on('event', ({ message } => process(message));

But nothing to receive messages from clients server side and nothing to send events to a server from client.

Describe the solution you'd like

I propose to enhance existing functionality with this solution:

// Cleint emits an event to a server
api.interfaceName.emit('event', { message });

// Server receive an event from client
api.interfaceName.on('event', ({ message }) => {
  if (message === 'hello') context.client.emit('interfaceName/event', 'hi');
});

Additional context

@tshemsedinov @rohiievych please suggest your alternatives, if anything can be done better.

@rohiievych
Copy link
Member

rohiievych commented Jul 14, 2022

How this approach differs from the regular RPC call from client to server?
If you subscribe on client events, this will have the same effect as RPC because we have connection.on('message', () => {}) in WsChannel, which is actually low level implementation of api.interfaceName.processEvent(({ message }) => {}).

@georgolden
Copy link
Member Author

This is different from low-level implementation, because there will be metadata in a packet as well. So packet will be recognized by metadata. In some cases, we need async messaging, e.g. some user activity tracking. So basically RPC - remote procedure call. We run procedure in server and expecting response/error within the call directly. Async messaging - we don't care about immediate response. Notifications, user's actions tracking, any similar functionality

@georgolden
Copy link
Member Author

connection.on('message', () => is far not the same as api.interfaceName.processEvent(({ message }) => {}). There is an interfaceName metadata provided withing the packet. So this is an alternative solution, and it looks worse than proposed.

@rohiievych
Copy link
Member

Let me clarify - by saying low level implementation I mean connection.on('message', (msg) => {}), which is placed in WsChannel class and works as a subscription to client messages including protocol metadata like interface name.
It means that api.interfaceName.processEvent(({ message }) => {}) will need additional message subscription.
But do we really need it, while it can be implemented as a simple interface call, where user's metadata is defined by the user and the result of that call is ignored and not awaited?

@georgolden
Copy link
Member Author

The alternative solution just brought confusion to the topic. I removed it. So speaking about proposed solution. It is just mirroring existing functionality, and of course I see this useful to have in metacom. So developer don't need to go to a low level at all and stay within the metacom only, cause metacom is a high-level network library compare to raw WS

@georgolden
Copy link
Member Author

Server-side, we have no direct link to a WS connection available. This would break our abstraction layers. So we need to have such functionality implemented. For client, I am sure it is the same. By design, we don't need to go directly to a WS connection, just to not break abstraction layers/

@rohiievych
Copy link
Member

@tshemsedinov
Need your thoughts on this issue

@tshemsedinov
Copy link
Member

Client code is ok for me, but server-side event handler I'd like to have, for example, file onEventName.js with the following code:

({ message }) => {
  if (message === 'hello') {
    context.client.emit('interfaceName/event', 'hi');
  }
};

@zaitsev-oleksii
Copy link
Contributor

zaitsev-oleksii commented Aug 11, 2022

Can we implement server-side event handlers as it is?
We have application.getMethod(iname, ver, methodName) in impress for rpc calls, but don't have analogue for events
(sth like application.getEvent(iname, eventName))
We can do client-side event emitting though.

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

No branches or pull requests

4 participants