Agendar trabalhos com o Agendador do Apex
Objetivos de aprendizagem
Acompanhar com o Trail Together
Deseja acompanhar um instrutor enquanto trabalha nesta etapa? Veja este vídeo que faz parte da série Trail Together no Trailhead Live.
(Este clipe começa na marca dos 01:09:53 minutos, caso você queira retroceder e ver o início da etapa novamente.)
Apex agendado
O Agendador do Apex permite atrasar a execução para que você possa executar as classes do Apex em uma hora especificada. Isso é ideal para tarefas de manutenção diária ou semanal com o Apex de lote. Para aproveitar o agendador, escreva uma classe do Apex que implemente a interface Passível de agendamento
e agende-a para execução em uma agenda específica.
Sintaxe do Apex agendado
Para invocar classes do Apex para serem executadas em horários específicos, implemente antes a interface Schedulable
para a classe. Depois, agende uma instância da classe para ser executada em um momento específico usando o método System.schedule()
.
public class SomeClass implements Schedulable { public void execute(SchedulableContext ctx) { // awesome code here } }
Esta classe implementa a interface Schedulable
(Passível de agendamento) e deve implementar o único método que esta interface contém, que é o método execute()
.
O parâmetro deste método é um objeto SchedulableContext
. Após a classe ter sido agendada, um objeto CronTrigger
é criado para representar o trabalho agendado. Isso oferece um método getTriggerId()
que retorna a ID de um objeto API CronTrigger
.
Código de exemplo
Esta classe consulta oportunidades abertas que deveriam ter sido fechadas até a data atual e cria uma tarefa em cada uma para lembrar o proprietário de atualizar a oportunidade.
public class RemindOpptyOwners implements Schedulable { public void execute(SchedulableContext ctx) { List<Opportunity> opptys = [SELECT Id, Name, OwnerId, CloseDate FROM Opportunity WHERE IsClosed = False AND CloseDate < TODAY]; // Create a task for each opportunity in the list TaskUtils.remindOwners(opptys); } }
É possível programar sua classe para ser executada por programação ou a partir da IU do Agendador do Apex.
Como usar o método System.Schedule
Após implementar uma classe com a interface Schedulable
(Passível de agendamento), use o método System.schedule()
para executá-la. O método System.schedule()
usa o fuso horário do usuário para a base de todos os agendamentos, mas é executado em modo de sistema: todas as classes são executadas, independente de o usuário ter ou não permissão para executar a classe.
O método System.schedule()
utiliza três argumentos: um nome para o trabalho, uma expressão CRON usada para representar a data e hora na qual o trabalho está agendado para ser executado e uma instância de uma classe que implemente a interface Schedulable
(Passível de agendamento).
RemindOpptyOwners reminder = new RemindOpptyOwners(); // Seconds Minutes Hours Day_of_month Month Day_of_week optional_year String sch = '20 30 8 10 2 ?'; String jobID = System.schedule('Remind Opp Owners', sch, reminder);
Para mais informações sobre a expressão CRON usada para o agendamento, consulte a seção “Como usar o método System.Schedule” no Agendador do Apex.
Como programar um trabalho a partir da IU
- Em Configuração, insira
Apex
na caixa Busca rápida e selecione Classes do Apex. - Clique em Agendar Apex.
- Para o nome do trabalho, digite algo como
Lembretes diários da oportunidade.
- Clique no botão de pesquisa junto à classe do Apex e digite
*
como termo para pesquisa para obter uma lista de todas as classes que podem ser agendadas. Nos resultados da pesquisa, clique no nome de sua classe agendada. - Selecione a frequência
Semanal
ouMensal
para definir a frequência desejada. - Selecione as datas inicial e final e a hora de início desejada.
- Clique em Salvar.
Como testar o Apex agendado
Assim como os outros métodos assíncronos abordados até agora, com o Apex agendado é necessário garantir que o trabalho agendado seja finalizado antes de verificar os resultados. Para isso, use novamente o startTest()
e o stopTest()
no método System.schedule()
para garantir que o processo seja finalizado antes de continuar seu teste.
@IsTest private class RemindOppyOwnersTest { // Dummy CRON expression: midnight on March 15. // Because this is a test, job executes // immediately after Test.stopTest(). public static String CRON_EXP = '0 0 0 15 3 ? 2042'; @IsTest static void testScheduledJob() { // Create some out of date Opportunity records List<Opportunity> opptys = new List<Opportunity>(); Date closeDate = Date.today().addDays(-7); for (Integer i=0; i<10; i++) { Opportunity o = new Opportunity( Name = 'Opportunity ' + i, CloseDate = closeDate, StageName = 'Prospecting' ); opptys.add(o); } insert opptys; // Get the IDs of the opportunities we just inserted Map<Id, Opportunity> opptyMap = new Map<Id, Opportunity>(opptys); List<Id> opptyIds = new List<Id>(opptyMap.keySet()); Test.startTest(); // Schedule the test job String jobId = System.schedule('ScheduledApexTest', CRON_EXP, new RemindOpptyOwners()); // Verify the scheduled job has not run yet. List<Task> lt = [SELECT Id FROM Task WHERE WhatId IN :opptyIds]; System.assertEquals(0, lt.size(), 'Tasks exist before job has run'); // Stopping the test will run the job synchronously Test.stopTest(); // Now that the scheduled job has executed, // check that our tasks were created lt = [SELECT Id FROM Task WHERE WhatId IN :opptyIds]; System.assertEquals(opptyIds.size(), lt.size(), 'Tasks were not created'); } }
Coisas a serem lembradas
- Só podem ser agendados 100 trabalhos do Apex por vez e há um número máximo de execuções Apex agendadas para um período de 24 horas. Consulte Administradores e limites de execução, na seção Recursos, para obter detalhes.
- Tome muito cuidado se estiver planejando programar uma classe a partir de um acionador. Você tem de garantir que o acionador não adicionará mais trabalhos agendados do que o limite.
- Os callouts de serviço da Web síncronos não são aceitos a partir do Apex agendado. Para poder fazer callouts, faça um callout assíncrono colocando-o em um método anotado com
@future(callout=true)
e chame este método a partir do Apex agendado. Porém, se seu Apex agendado executar um trabalho em lote, os callouts são compatíveis com a classe de lote.