Nesta página6 seções
“O Schedule não rodou” junta pelo menos quatro problemas diferentes: o agendamento não existe, existe mas não disparou, disparou e a rotina não foi chamada, ou a rotina foi chamada e falhou ou terminou sem fazer nada. Cada um pede uma evidência diferente. Tratar todos como “problema do agendador” é o caminho mais longo.
Este texto cobre o que o fonte da rotina controla e você pode conferir. Cadastro do agendamento e disparo pelo servidor dependem do ambiente e não foram verificados aqui.
O que a rotina precisa expor
A rotina que aceita agendamento expõe uma Static Function SchedDef() sem parâmetros, que devolve um array. O array tem as primeiras posições:
| Posição | Conteúdo |
|---|---|
| 1 | Tipo: "R" para relatório, "P" para processo |
| 2 | Grupo de perguntas (Pergunte); se não usar, passar ParamDef |
| 3 | Alias |
| 4 | Array de ordens |
| 5 | Título |
| 7 | Se o agendamento pode ser cadastrado como “sempre ativo” |
| 8 | Se o agendamento pode ser feito por filiais |
A posição 6 é o nome do relatório. Há rotinas padrão que devolvem só as cinco primeiras posições, e há um fonte cujo comentário diz que o nome do fonte deve ser o mesmo do Job. Se o agendamento não aparece para a rotina, ou aparece sem as perguntas esperadas, comece por aqui. Isso afeta o cadastro do agendamento; nesse caso, o log de execução da rotina talvez não traga pista, mas isso não foi verificado.
Etapa 1: a rotina roda sem tela?
Uma rotina agendada costuma rodar sem interface (comportamento a confirmar no seu ambiente). É comum usar IsBlind() para saber se a rotina está nesse modo. Qualquer MsgInfo, Aviso, Pergunte com tela ou FWAlertSuccess dentro do caminho agendado é um candidato a travar ou falhar sem que ninguém veja. Rode a rotina pelo caminho de processamento, sem tela, e observe se ela chega ao fim.
Etapa 2: duas execuções ao mesmo tempo
Um padrão comum é proteger o processo com semáforo (LockByName e UnLockByName) e, se já estiver rodando, apenas registrar uma linha de log e sair. Uma execução que “não fez nada” pode ser exatamente essa saída. Se a sua rotina tem semáforo, a saída precisa deixar rastro; se ela não tem, duas execuções sobrepostas podem gravar em duplicidade.
Exemplo neutro
Rotina fictícia que expõe SchedDef, marca início e fim e deixa rastro quando encontra bloqueio. Não foi compilada. Atenção: SchedDef costuma ser declarada como Static Function dentro de rotinas Function; não foi verificado que a combinação com User Function, usada aqui, funciona no agendador. Teste antes de adotar.
#Include "Protheus.ch"
User Function ZSchDemo()
Local cSemaforo := "ZSCHDEMO" + cEmpAnt
Local lBlind := IsBlind()
Conout("[ZSchDemo] inicio " + DToS(Date()) + " " + Time() + " blind=" + IIf(lBlind, "S", "N"))
If !LockByName(cSemaforo, .T., .F.)
Conout("[ZSchDemo] ja em execucao, saindo sem processar")
Return Nil
EndIf
Begin Sequence
// trabalho da rotina, sem tela
Conout("[ZSchDemo] processando")
End Sequence
UnLockByName(cSemaforo)
Conout("[ZSchDemo] fim " + DToS(Date()) + " " + Time())
Return Nil
Static Function SchedDef()
Local aParam := {}
aParam := { "P",; // processo
"",; // sem grupo de perguntas
,; // alias
,; // ordens
"Rotina de teste de agendamento" }
Return aParamSe o semáforo for usado, garanta que ele seja liberado também quando a rotina falha no meio: sem isso, a próxima execução sai sempre pelo “já em execução”.
Por etapa: qual evidência procurar
| Etapa | Pergunta | Evidência que responde |
|---|---|---|
| Cadastro | O agendamento existe para essa rotina, empresa, filial e horário? | O cadastro do agendamento no ambiente. Sem ele, nada mais importa. |
| Disparo | O servidor chegou a iniciar a tarefa no horário? | Registro do servidor. Onde fica e o que mostra depende da configuração do ambiente e não foi verificado aqui. |
| Chamada | A sua rotina começou? | A linha de início do seu próprio log, como a do exemplo. |
| Resultado | Terminou e fez o esperado? | A linha de fim e o efeito nos dados. |
A linha de início da sua rotina é a evidência mais útil: se ela aparece, o agendamento funcionou e o problema está do Conout para dentro. Se não aparece, o problema está antes da sua rotina, e aí você precisa das duas primeiras linhas da tabela.
Anote o horário previsto, a empresa e a filial do agendamento e o horário em que você olhou. Sem isso, a comparação com o log vira palpite.
O que não fazer
- Não reinicie serviços para “destravar” antes de saber em que etapa a evidência some: você perde justamente o rastro.
- Não atribua atraso ou lentidão ao agendador sem comparar o horário de início da sua rotina com o horário previsto.
- Não teste só pela tela: a rotina agendada provavelmente percorre outro caminho, sem interface (a confirmar).
Para rotina que precisa trocar de empresa por conta própria, veja trocar de empresa com StartJob. Quando a falha está em uma execução automática de outra rotina, como descobrir por que o MsExecAuto falhou ajuda a ler o erro.
Continue por aqui
- Vídeo
ProtheusGuia de processo
Trocar de empresa dentro de uma API: por que RpcSetEnv derruba a thread e o que fazer
RpcSetEnv na mesma thread de uma API REST não troca o ambiente, derruba a conexão; StartJob cria a thread nova para trocar de empresa.
- Vídeo
DesenvolvimentoReferência técnica
MsExecAuto: como descobrir por que a rotina falhou
MsExecAuto: uma integração que devolve só 'erro ao incluir' obriga a repetir o processo para saber o motivo. O diagnóstico começa antes do primeiro lote.