]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
app_queue: Add 'prio' setting to the 'force_longest_waiting_caller' option
authorserfreeman1337 <serfreeman1337@gmail.com>
Thu, 29 Jan 2026 16:52:10 +0000 (21:52 +0500)
committergithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Wed, 4 Feb 2026 13:09:49 +0000 (13:09 +0000)
This adds a 'prio' setting to ensure that call priority is respected across multiple queues.
Using 'yes' could cause high-priority callers to be skipped if a caller
in another queue had a longer wait time, regardless of priority.

Resolves: #1637

UserNote: The 'force_longest_waiting_caller' option now supports a 'prio' setting.
When set to 'prio', calls are offered by priority first, then by wait time.

apps/app_queue.c
configs/samples/queues.conf.sample

index fdb426aa1beb381c1b0c163f98e4743e7be22d6e..b8ea7a616e2b3a1513c0fc8b0209ace7d57962f2 100644 (file)
@@ -1942,6 +1942,10 @@ struct penalty_rule {
 #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than <limit>" */
 #define ANNOUNCEPOSITION_LIMIT 4 /*!< We not announce position more than \<limit\> */
 
+#define FORCELONGESTWAITINGCALLER_NO 0
+#define FORCELONGESTWAITINGCALLER_YES 1
+#define FORCELONGESTWAITINGCALLER_PRIO 2 /*!< Account for call priorities when forcing longest waiting caller */
+
 struct call_queue {
        AST_DECLARE_STRING_FIELDS(
                /*! Queue name */
@@ -4778,7 +4782,13 @@ static int is_longest_waiting_caller(struct queue_ent *caller, struct member *me
                                         * will be unused until the first caller is picked up.
                                         */
                                        if (!ch->pending) {
-                                               if (ch->start < caller->start) {
+                                               if (ch->prio != caller->prio && force_longest_waiting_caller == FORCELONGESTWAITINGCALLER_PRIO) { 
+                                                       if (ch->prio > caller->prio) { /* This queue has a caller with higher priority. */
+                                                               ast_debug(1, "Queue %s has a call at position %i that's higher priority (%d vs %d)\n",
+                                                                       q->name, ch->pos, ch->prio, caller->prio);
+                                                               is_longest_waiting = 0;
+                                                       }
+                                               } else if (ch->start < caller->start) {
                                                        ast_debug(1, "Queue %s has a call at position %i that's been waiting longer (%li vs %li)\n",
                                                                          q->name, ch->pos, ch->start, caller->start);
                                                        is_longest_waiting = 0;
@@ -4787,6 +4797,8 @@ static int is_longest_waiting_caller(struct queue_ent *caller, struct member *me
                                        }
                                        ch = ch->next;
                                }
+
+                               ao2_ref(mem, -1);
                        }
                }
                ao2_unlock(q);
@@ -9842,7 +9854,13 @@ static void queue_set_global_params(struct ast_config *cfg)
                log_membername_as_agent = ast_true(general_val);
        }
        if ((general_val = ast_variable_retrieve(cfg, "general", "force_longest_waiting_caller"))) {
-               force_longest_waiting_caller = ast_true(general_val);
+               if (!strcasecmp(general_val, "prio")) {
+                       force_longest_waiting_caller = FORCELONGESTWAITINGCALLER_PRIO;
+               } else if (ast_true(general_val)) {
+                       force_longest_waiting_caller = FORCELONGESTWAITINGCALLER_YES;
+               } else {
+                       force_longest_waiting_caller = FORCELONGESTWAITINGCALLER_NO;
+               }
        }
        if ((general_val = ast_variable_retrieve(cfg, "general", "log_unpause_on_reason_change"))) {
                log_unpause_on_reason_change = ast_true(general_val);
index 2b4cb4b09701c7e6b9188dae5b39b00d05084c73..16882e63c5d7530d83118f941d3a2ad539a7651c 100644 (file)
@@ -73,6 +73,8 @@ monitor-type = MixMonitor
 ; is a member of another queue with a call that's been waiting longer. If so, the current
 ; call is not offered to the agent. The default value is 'no'.
 ;
+; Setting this to 'prio' performs the same check but also accounts for call priority.
+;
 ;force_longest_waiting_caller = no
 ;
 ; Add unpause event to queue log in case of pause send twice with different reason code.