Comportamento
Agentes estavam conseguindo logar e deslogar normalmente nas filas, em determinado momento do dia, os agentes que estavam logados permaneciam logados e trabalhando, mas qualquer agente que tentasse logar na fila, não conseguia.
Ao entrar na tela do agente, o usuário clicava na fila mas nenhum ramal era listado para ele selecionar e logar.
Nos logs do manager era exibido o seguinte erro quando o usuário entrava na tela do agente:
[error] 2021-10-21 14:23:31 - application - String index out of range: -1
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1967)
at business.atendimento.AtendimentoBusiness.getRamaisLogado(AtendimentoBusiness.java:1068)
at business.atendimento.AtendimentoBusiness.listarRamaisAgente(AtendimentoBusiness.java:146)
at business.atendimento.AtendimentoBusiness.getDadosAtendimento(AtendimentoBusiness.java:452)
at controllers.AtendimentoController.atendimento(AtendimentoController.java:74)
at router.Routes$$anonfun$routes$1$$anonfun$applyOrElse$461$$anonfun$apply$461.apply(Routes.scala:21153)
at router.Routes$$anonfun$routes$1$$anonfun$applyOrElse$461$$anonfun$apply$461.apply(Routes.scala:21153)
at play.core.routing.HandlerInvokerFactory$$anon$4.resultCall(HandlerInvoker.scala:136)
at play.core.routing.HandlerInvokerFactory$JavaActionInvokerFactory$$anon$14$$anon$3$$anon$1.invocation(HandlerInvoker.scala:127)
at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:70)
at http.handlers.HTTPRequestHandler$1.call(HTTPRequestHandler.java:73)
at play.core.j.JavaAction$$anonfun$7.apply(JavaAction.scala:94)
at play.core.j.JavaAction$$anonfun$7.apply(JavaAction.scala:94)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:40)
at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70)
at play.core.j.HttpExecutionContext.execute(HttpExecutionContext.scala:32)
at scala.concurrent.impl.Future$.apply(Future.scala:31)
at scala.concurrent.Future$.apply(Future.scala:492)
at play.core.j.JavaAction.apply(JavaAction.scala:94)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105)
at play.utils.Threads$.withContextClassLoader(Threads.scala:21)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:104)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:103)
at scala.Option.map(Option.scala:146)
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:103)
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:96)
at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:524)
at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:524)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:560)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:560)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$13.apply(Iteratee.scala:536)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$13.apply(Iteratee.scala:536)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Diagnóstico e Causa
Primeiro foram avaliadas as 3 condições usadas pelo sistema para exibir o ramal para o agente selecionar:
1- Se o ramal está registrado
2- Se o ramal está associado à fila selecionada
3- Se não existe nenhum outro agente logado com o ramal
As 3 condições eram atendidas.
A avaliação passou então para a lista de contatos na tabela agents da base unity_sip para verificar se existia alguma inconsistência, nos dados. Para essa avaliação foi executado o seguinte select na tabela:
select name, contact, status, state from agents
Esses campos trazem as seguintes informações:
- name: login do agente no formato <login>@<dominio>
- contact: informações de contato do agente, ou seja, quando ele está logado traz o ramal no qual o agente logou. A informação fica no seguinte formato:
- Quando o agente está deslogado, ou seja status Logged Out:
- {call_timeout=12}
- o valor 12 é um exemplo de call_timeout que é configurado no menu Metrics –> Opções dos agentes, editando o agente e configurando o campo call_timeout
- {call_timeout=12}
- Quando o agente está logado, ou seja, status Available ou On Break e no ambiente a criptografia de RTP (SRTP) está habilitada:
- {rtp_secure_media=true,call_timeout=12}user/12004@<domínio>
- O 12004@<domínio> é um exemplo com o número do ramal que o agente selecionou na hora de logar
- O campo só fica
- {rtp_secure_media=true,call_timeout=12}user/12004@<domínio>
- Quando o agente está logado, ou seja, status Available ou On Break e no ambiente a criptografia de RTP (SRTP) está desabilitada:
- {call_timeout=12}user/12004@<domínio>O 12004@<domínio> é um exemplo com o número do ramal que o agente selecionou na hora de logar
- Quando o agente está deslogado, ou seja status Logged Out:
- Status: indica o status do agente
- Logged Out: quando o agente não está logado
- Available: quando o agente está logado
- On Break: quando o agente está logado, mas em pausa
- State: indica o estado do agente:
- Waiting: quando o agente está disponível para receber uma chamada
- In a queue call: quando o agente está com uma chamada ativa
No caso do problema específico, existia uma inconsistência nessa tabela, na qual um agente estava com status Available, mas o campo contact não estava preenchido com a informação do ramal no qual o agente estava logado:

Solução
Para solucionar, temos duas opções:
- Através da interface, editar o usuário específico menu Configurações –> Usuários, e desmarcar a flag AGENTE e depois clicar em SALVAR. Após isso, marcar novamente a flag AGENTE e depois clicar em SALVAR. Com essa ação o registro do agente na tabela AGENTS será recriado, com as informções corretas
- Executar um update no banco de dados modificando o campo STATUS do agente de Available para Logged Out
update agents set status = 'Logged Out' where name = '<login>@<domínio>';