Agendar trabalhos com o Agendador do Apex
Objetivos de aprendizagem
Após concluir esta unidade, você saberá:
- Quando usar o Apex agendado.
- Como monitorizar trabalhos agendados.
- Sintaxe do Apex agendado.
- Melhores práticas para o método agendado.
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 Schedulable (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
List<Task> tasks = new List<Task>();
for (Opportunity opp : opptys) {
Task newTask = new Task(
Subject = 'Update the Opportunity!',
Priority ='Normal',
Status = 'Not Started',
WhatId = opp.Id
);
tasks.add(newTask);
}
insert tasks;
}
}
É 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
Também é permitido agendar uma classe usando a interface de usuário.
- Em Setup (Configuração), insira
Jobs(Trabalhos) na caixa Quick Find (Busca rápida) e selecione Scheduled Jobs (Trabalhos agendados). - Clique em Agendar Apex.
- Para o nome do trabalho, insira algo como
Daily Oppty Reminder(Lembrete de oportunidades diárias). - Clique no botão de pesquisa junto à classe do Apex e insira
*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
Weekly(Semanal) ouMonthly(Mensal) 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 do Apex 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 {
// Placeholder CRON expression: midnight on March 15.
// Because this is a test, job executes
// immediately after Test.stopTest(), not at the time set in the CRON expression
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');
// Check the scheduled time
List<CronTrigger> ct = [SELECT Id, TimesTriggered, NextFireTime
FROM CronTrigger WHERE Id = :jobId];
System.debug('Next Fire Time ' + ct[0].NextFireTime);
}
}Coisas a serem lembradas
O Apex agendado tem alguns itens aos quais você deve estar atento (quando tiver tempo, consulte Agendador do Apex para obter uma lista completa), mas em geral:
- 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 para ver mais 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.
Recursos
- Guia do desenvolvedor do Apex: Agendador do Apex
- Guia do desenvolvedor do Apex: Administradores e limites de execução
