feat: implement Call Center queues (mod_callcenter)
- Investigated the real callcenter_config command surface via
'help callcenter_config' on the running FreeSWITCH before writing any
code: queues only have load/unload/reload (static XML + reload, no
'queue add' exists), while agents and tiers are fully dynamic via ESL
commands (agent add, tier add) -- no file involved. This shapes the next
phase (Agents/Tiers) differently from this one.
- queues table (tenant-scoped, RLS): strategy, moh/announce, wait times,
tier rules, discard/abandoned handling, skip-agents-with-external-calls,
recording_enabled
- packages/telephony: buildQueueXml()
- infrastructure/freeswitch: our own callcenter.conf.xml override (empties
the vanilla static agents/tiers -- those become fully dynamic in the next
phase) that includes callcenter_queues.conf.d/*.xml via X-PRE-PROCESS,
same pattern as the Sofia gateway directory
- apps/api/src/queues: CRUD (POST/GET/GET:id/DELETE) using the queues.view/
.manage permissions already in the seed
- b2bcall-fs-config (queue-sync.ts): one XML file per queue on a shared
volume, synced via Redis pub/sub (b2bcall:queues:sync) on create/delete
and once at boot -- same shape as trunk-sync.ts
- confirmed manually against the real FreeSWITCH, before coding the sync
logic: 'queue load <name>' fails ('Invalid Queue not found!') for a file
added after boot -- needs 'reloadxml' first to repopulate the in-memory
XML tree from disk; after that, 'queue reload <name>' alone handles both
create and update, no need to distinguish load vs reload
- verified end-to-end: created a queue (ROUND_ROBIN, maxWaitTime=120,
discardAbandonedAfter=90), 'callcenter_config queue list' showed the
correct values on the FreeSWITCH side; deleted it, list went back empty
docs/QUEUES.md
This commit is contained in:
82
docs/QUEUES.md
Normal file
82
docs/QUEUES.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Filas (mod_callcenter)
|
||||
|
||||
Agente.md secao 37 (mod_callcenter como ACD) e 50-51 (Filas/Estratégias).
|
||||
Primeira peça do Call Center — Agentes/Tiers/Pausas ficam pra próxima fase
|
||||
(dependem do fluxo de login do agente, seção 45-49, escopo maior).
|
||||
|
||||
## Descoberta real sobre `callcenter_config`
|
||||
|
||||
Antes de escrever qualquer código, rodei `help callcenter_config` no
|
||||
FreeSWITCH real pra ver a sintaxe exata — e ela é bem diferente do que os
|
||||
Trunks fizeram supor:
|
||||
|
||||
- **Filas**: só `queue load`/`unload`/`reload`/`list` — **não existe**
|
||||
`queue add` nem `queue set param`. Filas só podem vir de XML estático,
|
||||
carregado/recarregado por nome.
|
||||
- **Agentes**: `agent add`/`del`/`set status`/`set state`/... — 100%
|
||||
dinâmico via comando ESL, sem XML.
|
||||
- **Tiers**: `tier add`/`del`/`set state`/`set level`/`set position` — também
|
||||
100% dinâmico.
|
||||
|
||||
Ou seja, filas usam o mesmo padrão "arquivo + reload" dos Trunks; agentes e
|
||||
tiers (próxima fase) vão usar comandos ESL diretos, sem arquivo nenhum.
|
||||
|
||||
## Mecanismo
|
||||
|
||||
Mesmo padrão dos gateways Sofia: um arquivo XML por fila
|
||||
(`autoload_configs/callcenter_queues.conf.d/<queue_id>.xml`, volume Docker
|
||||
compartilhado), incluído via `X-PRE-PROCESS` no nosso
|
||||
`callcenter.conf.xml` próprio (agente.md secao 15 — "carregar somente o
|
||||
necessário": zeramos os `<agents>`/`<tiers>` estáticos da vanilla, já que
|
||||
essas partes vão ser 100% dinâmicas).
|
||||
|
||||
**Sequência de comandos confirmada manualmente contra o FreeSWITCH real**
|
||||
(testei cada passo antes de escrever o código):
|
||||
|
||||
1. `queue load <nome>` **falha** ("Invalid Queue not found!") se o arquivo
|
||||
foi adicionado depois do boot — a árvore XML em memória não sabe do
|
||||
arquivo novo ainda.
|
||||
2. `reloadxml` primeiro repopula essa árvore a partir do disco.
|
||||
3. Depois disso, **`queue reload <nome>` sozinho** já serve tanto pra criar
|
||||
quanto atualizar — não precisa distinguir `load` de `reload`.
|
||||
4. Fila removida: apagar o arquivo, `reloadxml`, `queue unload <nome>`.
|
||||
|
||||
`b2bcall-fs-config` (`queue-sync.ts`) reescreve todos os arquivos de fila
|
||||
habilitada (todos os tenants) a cada sync, remove os obsoletos, roda
|
||||
`reloadxml` uma vez, depois `queue reload` por fila desejada e
|
||||
`queue unload` por fila removida. Disparado por Redis pub/sub
|
||||
(`b2bcall:queues:sync`, mesmo mecanismo dos Trunks) a cada create/delete via
|
||||
API, e uma vez no boot do serviço.
|
||||
|
||||
## Nome da fila no FreeSWITCH
|
||||
|
||||
`<queue.id>@<tenant.telephonyDomain>` — mesma convenção UUID dos gateways.
|
||||
Como o `telephonyDomain` hoje é compartilhado entre tenants (limitação já
|
||||
documentada em docs/EXTENSIONS.md), o unload de uma fila apagada usa o
|
||||
domain de "qualquer tenant ativo" como aproximação, já que o registro no
|
||||
banco já não existe mais nesse ponto pra sabermos o domain exato.
|
||||
|
||||
## Verificado ponta a ponta
|
||||
|
||||
```
|
||||
POST /queues {"name":"Suporte","strategy":"ROUND_ROBIN","maxWaitTime":120,"discardAbandonedAfter":90}
|
||||
→ fs-config sincroniza (desired:1) → reloadxml + queue reload
|
||||
|
||||
callcenter_config queue list
|
||||
→ <id>@b2bcall.local|round-robin|...|90|false|120|... (parâmetros batem)
|
||||
|
||||
DELETE /queues/:id
|
||||
→ fs-config sincroniza (removed:1) → reloadxml + queue unload
|
||||
→ callcenter_config queue list volta vazia
|
||||
```
|
||||
|
||||
## O que falta
|
||||
|
||||
- Agentes, Tiers, Pausas (secao 45-49) — fase separada, mecanismo é
|
||||
puramente via comando ESL (`agent add`, `tier add`), sem arquivo.
|
||||
- Monitoramento em tempo real das filas (secao 54) — depende de WebSocket
|
||||
multi-tenant, que ainda não existe.
|
||||
- `tier-rule-wait-multiply-level` e `tier-rule-no-agent-no-wait` (vistos no
|
||||
`queue list` da config vanilla) não são expostos como campos próprios
|
||||
ainda — ficaram de fora do escopo desta fase.
|
||||
- Quota de filas (`max_queues`) — depende de Plans/Entitlements.
|
||||
Reference in New Issue
Block a user