app_queue: Preserve reason for realtime queues

When Asterisk is restarted it does not preserve paused reason for
members of realtime queues. This was fixed for non-realtime queues in
ASTERISK_25732

Resolves: #66

UpgradeNote: Add a new column to the queue_member table:
reason_paused VARCHAR(80) so the reason can be preserved.

UserNote: Make paused reason in realtime queues persist an
Asterisk restart. This was fixed for non-realtime
queues in ASTERISK_25732.
This commit is contained in:
Niklas Larsson 2023-05-05 15:30:13 +02:00 committed by George Joseph
parent a5b9fa09ca
commit c1f21b6f66
2 changed files with 50 additions and 5 deletions

View File

@ -1606,6 +1606,9 @@ static int log_membername_as_agent;
/*! \brief name of the ringinuse field in the realtime database */
static char *realtime_ringinuse_field;
/*! \brief does realtime backend support reason_paused */
static int realtime_reason_paused;
enum queue_result {
QUEUE_UNKNOWN = 0,
QUEUE_TIMEOUT = 1,
@ -3566,6 +3569,7 @@ static void rt_handle_member_record(struct call_queue *q, char *category, struct
const char *penalty_str = ast_variable_retrieve(member_config, category, "penalty");
const char *paused_str = ast_variable_retrieve(member_config, category, "paused");
const char *wrapuptime_str = ast_variable_retrieve(member_config, category, "wrapuptime");
const char *reason_paused = ast_variable_retrieve(member_config, category, "reason_paused");
if (ast_strlen_zero(rt_uniqueid)) {
ast_log(LOG_WARNING, "Realtime field 'uniqueid' is empty for member %s\n",
@ -3632,6 +3636,9 @@ static void rt_handle_member_record(struct call_queue *q, char *category, struct
m->penalty = penalty;
m->ringinuse = ringinuse;
m->wrapuptime = wrapuptime;
if (realtime_reason_paused) {
ast_copy_string(m->reason_paused, S_OR(reason_paused, ""), sizeof(m->reason_paused));
}
found = 1;
ao2_ref(m, -1);
break;
@ -3646,6 +3653,9 @@ static void rt_handle_member_record(struct call_queue *q, char *category, struct
m->dead = 0;
m->realtime = 1;
ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
if (!ast_strlen_zero(reason_paused)) {
ast_copy_string(m->reason_paused, reason_paused, sizeof(m->reason_paused));
}
if (!log_membername_as_agent) {
ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
} else {
@ -7656,10 +7666,17 @@ static void set_queue_member_pause(struct call_queue *q, struct member *mem, con
(paused ? "" : "un"), (paused ? "" : "un"), q->name, mem->interface);
}
if (mem->realtime) {
if (update_realtime_member_field(mem, q->name, "paused", paused ? "1" : "0")) {
ast_log(LOG_WARNING, "Failed %spause update of realtime queue member %s:%s\n",
(paused ? "" : "un"), q->name, mem->interface);
if (mem->realtime && !ast_strlen_zero(mem->rt_uniqueid)) {
if (realtime_reason_paused) {
if (ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, "reason_paused", S_OR(reason, ""), "paused", paused ? "1" : "0", SENTINEL) < 0) {
ast_log(LOG_WARNING, "Failed update of realtime queue member %s:%s %spause and reason '%s'\n",
q->name, mem->interface, (paused ? "" : "un"), S_OR(reason, ""));
}
} else {
if (ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, "paused", paused ? "1" : "0", SENTINEL) < 0) {
ast_log(LOG_WARNING, "Failed %spause update of realtime queue member %s:%s\n",
(paused ? "" : "un"), q->name, mem->interface);
}
}
}
@ -11607,11 +11624,13 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, SENTINEL);
ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, "reason_paused", RQ_CHAR, 80, SENTINEL);
/*
* This section is used to determine which name for 'ringinuse' to use in realtime members
* Necessary for supporting older setups.
*
* It also checks if 'reason_paused' exists in the realtime backend
*/
member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name LIKE", "%", SENTINEL);
if (!member_config) {
@ -11629,6 +11648,10 @@ static int load_module(void)
ast_log(LOG_NOTICE, "No entries were found for ringinuse/ignorebusy in queue_members table. Using 'ringinuse'\n");
realtime_ringinuse_field = "ringinuse";
}
if (ast_variable_retrieve(member_config, NULL, "reason_paused")) {
realtime_reason_paused = 1;
}
}
ast_config_destroy(member_config);

View File

@ -0,0 +1,22 @@
"""add reason_paused to queue_members
Revision ID: 4042a0ff4d9f
Revises: 5a2247c957d2
Create Date: 2022-12-21 14:24:48.885750
"""
# revision identifiers, used by Alembic.
revision = '4042a0ff4d9f'
down_revision = 'f261363a857f'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column('queue_members', sa.Column('reason_paused', sa.String(80)))
def downgrade():
op.drop_column('queue_members', 'reason_paused')