Agendar trabalhos com o Agendador do Apex
Objetivos de aprendizagem
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 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.
global class SomeClass implements Schedulable { global void execute(SchedulableContext ctx) { // awesome code here } }
Esta classe implementa a interface Schedulable e deve implementar o único método que essa interface contém, que é o método execute.
O parâmetro desse 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 o 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.
global class RemindOpptyOwners implements Schedulable { global 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, 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 considera 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 o nome da classe.
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 Daily Oppty Reminder.
- 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 ou 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 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 ter certeza de que o processo foi 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 ? 2022'; static testmethod 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 no Apex agendado. Porém, se seu Apex agendado executar um trabalho em lote, os callouts são compatíveis com a classe de lote.