gdaws/stompit

Preferable way to unsubscribe on topics

Closed this issue · 3 comments

Hello! Could you share the best way for using unsubscribe for topics? I was trying to use subscription's unsubscribe in message.readString callback, like here (the goal is to get just a first message, not more):

const subscribeHeaders = {
   destination: `/topic/virginia/${message.meta.mqTxId}`,
};
self.client.subscribe(subscribeHeaders, function(error, message, subscription) {
        if (error) {
          return reject(error);
        }

        message.readString('UTF-8', (err, body) => {
          if (err) {
            return reject(err);
          }

          resolve(JSON.parse(body));
          subscription.unsubscribe();
        });
      });

But on high load the onMessage method throw the error about undefined subscription (caused
by unsubscribe, at least it looks so).

ERROR uncaughtException: invalid subscription id 192 

@gdaws, need your advice, please. Thank you!

gdaws commented

Hi @pavelrudenya, apologies for the late response.

The way you've used unsubscribe looks fine. It shouldn't be causing the error you quoted. It's safe to call unsubscribe anywhere inside the subscribe callback (excluding error branches).

To see 'invalid subscription' error means the server or client is not behaving correctly. The server is sending messages after the client has received the receipt for the unsubscribe, or the client is processing messages out of order.

In your subscribe headers you haven't included an ack header, therefore the subscription will be in auto acknowledgement mode. In this ack mode the server assumes all messages sent to the client are received and processed. I would only use auto ack mode in a scenario where message loss is acceptable. Any messages buffered/received after the unsubscribe (or disconnect) call are discarded by the client.

If you require reliable message delivery then open your subscriptions in 'client-individual' ack mode and make use of the client.ack function.

@gdaws Thank you for the explanation!

@gdaws @PSyton
I'm getting a similar error invalid subscription id 1 when using auto connect with failover, few seconds after explicitly calling unsubscribe in a very similar way as done in the snippet above:

Error: invalid subscription id 1
    at Client._createError (/Users/loretoparisi/Documents/node_modules/stompit/lib/Socket.js:240:15)
    at Client.createProtocolError (/Users/loretoparisi/Documents/Projects/node_modules/stompit/lib/Socket.js:265:24)
    at Client.onMessage (/Users/loretoparisi/Documents/Projects/node_modules/stompit/lib/Client.js:454:23)
    at readFrameBody (/Users/loretoparisi/Documents/Projects/node_modules/stompit/lib/Socket.js:71:17)
    at IncomingFrameStream.readIncomingFrame (/Users/loretoparisi/Documents/Projects/node_modules/stompit/lib/Socket.js:94:7)
    at IncomingFrameStream.emit (events.js:375:28)
    at IncomingFrameStream.emit (domain.js:470:12)
    at emitReadable_ (internal/streams/readable.js:550:12)
    at processTicksAndRejections (internal/process/task_queues.js:81:21)

The subscription id 1 is not used in my code anywhere.