[Home]

Summary:ASTERISK-27017: app_queue: Linear queue retries as many agents as were skipped
Reporter:Jared Hull (fortytwo)Labels:
Date Opened:2017-05-25 14:36:48Date Closed:
Priority:MajorRegression?
Status:Open/NewComponents:Applications/app_queue
Versions:13.15.0 13.16.0 14.5.0 Frequency of
Occurrence
Related
Issues:
Environment:Attachments:( 0) log.txt
( 1) queues.conf.txt
Description:When using a linear or rrmemory queue, all agents are dialed in the order they are added to queues.conf. With the option 'n' added to the queue application, I would expect the queue to stop once it has reached the timeout of the last agent. It does this when all agents are (Not in use).

n - No retries on the timeout; will exit this application and go to the next step

Paused or unavailable agents (due to an unavailable contact status) will be skipped and cause the queue to loop around to the first agent and ring as many agents as there were paused or unavailable before 'Exiting on time-out cycle'.

{quote}exten => 424242,1,Answer
same => n,Queue(linearQ,wxRn)
same => n(noAnswer),Busy{quote}

{quote}testbed*CLI> queue show
linearQ has 0 calls (max unlimited) in 'linear' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 60s
  Members:
     PJSIP/109 (ringinuse enabled) (paused) (Not in use) has taken no calls yet
     PJSIP/100 (ringinuse enabled) (Unavailable) has taken no calls yet
     PJSIP/103 (ringinuse enabled) (Not in use) has taken no calls yet
     PJSIP/102 (ringinuse enabled) (Not in use) has taken no calls yet
  No Callers{quote}

The test case in log.txt, the order of agents and status is show above. the expected behaviour is that 103 and 102 would ring before the caller exits the queue to the next line in dialplan. Instead we see the queue loop around and dial both 103 and 102 again. If 109 was unpaused, it rings 109,103,102 and then loops around to 109 again because 100 is unavailable.
Comments:By: Asterisk Team (asteriskteam) 2017-05-25 14:36:49.396-0500

Thanks for creating a report! The issue has entered the triage process. That means the issue will wait in this status until a Bug Marshal has an opportunity to review the issue. Once the issue has been reviewed you will receive comments regarding the next steps towards resolution.

A good first step is for you to review the [Asterisk Issue Guidelines|https://wiki.asterisk.org/wiki/display/AST/Asterisk+Issue+Guidelines] if you haven't already. The guidelines detail what is expected from an Asterisk issue report.

Then, if you are submitting a patch, please review the [Patch Contribution Process|https://wiki.asterisk.org/wiki/display/AST/Patch+Contribution+Process].

By: Benjamin Keith Ford (bford) 2017-06-05 11:49:22.954-0500

Thank you for posting this issue! We have confirmed that this is reproducible.

By: Tom Hughes (tomhughes) 2017-08-21 06:41:38.611-0500

I believe the cause is basically down to this line in app_queue.c:

{code}
/* exit after 'timeout' cycle if 'n' option enabled */
if (noption && tries >= ao2_container_count(qe.parent->members)) {
{code}

Which exits once the number of lines tried is equal to the number of members of the queue, including any that aren't currently available.

By: Jared Hull (fortytwo) 2017-08-22 11:50:19.291-0500

try_calling() increments 'tries' before setting up a call attempt, then it looks for a member to dial.
It doesn't attempt the unavailable or paused members, nor does it count them towards the 'tries'.
This is why it is ringing the same members until 'tries' is greater than or equal to the member count.

tries=0
{quote}app_queue.c: PJSIP/108-00000005 is trying to call a queue member.
app_queue.c: Trying 'PJSIP/107' with metric 0
app_queue.c: PJSIP/107 not available, can't receive call
app_queue.c: Trying 'PJSIP/108' with metric 1
app_queue.c: PJSIP/108 paused, can't receive call
app_queue.c: Trying 'PJSIP/109' with metric 2
app_queue.c: Add PJSIP/109 to pending_members{quote}
tries=1
{quote}app_queue.c: PJSIP/108-00000005 is trying to call a queue member.
app_queue.c: Trying 'PJSIP/201' with metric 3
app_queue.c: Add PJSIP/201 to pending_members{quote}
tries=2
{quote}PJSIP/108-00000005 is trying to call a queue member.
app_queue.c: Trying 'PJSIP/107' with metric 0
app_queue.c: PJSIP/107 not available, can't receive call
app_queue.c: Trying 'PJSIP/108' with metric 1
app_queue.c: PJSIP/108 paused, can't receive call
app_queue.c: Trying 'PJSIP/109' with metric 2
app_queue.c: Add PJSIP/109 to pending_members{quote}
tries=3
{quote}app_queue.c: PJSIP/108-00000005 is trying to call a queue member.
app_queue.c: Trying 'PJSIP/201' with metric 3
app_queue.c: Add PJSIP/201 to pending_members{quote}
tries=4
{quote}Exiting on time-out cycle{quote}
I suppose this is intended behavior to check the status of the members before each attempt, since they are certainly capable of changing. I think the solution here, without breaking any use cases when noption=0, would be to do this when noption=1:
linear - Don't skip any ordered members. If they are unavailable or paused at the time they are supposed to be tried, they should be treated as failed attempts before trying the next ordered member.
rrordered - Same as the above, except we must start and end at a certain member.
rrmemory - Not sure, I think the order of these members changes?