ibm-messaging / mq-mqi-nodejs

Calling IBM MQ from Node.js - a JavaScript MQI wrapper
Apache License 2.0
79 stars 41 forks source link

Unable to use GET ( async ) method for 2 read channel on single connection. #182

Closed sanohdar closed 3 months ago

sanohdar commented 3 months ago

Hi @ibmmqmet and all, need your expertise here Please include the following information in your ticket.

With single connection and single Open read channel i am using Get (Async) method to retrieve the message from the queue and its working fine and running , it is re-triggering the callback after waitInterval.

but if we open other read mode channel (we will get different hObj ) on the same connection, we have use this new hObj to invoke Get (async) method , it crashes the server with

MQError: GET[async]: MQCC = MQCC_FAILED [2] MQRC = MQRC_HCONN_ASYNC_ACTIVE [2500] at exports.GetAsync (/Users/s_o/iProject/mq/ibmmq-server-connection-test/node_modules/ibmmq/lib/mqigeta.js:250:17) at exports.Get (/Users/s_o/iProject/mq/ibmmq-server-connection-test/node_modules/ibmmq/lib/mqi.js:1646:12) at /Users/s_o/iProject/mq/ibmmq-server-connection-test/getmessageIbmq.js:26:8 at new Promise (<anonymous>) at getMessage (/Users/s_o/iProject/mq/ibmmq-server-connection-test/getmessageIbmq.js:13:10) at /Users/s_o/iProject/mq/ibmmq-server-connection-test/server4get.js:43:16 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { mqcc: 2, mqccstr: 'MQCC_FAILED', mqrc: 2500, mqrcstr: 'MQRC_HCONN_ASYNC_ACTIVE', version: '2.0.4', verb: 'GET[async]'

Connection on Queue-manager = 1 (hConn) Open Read mode = 2 (hObj1 , hObj2)

getMessage implementation

` function getMessage(hObj) { return new Promise((resolve, reject) => { console.log('Getting meessage from queue ', hObj._name); let mqmd = new mq.MQMD(); let gmo = new mq.MQGMO();

gmo.Options = MQC.MQGMO_NO_SYNCPOINT |
  MQC.MQGMO_WAIT |
  MQC.MQGMO_CONVERT |
  MQC.MQGMO_FAIL_IF_QUIESCING;

gmo.MatchOptions = MQC.MQMO_NONE;
gmo.WaitInterval = 3 * 1000; // 3 seconds

mq.Get(hObj, mqmd, gmo, getCB);
mq.Ctl(hObj._mqQueueManager, MQC.MQOP_START);

function getCB(err, hObj, gmo, md, buf, hConn) {
  if (err) {
    if (err.mqrc == MQC.MQRC_NO_MSG_AVAILABLE) {
      console.log("No more messages available.");
      resolve('No New Message')
    } else {
      if (hObj && hObj._mqQueueManager) {
        mq.GetDone(hObj);
        mq.Ctl(hObj._mqQueueManager, MQC.MQOP_STOP);
      }
      console.log('Different error', err);
      reject(err);

    }
  } else {
    if (md.Format == "MQSTR") {
      console.log("message <%s>", decoder.write(buf));
      message = decoder.write(buf)
    } else {
      console.log("binary message: " + buf);
    }
    resolve(message);
  }
}

}) } ` Open channel implmentation

`async function openInput(qmr, od) { return new Promise((resolve, reject) => { console.log('Opening MQ Connection Input mode'); mq.Open(qmr, od, MQC.MQOO_INPUT_AS_Q_DEF, (err, hObj) => { if(err) console.log('Error in opening the queue.', err);

        console.log('Opened queue in INPUT mode')
        InputObj =  hObj;
        resolve();
    })
})

}`

chughts commented 3 months ago

I think this was fixed in 2.0.4 of ibmmq

If you are on an earlier release, then you need to MQC.MQOP_SUSPEND the first async get, then MQC.MQOP_RESUME it when the second async get has completed.

See. https://github.com/ibm-messaging/mq-dev-patterns/blob/294d69ae0cabf3bca42972f48a558308463e3cce/Node.js/boilerplate.js#L317

sanohdar commented 3 months ago

I am using 2.0.4 , i am facing difficulties in running 2 instances of async get. what i have understood is each async get runa separate thread and these are attached through TSFN with main thread of node process.

i have tested with above suggestion , able to perform the task. Thank you