= Jobs = Jobs são códigos, vinculados a processos, que são agendados para execução. Os Jobs não possuem uma finalidade específica. Entre as possíveis utilizações de Job, podemos sugerir: * Envio, no último dia de cada mês e através de e-mail, de um relatório contendo dados produzidos pela execução do processo; * Auto-execução, diária, de instâncias que estão paradas há mais de 5 dias; * Acesso, a cada 5 minutos, a um banco externo para coleta de dados. Cada Job corresponde a um arquivo contendo a implementação de uma classe (que estende a classe base dos Jobs). == Propriedades == === Nome === O nome do Job. O nome do Job deve ser único em relação aos outros Jobs do mesmo processo. É também esta propriedade que define o nome da classe (e do arquivo) que será gerada para a execução do Job. Para a geração do nome da classe, o nome informado é normalizado. Esta normalização é diferente daquela usada no nome dos processos e atividades. Exemplo de conversão: {{{ Nome: Avaliar Solicitação Classe: AvaliarSolicitacao Arquivo: class.job.AvaliarSolicitacao.inc.php }}} === Descrição === A descrição do que o Job faz. === Ativo === Indica se o Job está ativo (checkbox marcada) ou não. Se o Job estiver inativo, ele não será executado, mesmo que esteja agendado. === Data de Início === Indica a data a partir da qual o Job será válido para execução. === Hora da Execução === A hora em que o Job será executado. === Tipo de Data === Os Jobs são bem versáteis quanto à sua repetição. Esta propriedade define que critério utilizar para definir sua repetição. São três as possibilidades: * Data Absoluta: ideal para Jobs que possuem um intervalo de execução bem definido. e.g.: executar o Job a partir do dia 07/05/2008 e repetir a cada 3 dias; * Dias da Semana: para Jobs que têm sua execução baseada em dias da semana. e.g.: a partir do dia 14/04/2008, executar o Job às segundas, quartas e sextas com repetição a cada duas semanas; * Data Relativa do Mês: para Jobs que devem ser executados em relação ao número de dias restantes para o fim do mês. e.g.: executar o Job a cada 6 meses, no último dia do mês. O intervalo mínimo para execução de Jobs é de 1 minuto (disponível na repetição "Data Absoluta"). Não possui limite de intervalo máximo. Dependendo do "Tipo de Data" selecionada, outros campos podem surgir: * Dias da Semana: são apresentados os dias da semana para que sejam selecionados aqueles em que o Job deve ser executado; * Data Relativa do Mês: é necessário informar quando o Job deve ser executado informando a quantidade de dias para o fim do mês. === Repetição do Job === Indica se o Job possi repetição (checkbox marcada) ou não. === Campos de Repetição === São campos onde se informa a periodicidade em que o Job é executado. == Manutenção de Jobs == === Criação de Jobs === Basta clicar no botão "Novo" da interface. Ao salvar um Job, automaticamente será criado um arquivo modelo do Job. === Editar um Job === Para editar um Job, basta clicar no ícone que contém uma folha de papel e um lápis. Se o nome do Job for trocado, o arquivo PHP do Job será renomeado e, a Engine tentará trocar o nome da classe. Caso a troca não seja possível, será enviada um alerta para o desenvolvedor informando que a troca precisa ser feita manualmente. === Remoção do Job === Para remover um Job, basta clicar no ícone de uma circunferência cortada (vermelha) e, confirmar a exclusão. Ao remover um Job, o arquivo que implementa o Job também é excluído do sistema de arquivos. Além disso, os Logs produzidos pelo Job também são apagados. == Exemplo 1 == No exemplo abaixo, buscamos as instâncias que estão paradas na atividade "Avaliar Serviço" há mais de 10 dias e, chamamos a ação "Confirmar". Este Job poderia ser executado diariamente e, assim, evitar o acúmulo de instâncias. {{{ class ForcarAvaliacao extends JobBase { public function run() { $objinstance = Factory::getInstance('wf_instance'); $objengine = Factory::getInstance('wf_engine'); /* seleciona as atividades */ $atividade = $objengine->getActivityInformationByName('Avaliar Serviço'); /* busca as instâncias abandonadas */ $instancias = $objinstance->getIdle(10, array($atividade['activity_id'])); $numeroInstancias = 0; foreach ($instancias as $instancia) { /* define as variáveis de request */ $_REQUEST['action'] = 'Confirmar'; /* tenta continuar a instância */ if ($objinstance->continueInstance($instancia['wf_activity_id'], $instancia['wf_instance_id'])) $numeroInstancias++; /* podemos limitar a somente 50 instâncias (para não estourar o tempo de execução) */ if ($numeroInstancias >= 50) break; /* ou podemos limitar de acordo com a quantidade de tempo disponível. * Neste caso, usaremos apenas 90% do tempo disponível */ /* if (($this->getExecutionTime() / $this->getMaximumExectuionTime()) >= 0.9) break; */ } /* grava o log de acordo com o número de instâncias avaliadas */ if ($numeroInstancias > 0) $this->success('Foram continuadas ' . $numeroInstancias . ' instâncias'); else if (count($instancias) > 0) $this->fail('Existem ' . count($instancias) . ' instâncias que não puderam ser continuadas.'); else $this->success('Não há instâncias para serem continuadas'); } } }}} == Exemplo 2 == Neste exemplo mostrarmos como criar uma instância automaticamente à partir de um Job. A criação da instância é realizada através do seguinte método. {{{ final public function createNewInstance($startActivityId, $instanceName=false, $properties=false, $user=false) }}} '''Onde:''' * '''startActivityId''': ID da atividade Start que criará a instância; * '''instanceName''': Identificador da instância no processo; * '''properties''': Array de propriedades da instância; e * '''user''': uidNumber do dono da instância, que se omitido, será um usuário padrão do Job. O código fonte abaixo apresenta na prática como uma instância pode ser criada em um Job. {{{ class CriarInstancia extends JobBase { public function run() { // Cria objeto $role para pegar o código da atividade start, no caso Abrir OS $role = Factory::getInstance('wf_role'); $activityId = $role->getActivityIdByName('Abrir OS'); // Instância não necessita de identificador $name = false; // seta o array de propriedades da instância $properties = array ('_servico_id' => 5 , '_roteamento' => 'end' ); // Cria a instância e grava mensagens de sucesso ou falha no log de execução do Job. if ($this->createNewInstance($activityId, $name, $properties)){ $this->success('Instância criada'); } else { $this->fail('Não foi possível criar a instância.'); } } } }}} == Logs == O Log é o resultado de cada execução de um Job. Sua listagem pode ser acessada através do ícone de um documento contendo ítens. O Log pode indicar quatro resultados: desconhecido, erro, falha e sucesso. Veja a figura abaixo: [[Image(jobs_logs.png)]] Explicando, de cima para baixo: * Erro - ocorre quando o Job possui algum erro em seu código. O erro é salvo no log; * Falha - ocorre em dois casos: (1) o executor de Job encontra algum problema que impede sua execução (e.g. não estende a classe {{{JobBase}}}, não possuí implementado o método {{{run}}}, etc.); (2) o desenvolvedor chamou o método {{{fail}}} da classe {{{JobBase}}}; * Sucesso - ocorre quando o usuário chama o método {{{success}}} da classe {{{JobBase}}}; * Desconhecido - quando não ocorrem erros ou falhas detectáveis pelo executar ou gerenciador de Jobs e, o desenvolvedor não fez nenhuma chamada a {{{success}}} ou {{{fail}}}. Caso haja mais de uma chamada aos métodos {{{success}}} e/ou {{{fail}}}, será gravado em forma de Log somente a última chamada. == Execução de Jobs para Teste == Na interface de administração de Jobs, é possível executar um Job para testar seu funcionamento. Para isto, basta clicar no ícone da engrenagem (azul). Após a execução de um Job (acionada a partir da interface), são exibidas até três informações: * Mensagens: informações sobre a execução do processo (e.g. tempo de execução, etc.); * Saída Default: strings enviadas para a saída padrão. Normalmente enviadas por {{{echo}}}, {{{print}}}, {{{print_r}}}, etc.; * Saída de Erro: erros capturados durante a execução do Job. Veja, por exemplo, a tela de execução de um Job e o código do Job que a produziu: [[Image(jobs_execucao.png)]] {{{ class MeuSegundoJob extends JobBase { public function run() { /* enviado antes do erro. Vai para a saída padrão */ echo "minha saída\nantes do erro"; /* código que vai causar erro */ funcaoInexistente(); } } }}} Durante a execução de um Job, o atributo {{{testMode}}} possui o valor {{{true}}} (este atributo é disponível na própria classe do Job é poe ser acessado através de {{{$this->testMode}}}). Isto é feito para que, caso seja necessário, o código possa se comportar de maneira diferente se estiver sendo executado para testes ou para valer. == Considerações == Os Jobs foram introduzidos na versão 1.7.00.000 do Workflow. Os Jobs possuem um tempo máximo de execução de 15 minutos. Se passarem deste tempo, serão finalizados. A classe base dos Jobs provê métodos que permitem ao desenvolvedor saber a quanto tempo o seu Job está executando e, tomar providências para que encerre sua execução antes do tempo limite ser atingido. Para que os Jobs sejam executados, é necessário incluir a seguinte entrada no Crontab (executando o comando: crontab -e) do usuário do PHP (em sistemas Debian, seria o www-data): {{{ * * * * * cd /var/www/expresso/workflow/inc; php5 -q /var/www/expresso/workflow/inc/class.JobScheduler.inc.php }}} Até o momento, a edição de Jobs não pode ser feita via Web (como é possível com o código dos processos). Sendo assim, é necessário editá-los manualmente. Os arquivos de Job encontram-se em: {{{ /home/expressolivre/workflow/Nome_Processo_XX/code/jobs/ }}}