[asterisk-users] Cascading queues & calls not joining unavailable queues.

James FitzGibbon james.fitzgibbon at gmail.com
Fri Sep 7 13:11:11 CDT 2007


On 9/7/07, Atis <atis at best.eu.org> wrote:
>
> > It doesn't work if you're using AddQueueMember with SIP channels,
> because
> > the Dial() is implicit, so you have no control over what happens after
> that
> > implicit Dial() finishes.
>
> Nop, it works for Dial to SIP channels, if you set "g" option in Dial.


I call AddQueueMember like this:

AddQueueMember(queuename,SIP/1234)

When I then call

Queue(queuename)

from my dialplan, the Dial() of SIP/1234 is implicit.  There is no priority
and extension that I control where Dial() is being executed, and thus there
is no "priority + 1" for me to go to by using the 'g' option to Dial.

What you're talking about only works if I do this instead:

AddQueueMember(queuename,Local/1234 at agents)

And then somewhere in my dialplan I have:

[agents]
exten => 1234,1,Dial(SIP/1234,20)
exten => 1234,n,DoSomethingHereIfDollarDialStatusIsNotANSWERED

And then of course it makes no difference that agent 1234 is on SIP - they
could be Zap, IAX, Skinny, whatever.

> And yes, I have good reason for using SIP channels.  We have externally
> > driven automatic pausing (because the built-in wrapuptime is per-queue
> and
> > therefore broken for any agent who is assigned to more than one queue),
> and
> > neither form of Local (with or without /n) perform properly under this
> > configuration.
>
> This is something new for me. Are you sure about this? Isn't
> wrapuptime taking in account agent state change? Because then, it's
> really bad for direct calls (for me it's rare that agent have several
> queues).


Wrapuptime isn't a state in app_queue.  You'd think it was (agent goes from
"in-use" to "in-wrapup", then back to "available" after the configured
number of seconds).  But what really happens is that the last time a member
took a call is part of the member struct, which is subordinate to the queue
struct (i.e. the last time a member took a call is stored
per-member-per-queue, not per-member).  You can test this easily by adding a
member to two queues, then sending a call to each queue spaced a minute
apart.  Then run 'queue show' on the CLI.  You'll see that the "last was xxx
seconds ago" differs for the same member in  the two queues.

When app_queue is attempting to dequeue a call to an available agent, it
checks if the current time minus the time of the last call for the member in
this queue is less than the wrapuptime, and if it is, it skips that member
and goes onto the next.

Because the last call time is per queue, you can have an agent take a call
on queue foo, hang up that call, and receive a call for queue bar one second
later, even if both queue foo and queue bar have a wrapuptime of 60 seconds
configured.

So, the built in wrapup has three major problems compared to the ACD system
we moved to Asterisk from:

- wrapuptime is per-queue-per-member, not per-member
- wrapuptime is invisible (the internal state of the member during the
wrapup is "not in use", and only by looking at the "last was xxx seconds
ago" and knowing what the configured wrapuptime for the queue is can you
tell that a member is not actually eligible to take a call)
- wrapuptime cannot be shortened or extended by the agent (or anyone else
for that matter - I once mused with writing a dialplan function to set the
last call time to some arbitrary epoch value to make this viable)

These problems led to me developing this external wrapuptime system.

My original implementation for doing external auto-pause was to have an AMI
client watch for Hangup events.  When I did that, Local channels caused
problems.  If I used one form of Local channel (with or without the /n, I
forget now) then the hangup event was fired when the call was bridged to the
agent.  The other way, the hangup didn't fire until the agent was done with
the caller, but some equally unpleasant side effect manifested.  This was
all months ago, so I don't recall the specific problems I faced.

The AMI solution was too CPU intensive, so I switched to a system that
essentially tails queue_log.  When it seems COMPLETEAGENT or COMPLETECALLER
or TRANSFER, it uses AMI to pause the member, and schedules an unpause for x
seconds in the future.    By using PauseQueueMember without a queue name, it
pauses an agent in all their queues, and if the agent needs to, he can
unpause themselves early or cancel the pending unpause to give themselves
more time to write notes.

This way of doing things might not be incompatible with Local channels, but
I'd have to do some tests.

-- 
j.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.digium.com/pipermail/asterisk-users/attachments/20070907/c2aebdc3/attachment.htm 


More information about the asterisk-users mailing list