[Home]

Summary:ASTERISK-14133: autofill problem when coming back from paused on realtime
Reporter:Gabriel Ortiz Lour (elbriga)Labels:
Date Opened:2009-05-14 13:29:05Date Closed:2011-06-07 14:08:10
Priority:MinorRegression?No
Status:Closed/CompleteComponents:Applications/app_queue
Versions:Frequency of
Occurrence
Related
Issues:
Environment:Attachments:
Description:I'm testing this on 1.4.19, but I dont see anything related on the latest changelog (maybe something on 1.4.25-rc1, but right now I dont have SVN access to get it).

I have my queues setup on realtime and i directly access the 'paused' column on the queue members table to change their status. When I enable 'autofill' (directly on the table, not in the conf file) it will do the autofill behavior OK, until this scenario...

- A queue member is paused
- A call enters the queue, and here it will be looping in the "wait_out_turn" function, that calls "is_our_turn"
- The queue member gets unpaused (directly via SQL on the respective paused column)
- The call is still on the "wait_out_turn" loop, and inside it there are no direct call to refresh the realtime data, so it will "never" know that the member get unpaused (but if I, for eg, do a "queue show" CLI command it will ring that agent right away, because the queue struct got refreshed)

I was thinking about doing a "update_realtime_members" at some frequency inside the "wait_out_turn" loop, but then it would get executes for every call on the queue, so I think the best way flag the need of a refresh inside the "wait_out_turn" loop and actually refresh some place else (where?)

****** ADDITIONAL INFORMATION ******

Setting up a realtime queue with autofill=1, with one realtime member, pausing it, calling the queue and unpausing it. The member will only be called once a realtime refresh eventually occur.
Comments:By: Gabriel Ortiz Lour (elbriga) 2009-05-14 13:57:43

Tested on 1.4.24.1 : Shows the same issue

By: Gabriel Ortiz Lour (elbriga) 2009-05-14 14:41:58

putting "update_realtime_members(qe->parent);" inside the "wait_our_turn" loop (I put a counter to do it each 5 iterations) solves the problem, but creates another one: it will Query: "SELECT * FROM membrosfila WHERE interface LIKE '%' AND queue_name = 'XXXXX' ORDER BY interface" every 5 seconds for every call in the queue! No Good!!

By: Mark Michelson (mmichelson) 2009-05-15 17:47:30

The problem here is that unlike other fields in the queue_members table, the 'paused' field represents state for a queue member, rather than a configuration option.

The 'paused' field really wasn't intended to be directly modified as you are doing. Rather, when a manager action, dialplan application, or CLI command is used to pause a queue member, we write the value to the database so that when we need to recreate the member later, we can maintain his paused status from before.

Unfortunately, this is not documented anywhere, and it's too late to change history. Plus, in the situation you're discussing, the biggest problem is that it sounds like the data is never being refreshed from the database. While the "paused" field obviously has the detriment of making it so that it is not possible to unpause a member, there are other potential issues too. Consider if a member were added to the database during this period. He would not be able to take a call until something had triggered a read of the database.

I have an idea about this, and it will require a bit of work to get written correctly. Currently, app_queue works by periodically loading realtime data, or it will load realtime data when an operation requires it, such as typing certain CLI queue commands. My idea is to have app_queue spawn a thread which is essentially the "realtime queue thread." Its sole job will be to sleep and wake up periodically (say every 30 seconds or so. I could make this configurable) to reload realtime queue member data. This thread could be "prodded" by other threads to wake up early and reload realtime queue member data if necessary (e.g. issuing the "queue show" CLI command).

Right now the idea is nothing more than an idea fumbling around in my head. I'll have to weigh the pros and cons of such an idea. One big con I have thought of already is that an idle system will be making periodic database lookups essentially for no reason.

By: Gabriel Ortiz Lour (elbriga) 2009-05-16 10:12:45

mmichelson,

I had my problem solved by deciding to use only dynamic members with persistentmember=yes, and doing manager commands to Add/Remove/Pause members instead of changing teh DB directly.

But along the way I had the same toughts as you on the need of a periodic refreshing system. Regarding this I came up with this idea:
The various parts of the queue system would flag (in the queue struct) the need of a refresh, doing so the refresh thread could be as quick as a 5 seconds delay, but it would only actually performing it if the flag tell it to.

What do you think?

By: Mark Michelson (mmichelson) 2009-05-18 09:46:40

I had a similar idea, except that instead of using a flag, I thought to use an ast_cond_t variable. This way, one could use ast_cond_timed_wait to wait for a certain amount of time before auto-refreshing. However, the wait could be interrupted by ast_cond_signal from any thread which required an immediate update.

By: Leif Madsen (lmadsen) 2009-09-18 08:35:24

I'm closing this as it looks like the issue was solved another way, and that the other potential (coding) ways of solving this may introduce more problems than it would solve. Thanks for the discussion!