ibm-messaging / mq-mqi-nodejs

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

The polling mechanism doesn't work properly if I connect to more than one queue manager #151

Open nagybar opened 1 year ago

nagybar commented 1 year ago

The polling mechanism doesn't work properly if I connect to more than one queue manager from the same NodeJS application.

If I connect to two different MQs the LoopPollTimeMs tuning parameter does not apply when using the mq.Get() method and polling runs without waiting. Otherwise, it reads the messages from the queues.

I get the same error when I connect to the same QM and poll (mq.Get) two queues.

My environment:

My questions:

        mq.setTuningParameters({
            getLoopPollTimeMs: 3000,
            debugLog: true, 
        });

        var md = new mq.MQMD();
        var gmo = new mq.MQGMO(); // Get Message Options

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

        gmo.MatchOptions = MQC.MQMO_NONE;

        mq.Get(hObj, md, gmo, handler);

MQCONN to QM2 successful
[ibmmq] 2022-12-01T15:53:57.984Z  : Tuning Parameters are now {"maxConsecutiveGets":100,"getLoopPollTimeMs":3000,"getLoopDelayTimeMs":250,"syncMQICompat":false,"debugLongCalls":false,"debugLog":true}
MQOPEN of DEV.QUEUE.2 successful
[ibmmq] 2022-12-01T15:53:57.998Z  : Async GET setup: {"_hObj":101,"_mqQueueManager":{"_hConn":2113929223,"_name":"QM2"},"_name":"DEV.QUEUE.2"}
[ibmmq] 2022-12-01T15:53:57.998Z  : schdeduledGetLoop ? false
MQOPEN of DEV.QUEUE.1 successful
[ibmmq] 2022-12-01T15:53:58.001Z  : Async GET setup: {"_hObj":101,"_mqQueueManager":{"_hConn":2113929221,"_name":"QM1"},"_name":"DEV.QUEUE.1"}
[ibmmq] 2022-12-01T15:53:58.001Z  : schdeduledGetLoop ? true
[ibmmq] 2022-12-01T15:53:58.002Z  : pollAllHConns
[ibmmq] 2022-12-01T15:53:58.003Z  : getFreshHConnsforPoll returning 2113929223,2113929221
[ibmmq] 2022-12-01T15:53:58.003Z  : Executing pollPerHconn for hConn: 2113929223
[ibmmq] 2022-12-01T15:53:58.003Z  : pollHObjs: About to work on #0 from 1 for 101/2113929223
[ibmmq] 2022-12-01T15:53:58.004Z  : PollHObjInternal: q = DEV.QUEUE.2 Get/HConn 0 Get/HObj 0
[ibmmq] 2022-12-01T15:53:58.008Z  : Executing pollPerHconn for hConn: 2113929221
[ibmmq] 2022-12-01T15:53:58.008Z  : pollHObjs: About to work on #0 from 1 for 101/2113929221
[ibmmq] 2022-12-01T15:53:58.009Z  : PollHObjInternal: q = DEV.QUEUE.1 Get/HConn 0 Get/HObj 0
[ibmmq] 2022-12-01T15:53:58.020Z  : MQRC: 2033 hObj {"_hObj":101,"_mqQueueManager":{"_hConn":2113929223,"_name":"QM2"},"_name":"DEV.QUEUE.2"} WaitStartTime: 1669910037998 Now: 1669910038019  WaitInterval: -1 diff: 21 waitExpired: false
[ibmmq] 2022-12-01T15:53:58.020Z  : Wait has not expired for hObj {"_hObj":101,"_mqQueueManager":{"_hConn":2113929223,"_name":"QM2"},"_name":"DEV.QUEUE.2"}
[ibmmq] 2022-12-01T15:53:58.020Z  : pollHObjs: About to work on #0 from 1 for 101/2113929223
[ibmmq] 2022-12-01T15:53:58.020Z  : PollHObjInternal: q = DEV.QUEUE.2 Get/HConn 0 Get/HObj 0
[ibmmq] 2022-12-01T15:53:58.031Z  : MQRC: 2033 hObj {"_hObj":101,"_mqQueueManager":{"_hConn":2113929221,"_name":"QM1"},"_name":"DEV.QUEUE.1"} WaitStartTime: 1669910038001 Now: 1669910038031  WaitInterval: -1 diff: 30 waitExpired: false
[ibmmq] 2022-12-01T15:53:58.031Z  : Wait has not expired for hObj {"_hObj":101,"_mqQueueManager":{"_hConn":2113929221,"_name":"QM1"},"_name":"DEV.QUEUE.1"}
[ibmmq] 2022-12-01T15:53:58.031Z  : pollHObjs: About to work on #0 from 1 for 101/2113929221
[ibmmq] 2022-12-01T15:53:58.031Z  : PollHObjInternal: q = DEV.QUEUE.1 Get/HConn 0 Get/HObj 0
[ibmmq] 2022-12-01T15:53:58.038Z  : MQRC: 2033 hObj {"_hObj":101,"_mqQueueManager":{"_hConn":2113929223,"_name":"QM2"},"_name":"DEV.QUEUE.2"} WaitStartTime: 1669910037998 Now: 1669910038038  WaitInterval: -1 diff: 40 waitExpired: false
[ibmmq] 2022-12-01T15:53:58.039Z  : Wait has not expired for hObj {"_hObj":101,"_mqQueueManager":{"_hConn":2113929223,"_name":"QM2"},"_name":"DEV.QUEUE.2"}```
ibmmqmet commented 1 year ago

You certainly can do Get calls across multiple queues & queue managers in the same program. I've just run a simple test and can see the messages being delivered from the different queues.

But there are several polling controls to try to give a "fair" opportunity while still being responsive to both existing and newly-arrived messages - we don't want to spin through all of QM1's messages before trying to get them from QM2 for example. We also don't want to be hogging all of the Node engine, not allowing other pieces of the application to execute. The getLoopPollTimeMs tends not to be the most relevant control once you have more than one queue open (regardless of whether they are on the same qmgr or different).

So you might want to try playing with the getLoopDelayTimeMs tuning parameter as an additional control. And there is also the maxConsecutiveGets which will add further delays or switches to other queue handles.

The current heuristics generally seem to balance fairly across a number of queues and queue managers, with the tuning parms giving that extra level of control. But of course you can always implement your own polling with GetSync if you find the current model doesn't match your requirements.