dashersw / cote

A Node.js library for building zero-configuration microservices.
http://cote.js.org
MIT License
2.35k stars 187 forks source link

Cote requester doesn't send all requests #276

Open EmillkaakillmE opened 2 days ago

EmillkaakillmE commented 2 days ago

I use cote with socket io. My socket accepts two events in a row. All of them goes to requester and sends to other cote responder

The issue is that requester sends only one of two requests for some reason..

socket.on('request', async (request) => {
    try {
      console.log(request);
      const coteRequest = {
        type: `${request.app}.${request.key}`,
        data: request.data,
      };
      requester.send(coteRequest, (response) => {
        console.info('Request:');
        console.log(coteRequest);
        console.info('Response:');
        console.log(response);
        socket.emit(response.socketEvent, response.data);
      });
    } catch (error) {
      console.error('Cote request failed:');
      console.error(error);
    }
  });

As you can see here I log two requests from socket and only one from cote: image

EmillkaakillmE commented 2 days ago

Probably the problem is that cote cant send multiple requests in short amount of time. I wrote some kinda improvised queue

const reqs = [];
  socket.on('request', async (request) => {
    reqs.push(request);
  });

And than

//FIXME remake it without setInterval
  setInterval(async () => {
    if (!reqs.length) return;

    console.log('reqs');
    console.log(reqs);

    const coteRequest = {
      type: `${reqs[0].app}.${reqs[0].key}`,
      data: reqs[0].data,
    };

    await requester.send(coteRequest, (response) => {
      console.info('Request:');
      console.log(coteRequest);
      console.info('Response:');
      console.log(response);
      socket.emit(response.socketEvent, response.data);

      reqs.splice(0, 1);
    });
  }, 1000);

But it's not optimized and very bad decision:( Looking forward for fix

dashersw commented 2 days ago

How is your responder configured? It's possible that you have two responders responding to two separate messages, but that's not how cote works. You need to shard responders with a namespace, key or environment if you want them to respond to different messages.

By the way, cote already has a sockend component that automatically routes these messages, so you don't have to build your own socket.io bridge.

EmillkaakillmE commented 1 day ago

In this example all requests are going to one responder. But yeah, I was gonna use separate responders for on requester. It would be one requester and requests would go to all responders, but with different types in request. So only one responder would react. So it's a bad idea?

I use socket io for my frontend/backend communications, and cote for interaction between microservices. My frontend hit request to socket, socket via cote sends request to microservice and gets response that goes back to frontend. So socket io is essential for project😅 Or you saying I can use cote instead of sockets at all?

dashersw commented 1 day ago

Yes, you can use cote for frontend/backend communication. It uses socket.io in the background.

EmillkaakillmE commented 1 day ago

Is it possible for cote to update sockets version in near future? It uses "^2.3.0" and we use ^4.6.2

EmillkaakillmE commented 1 day ago

And can cote send data to particular socket id? Or broadcast events?

dashersw commented 1 day ago

Oh let me check if it's a straight version upgrade.

dashersw commented 1 day ago

And yes, cote can do pretty much everything you'd want from a socket.io bridge.

dashersw commented 1 day ago

I released cote 1.2.0 that works with socket.io 4.8.1—it was a straightforward upgrade. Please give it a try.