Controlar processos com o Apex que permite a execução em fila

Objetivos de aprendizagem

Após concluir esta unidade, você saberá:
  • Quando usar a interface que permite a execução em fila.
  • As diferenças entre os métodos futuro e que permite a execução em fila.
  • A sintaxe do Apex que permite a execução em fila.
  • Melhores práticas para o método que permite a execução em fila.

Apex que permite a execução em fila

Lançado na versão Winter ‘15, o Apex que permite a execução em fila é basicamente um superconjunto de métodos futuros com algum #temperoextra. Pegamos a simplicidade dos métodos futuros e o poder do Apex de lote e os combinamos para gerar o Apex que permite a execução em fila! Ele lhe oferece uma estrutura de classes que a plataforma serializa para você, uma interface simplificada sem métodos start e finish e que permite inclusive que você use mais do que apenas argumentos primitivos! Para chamá-lo, basta usar o método System.enqueueJob(), que ele retornará um ID do trabalho que pode ser monitorado. É muito fácil!

O Apex que permite a execução em fila permite enviar trabalhos para processamento assíncrono, da mesma forma que os métodos futuros, com os seguintes benefícios adicionais:
  • Tipos não primitivos: Sua classe Que permite a execução em fila pode conter variáveis membro de tipos de dados não primitivos, como sObjects ou tipos personalizados do Apex. Tais objetos podem ser acessados quando o trabalho for executado.
  • Monitoramento: Quando você envia o trabalho invocando o método System.enqueueJob, o método retorna o ID do registro AsyncApexJob. É possível usar este ID para identificar seu trabalho e monitorar seu progresso, seja pela interface de usuário do Salesforce, na página de Trabalhos do Apex, seja programaticamente pela consulta de seu registro em AsyncApexJob.
  • Encadeamento de trabalhos: É possível encadear um trabalho a outro iniciando o segundo trabalho a partir de um trabalho em execução. O encadeamento de trabalhos é útil se você precisar fazer algum processamento sequencial.

Apex que permite a execução em fila versus Futuro

Como os métodos que permitem a execução em fila são funcionalmente equivalentes aos métodos futuros, na maioria das vezes você provavelmente preferirá usar os métodos que permitem a execução em fila. Porém, isso não significa necessariamente que você deva voltar e refazer todos os seus métodos futuros agora.

Outro motivo para usar métodos futuros em vez dos que permitem a execução em fila é quando sua funcionalidade é executada às vezes de modo síncrono e às vezes de modo assíncrono. É muito mais fácil refazer um método desta forma que convertê-lo em uma classe que permite a execução em fila. Isso é muito prático quando você descobre que parte de seu código atual precisa ser transferido para uma execução assíncrona. Você pode simplesmente criar um método futuro semelhante que envolva seu método síncrono, da seguinte forma:

@future
static void myFutureMethod(List<String> params) {
    // call synchronous method
    mySyncMethod(params);
}

Sintaxe do Apex que permite a execução em fila

Para usar o Apex que permite a execução em fila, basta implementar a interface Que permite a execução em fila.

public class SomeClass implements Queueable {
    public void execute(QueueableContext context) {
        // awesome code here
    }
}

Código de exemplo

Um cenário comum é pegar alguns conjuntos de registros sObject, executar algum processamento, como fazer um callout para um ponto de extremidade REST externo ou realizar alguns cálculos e então atualizá-los no banco de dados de forma assíncrona. Como os métodos @future são limitados a tipos de dados primitivos (ou matrizes ou coleções de dados primitivos), o Apex que permite a execução em fila é a opção ideal. O código a seguir pega uma coleção de registros de Conta, define a parentId para cada registro, e então atualiza os registros no banco de dados.

public class UpdateParentAccount implements Queueable {
    private List<Account> accounts;
    private ID parent;
    public UpdateParentAccount(List<Account> records, ID id) {
        this.accounts = records;
        this.parent = id;
    }
    public void execute(QueueableContext context) {
        for (Account account : accounts) {
          account.parentId = parent;
          // perform other processing or callout
        }
        update accounts;
    }
}

Para adicionar esta classe como um trabalho na fila, execute o seguinte código:

// find all accounts in ‘NY’
List<Account> accounts = [select id from account where billingstate = ‘NY’];
// find a specific parent account for all records
Id parentId = [select id from account where name = 'ACME Corp'][0].Id;
// instantiate a new instance of the Queueable class
UpdateParentAccount updateJob = new UpdateParentAccount(accounts, parentId);
// enqueue the job for processing
ID jobID = System.enqueueJob(updateJob);

Após enviar sua classe que permite a execução em fila para a execução, o trabalho será adicionado à fila e processado quando os recursos do sistema se tornarem disponíveis.

Você pode usar o novo ID para monitorar o progresso por meio da página de Trabalhos do Apex ou, programaticamente, consultando AsyncApexJob:

SELECT Id, Status, NumberOfErrors FROM AsyncApexJob WHERE Id = :jobID

Como testar o Apex que permite a execução em fila

O exemplo de código a seguir mostra como testar a execução de um trabalho que permite a execução em fila em um método de teste. Isso é muito semelhante ao teste do Apex de lote. Para garantir que o processo que permite a execução em fila seja executado no método de teste, o trabalho é enviado à fila entre os blocos Test.startTest e Test.stopTest. O sistema executa todos os processos assíncronos iniciados em um método de teste de forma síncrona após a instrução Test.startTest. A seguir, o método de teste verifica os resultados do trabalho que permite a execução em fila consultando os registros de conta que foram atualizados pelo trabalho.

@isTest
public class UpdateParentAccountTest {
    @testSetup
    static void setup() {
        List<Account> accounts = new List<Account>();
        // add a parent account
        accounts.add(new Account(name='Parent'));
        // add 100 child accounts
        for (Integer i = 0; i < 100; i++) {
            accounts.add(new Account(
                name='Test Account'+i
            ));
        }
        insert accounts;
    }
    static testmethod void testQueueable() {
        // query for test data to pass to queueable class
        Id parentId = [select id from account where name = 'Parent'][0].Id;
        List<Account> accounts = [select id, name from account where name like 'Test Account%'];
        // Create our Queueable instance
        UpdateParentAccount updater = new UpdateParentAccount(accounts, parentId);
        // startTest/stopTest block to force async processes to run
        Test.startTest();
        System.enqueueJob(updater);
        Test.stopTest();
        // Validate the job ran. Check if record have correct parentId now
        System.assertEquals(100, [select count() from account where parentId = :parentId]);
    }
}

Como encadear trabalhos

Um dos melhores recursos do Apex que permite a execução em fila é o encadeamento de trabalhos. Se você precisar executar trabalhos sequencialmente, o Apex que permite a execução em fila pode deixar sua vida muito mais fácil. Para encadear um trabalho a outro, envie o segundo trabalho de um método execute() de sua classe que permita a execução em fila. Só é permitido adicionar um trabalho a partir de um trabalho em execução, o que significa que apenas um trabalho filho pode existir para cada trabalho pai. Por exemplo, se houver uma segunda classe chamada SecondJob que implemente a interface Que permite a execução em fila, será possível adicionar esta classe à fila no método execute() da seguinte forma:

public class FirstJob implements Queueable {
    public void execute(QueueableContext context) {
        // Awesome processing logic here
        // Chain this job to next job by submitting the next job
        System.enqueueJob(new SecondJob());
    }
}

Novamente, o teste tem um padrão ligeiramente diferente. Não é possível encadear trabalhos que permitem a execução em fila em um testo do Apex. Isso resultaria em um erro. Para evitar erros graves, é possível verificar se o Apex está sendo executado em contexto de teste com a chamada de Test.isRunningTest() antes de encadear os trabalhos.

Coisas a serem lembradas

O Apex que permite a execução em fila é uma excelente ferramenta nova, mas há algumas coisas às quais é preciso estar atento:
  • A execução de um trabalho em fila é contada uma vez para o limite compartilhado para execuções do método Apex assíncrono.
  • Você pode adicionar até 50 trabalhos à fila com o System.enqueueJob em uma só transação.
  • Ao encadear trabalhos, você só pode adicionar um trabalho de um trabalho em execução com System.enqueueJob, o que significa que apenas um trabalho filho pode existir para cada trabalho pai que permita a execução em fila. Iniciar diversos trabalhos filhos no mesmo trabalho que permite a execução em fila não é aceitável.
  • Nenhum limite é imposto à profundidade dos trabalhos encadeados, o que significa que você pode encadear um trabalho atrás do outro e repetir esse processo, encadeando-o a outro trabalho filho. Porém, para as versões de Developer Edition e Organizações de teste, a profundidade máxima da pilha para trabalhos encadeados é de cinco, o que significa que você pode encadear trabalhos quatro vezes e o número máximo de trabalhos na cadeia é de cinco, incluindo o trabalho que permite a execução em fila pai inicial.

Recursos

Nota

Nota

Lembre-se: este módulo é destinado ao Salesforce Classic. Quando você iniciar sua organização prática, mude para o Salesforce Classic para concluir este desafio.

Continue a aprender de graça!
Inscreva-se em uma conta para continuar.
O que você ganha com isso?
  • Receba recomendações personalizadas para suas metas de carreira
  • Pratique suas habilidades com desafios práticos e testes
  • Monitore e compartilhe seu progresso com os empregadores
  • Conecte-se a orientação e oportunidades de carreira