Scheduler: mudanças entre as edições

De BIS Wiki
Ir para navegação Ir para pesquisar
Criou página com 'O Scheduler é o serviço de agendamento do framework BISCore. Ele é carregado na inicialização do container (deploy do EAR), e é responsável por disparar as atividades p...'
 
Sem resumo de edição
 
(7 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
O Scheduler é o serviço de agendamento do framework BISCore. Ele é carregado na inicialização do container (deploy do EAR), e é responsável por disparar as atividades programadas na hora certa.
O Scheduler é o serviço de agendamento de tarefas do BISFW. o Scheduler pode agendar tarefas para serem executadas de forma única ou repetidamente.


== Requisitos ==
= Componentes do Scheduler =


* As tarefas do Scheduler poderão definir uma coleção de propriedades, similares ao [[SystemProperties]]. Essas propriedades serão passadas para a tarefa na sua execução e poderão ser retornadas no método. Estas serão persistidas e serão passadas durante sua próxima execução. Retornar o valor NULL significa que não houve alteração, enquanto que retornar uma coleção de propriedades vazias indica que o sistema deve excluir todas as propriedades da tarefa.
== SchedulerController ==
* Toda tarefa tem uma data e hora para ser executada.
* Toda tarefa terá um Identificador (que não o do banco de dados) que pode ser definido pelo seu plugin owner, este identificador será único entre todas as tarefas. Tem a finalidade de permitir que o plugin encontre um agendamento sem que tenha seu ID de banco associado. Como por exemplo um agendamento genérico de manutenção do plugin.
* A tarefa terá o nome completo da classe que executará a tarefa. Esta deverá implementar a interface de tarefas do BIS que define os métodos para execução (BISTask).
* As tarefas deverão manter a data da sua última execução.
* As tarefas poderão ter um padrão de repetição ou re-agendamento automático após sua última execução conforme descrito abaixo:
** '''TIMED (Temporizado):''' A atividade é iniciada no horário programado e re-executada após períodos fíxos a partir da data de início. Por exemplo, repetir a cada 15 minutos a partir de 01/01/2011 15:32:25. Caso no próximo horário de repetição a atividade ainda esteja sendo executada não será iniciada outra execução da mesma atividade, o horário será pulado e a atividade será executada somente no próximo horário de repetição definido.
* As tarefas agendadas poderão ter uma data fim para finalizar as repetições. Isto é, caso seu novo agendamento passe a data fim ela não será mais re-agendada.
* As tarefas devem ter um atributo que define o que fazer em caso de atraso na execução. Este atraso refere-se apenas nos casos em que o sistema esteja desligado durante o horário que a tarefa devia ser executada, e quanto o sistema iniciar novamente qual o procedimento adotado com esta tarefa atrasada. Podendo definir as seguintes situações:
** Neste atributo podemos definir um tempo máximo de atraso aceito para que a tarefa seja executada;
** Definir que a tarefa deve ser executada de imediato, não importando o quanto atrasado esteja;
** Não executar atrasada, dar continuidade no agendamento. Se a tarefa tem repetição será agendada para o próximo horário conforme suas definições, ou, se for uma tarefa que não se repete, esta não será mais executada.
** O Scheduler deve ouvir os eventos de alteração/inclusão/exclusão de agendamentos para que possa processa-las a medida que forem feitas e não apenas quando o sistema iniciar.


== Scheduler Component (GUI) ==
A classe SchedulerController é a classe principal de controle, agendamento e execução das tarefas. Toda a manipulação das tarefas é realizada através dela.
Para configurar o agendamento de uma tarefa o próprio serviço oferece um componente para ser usado na camada de apresentação que receberá o SchedulingVO e o manipulará de acordo com as escolhas que o usuário fizer na GUI.
Este componente estará sempre atualizado com a tela, pois poderá ser solicitado a qualquer momento, ou mesmo já estar em uso simultâneo.


== Agendando uma Nova Task ==
== SchedulerTask ==


Um passo à passo para criar uma nova task:
SchedulerTask é a interface que representa a tarefa, suas propriedades e meta informações, não exatamente o código de execução. Normalmente a implementação dessa interface se assemelha à um POJO, ou um VO. Podendo inclusive extender diretamente BISVO para que possa ser persistida no banco de dados diretamente.
# Crie uma nova classe (lembre-se de usar o sufixo "Task" de acordo com Padrão de Nomes (descrito em [[Formatação e Escrita de Código]]), e implemente a interface [[BISTask]].
# Dentro do método definido pela interface, implemente as operações necessárias, para detalhes sobre o método (parâmetros e retornos) leia o tópico [[BISTask]].


Depois de implementada a task, precisamos definir como e quando ela será executa para criar o SchedulerVO. Para saber como popular o SchedulerVO utilize a descrição dos campos no JavaDoc. Uma vez que o objeto esteja criado, basta salvar o agendamento no BISCore através da sua fachada que a tarefa será processada e já passará a funcionar automaticamente.
 
Para entender melhor como configurar e quais atributos uma tarefa tem para seu agendamento verifique os métodos e o JavaDOC disponível na interface SchedulerTask.
 
== SchedulerRunnable ==
 
SchedulerRunnable é a interface do Scheduler para a definição do código de execução da tarefa. A implementação desta interface é o código da execução da tarefa. Note que o código da tarefa pode ficar separado dos atributos de definição da tarefa (SchedulerTask). Assim permitimos quando necessário que as informações possam da tarefa possam ser armazenadas em classes mais simples como os VOs, sem acompanhar o código da execução.
 
{{stop|Classes Não Visíveis Dentro do EJB|Note que a classe de implementação da SchedulerTask será inicializada pelo SchedulerController por reflexão, e que classes que estejam empacotadas dentro de Jar definidos como EJB ficam invisíveis para classes de fora. Logo, se tentar executar uma tarefa cuja classe esteja empacotada dentro do EJB você terá um '''ClassNotFoundException'''.
 
A recomendação é que a classe que implementa a tarefa esteja dentro do pacote externo ao EJB, como o pacote 'Client'. Mesmo que essa implementação não faça nada além de chamar o método do CRUD dentro do EJB. Mesmo porque a tarefa é iniciada sem nenhum tipo de Transaction. De forma geral, a SchedulerRunnable é iniciada como uma Thread 'crua'.}}
 
 
{{nota|Objetos Separados Para Otimização de Recursos|Uma vez agendada, o Scheduler manterá em memória o SchedulerTask e todas as suas propriedades. No entanto a implementação SchedulerRunnable só será inicializada no momento da execução. Ao termino a instância é descartada e as informações serão salvas no SchedulerTask novamente. Assim manter as implementações da tarefa e dos seus meta-dados separados, principalmente para tarefas que se executam com baixa frequência podem gerar economia de recursos significativas.}}
 
== SchedulerListener ==
 
O SchedulerListener é um listener de eventos do SchedulerController. Note que é do controller e não da tarefa, ou seja, esse listener ouvirá todos os eventos relacionados à todas as tarefas. O listener tem dois métodos, um que será chamado caso a tarefa termine em exception, e um caso ela termine com sucesso. Em ambos os casos a própria tarefa (SchedulerTask) é passado como parâmetro para que possa ser identificada.
 
 
Esse listener pode ser utilizado como o ponto para realizar log de problemas, bem como persistir os novos atributos relacionados a execução da tarefa.
 
= Funcionamento =
 
Uma vez implementada a interface SchedulerTask, para colocar a tarefa no SchedullerControler basta passa-la pelo método '''.processTask(SchedulerTask task)'''. Ao passar a tarefa o Scheduler já processará suas definições e se for o caso já executará a tarefa imediatamente (em caso de estar atrasada e a execução atrasada for permitida), ou ela será agendada para execução futura.
 
Caso a tarefa defina algum método de repetição, ao fim da execução da tarefa o próprio Scheduler se encarregará de reagendar a tarefa. Ou seja, só é preciso passar a tarefa para o SchedullerController uma única vez. Normalmente na inicialização (deploy) da aplicação.
 
Caso a tarefa não tenha definições de se repetir, casos de tarefas que são executadas uma única vez, o próprio Scheduler limpará os objetos da memória e descartará tudo para o GC.
 
= IDs Únicos =
 
Cada SchedulerTask deve ter um ID único que identifique a tarefa dentro do SchedulerControler. Normalmente, se as tarefas são persistidas em banco de dados, o ID pode ser a chave primária do banco pois é um valor que já se garante ser único por padrão.
 
No entanto, se temos tarefas que são criadas de forma dinâmica, ou se só existem em memória, essas tarefas precisam garantir que terão um ID único para identificação.
 
Uma vez que o SchedulerController gerencia suas tarefas pelo seu ID, ao inserir uma tarefa com o mesmo ID de uma já existente, a anterior será cancelada e eliminada para a alocação da nova.
 
 
Para garantir uma geração de IDs sequenciais o SchedulerController tem um método estático chamado '''.generateID()'''. Este método gerará IDs negativos sequenciais começando em -1 e seguindo para -2, -3, -4, e assim por diante. A intenção de gerar números negativos como chave é para não dar conflito com chaves eventualmente geradas pelo banco de dados. Desta forma é possível coexistir tanto tarefas persistidas pelo banco, e tenho seu ID gerado pela chave do banco, quando tarefas puramente de memória com IDs gerados dinâmicamente.
 
 
Para as tarefas que se utilizarem do recurso do '''.generateID()''', recomendamos que este valor seja salvo em uma constante da classe SchedulerTask, para que a tarefa mantenha o mesmo ID durante todas sua execução. Algo como:
<pre>public static final long taskID = SchedulerController.generateID();</pre>

Edição atual tal como às 12h23min de 24 de outubro de 2020

O Scheduler é o serviço de agendamento de tarefas do BISFW. o Scheduler pode agendar tarefas para serem executadas de forma única ou repetidamente.

Componentes do Scheduler

SchedulerController

A classe SchedulerController é a classe principal de controle, agendamento e execução das tarefas. Toda a manipulação das tarefas é realizada através dela.

SchedulerTask

SchedulerTask é a interface que representa a tarefa, suas propriedades e meta informações, não exatamente o código de execução. Normalmente a implementação dessa interface se assemelha à um POJO, ou um VO. Podendo inclusive extender diretamente BISVO para que possa ser persistida no banco de dados diretamente.


Para entender melhor como configurar e quais atributos uma tarefa tem para seu agendamento verifique os métodos e o JavaDOC disponível na interface SchedulerTask.

SchedulerRunnable

SchedulerRunnable é a interface do Scheduler para a definição do código de execução da tarefa. A implementação desta interface é o código da execução da tarefa. Note que o código da tarefa pode ficar separado dos atributos de definição da tarefa (SchedulerTask). Assim permitimos quando necessário que as informações possam da tarefa possam ser armazenadas em classes mais simples como os VOs, sem acompanhar o código da execução.

Classes Não Visíveis Dentro do EJB
Note que a classe de implementação da SchedulerTask será inicializada pelo SchedulerController por reflexão, e que classes que estejam empacotadas dentro de Jar definidos como EJB ficam invisíveis para classes de fora. Logo, se tentar executar uma tarefa cuja classe esteja empacotada dentro do EJB você terá um ClassNotFoundException.

A recomendação é que a classe que implementa a tarefa esteja dentro do pacote externo ao EJB, como o pacote 'Client'. Mesmo que essa implementação não faça nada além de chamar o método do CRUD dentro do EJB. Mesmo porque a tarefa é iniciada sem nenhum tipo de Transaction. De forma geral, a SchedulerRunnable é iniciada como uma Thread 'crua'.


Objetos Separados Para Otimização de Recursos
Uma vez agendada, o Scheduler manterá em memória o SchedulerTask e todas as suas propriedades. No entanto a implementação SchedulerRunnable só será inicializada no momento da execução. Ao termino a instância é descartada e as informações serão salvas no SchedulerTask novamente. Assim manter as implementações da tarefa e dos seus meta-dados separados, principalmente para tarefas que se executam com baixa frequência podem gerar economia de recursos significativas.

SchedulerListener

O SchedulerListener é um listener de eventos do SchedulerController. Note que é do controller e não da tarefa, ou seja, esse listener ouvirá todos os eventos relacionados à todas as tarefas. O listener tem dois métodos, um que será chamado caso a tarefa termine em exception, e um caso ela termine com sucesso. Em ambos os casos a própria tarefa (SchedulerTask) é passado como parâmetro para que possa ser identificada.


Esse listener pode ser utilizado como o ponto para realizar log de problemas, bem como persistir os novos atributos relacionados a execução da tarefa.

Funcionamento

Uma vez implementada a interface SchedulerTask, para colocar a tarefa no SchedullerControler basta passa-la pelo método .processTask(SchedulerTask task). Ao passar a tarefa o Scheduler já processará suas definições e se for o caso já executará a tarefa imediatamente (em caso de estar atrasada e a execução atrasada for permitida), ou ela será agendada para execução futura.

Caso a tarefa defina algum método de repetição, ao fim da execução da tarefa o próprio Scheduler se encarregará de reagendar a tarefa. Ou seja, só é preciso passar a tarefa para o SchedullerController uma única vez. Normalmente na inicialização (deploy) da aplicação.

Caso a tarefa não tenha definições de se repetir, casos de tarefas que são executadas uma única vez, o próprio Scheduler limpará os objetos da memória e descartará tudo para o GC.

IDs Únicos

Cada SchedulerTask deve ter um ID único que identifique a tarefa dentro do SchedulerControler. Normalmente, se as tarefas são persistidas em banco de dados, o ID pode ser a chave primária do banco pois é um valor que já se garante ser único por padrão.

No entanto, se temos tarefas que são criadas de forma dinâmica, ou se só existem em memória, essas tarefas precisam garantir que terão um ID único para identificação.

Uma vez que o SchedulerController gerencia suas tarefas pelo seu ID, ao inserir uma tarefa com o mesmo ID de uma já existente, a anterior será cancelada e eliminada para a alocação da nova.


Para garantir uma geração de IDs sequenciais o SchedulerController tem um método estático chamado .generateID(). Este método gerará IDs negativos sequenciais começando em -1 e seguindo para -2, -3, -4, e assim por diante. A intenção de gerar números negativos como chave é para não dar conflito com chaves eventualmente geradas pelo banco de dados. Desta forma é possível coexistir tanto tarefas persistidas pelo banco, e tenho seu ID gerado pela chave do banco, quando tarefas puramente de memória com IDs gerados dinâmicamente.


Para as tarefas que se utilizarem do recurso do .generateID(), recomendamos que este valor seja salvo em uma constante da classe SchedulerTask, para que a tarefa mantenha o mesmo ID durante todas sua execução. Algo como:

public static final long taskID = SchedulerController.generateID();