Skip to main content
Join the Agentforce Hackathon on Nov. 18-19 to compete for a $20,000 Grand Prize. Sign up now. Terms apply.

Usar o Apex assíncrono

Objetivos de aprendizagem

Após concluir esta unidade, você estará apto a:

  • Saber quando usar o Apex assíncrono
  • Usar métodos futuros para lidar com um callout da web
  • Trabalhar com a interface que permite a execução em lote para processar um grande número de registros
  • Compreender as vantagens de usar a interface que permite a execução em fila quando é preciso encontrar um meio-termo

Acompanhar com o Trail Together

Deseja acompanhar um especialista enquanto trabalha nesta etapa? Veja este vídeo que faz parte da série Trail Together.

(Este clipe começa na marca dos 32:07 minutos, caso você queira retroceder e ver o início da etapa novamente.)

Quando ser assíncrono

Como desenvolvedor .NET, você provavelmente já foi exposto ao mundo da programação assíncrona. Vamos assumir que você já sabe o que ela é e entende os benefícios de usar esse tipo de modelo de programação. O que você talvez não saiba é quando usar a programação assíncrona na plataforma do Lightning.

A escolha da programação assíncrona costuma ser embasada pelos três motivos a seguir.

  • Processar uma quantidade muito grande de registros. Esse motivo é exclusivo do mundo multilocatário da plataforma do Lightning, comandado pelos limites. Os limites associados aos processos assíncronos são mais altos do que os associados aos processos síncronos. Por isso, quando você precisa processar milhares ou até milhões de registros, o processamento assíncrono é a melhor opção.
  • Fazer callouts para serviços da web externos. O processamento dos callouts pode ser bem demorado, mas na plataforma do Lightning, os acionadores não podem fazer callouts diretamente.
  • Criar uma experiência de usuário melhor e mais rápida descarregando parte do processamento nas chamadas assíncronas. Por que fazer tudo de uma vez? Se dá para esperar, deixe esperar.

Métodos futuros

Quando você precisa fazer um callout a um serviço da web ou quer descarregar um processamento simples numa tarefa assíncrona, criar um método futuro pode ser a melhor saída.

Transformar um método de processamento síncrono em processamento assíncrono é incrivelmente fácil. Basta acrescentar a anotação @future ao método. Além disso, você só precisa garantir que o método é estático e retorna apenas um tipo nulo. Por exemplo, para criar um método que realize um callout a um serviço da web, podemos fazer assim:

public class MyFutureClass {
    // Include callout=true when making callouts
    @future(callout=true)
    static void myFutureMethod(Set<Id> ids) {
        // Get the list of contacts in the future method since
        // you cannot pass objects as arguments to future methods
        List<Contact> contacts = [SELECT Id, LastName, FirstName, Email
            FROM Contact WHERE Id IN :ids];
        // Loop through the results and call a method
        // which contains the code to do the actual callout
        for (Contact con: contacts) {
            String response = anotherClass.calloutMethod(con.Id,
                con.FirstName,
                con.LastName,
                con.Email);
            // May want to add some code here to log
            // the response to a custom object
        }
    }
}

Depois, podemos chamá-lo como faríamos com qualquer outro método estático. É moleza!

Limitações dos métodos futuros

Métodos futuros oferecem uma ótima opção para os desenvolvedores do Salesforce, no entanto, eles não deixam de ter desvantagens. Aqui estão algumas das limitações a considerar antes de usar um método futuro.

  • Não é possível rastrear a execução porque não é retornada uma ID de trabalho do Apex.
  • Os parâmetros precisam de dados primitivos ou coleções de tipos de dados primitivos. Os métodos futuros não podem receber sObjects como argumentos, pois eles podem mudar no período anterior à execução do método @future.
  • Não é possível encadear métodos futuros e fazer com que um chame o outro. Use o Apex que permite a execução em fila se precisar de execução em uma determinada ordem.

Embora as chamadas assíncronas sejam às vezes feitas para evitar limites, ainda é necessário considerar os limites. Confira o link Execution Governors and Limits em Resources.

Apex de lote ou agendado

Outra ferramenta assíncrona muito usada é a interface que permite a execução em lote. O motivo nº 1 para alguém usá-la é a necessidade de processar um grande número de registros. Por exemplo, caso você queira limpar ou arquivar até 150 milhões de registros, a interface que permite a execução em lote é o ideal, ou utilize a API em massa 2.0 em seu código Apex. É possível até agendar os lotes para execução em determinado momento.

Para usá-la, sua classe implementa a interface Database.Batchable. Você também define os métodos start(), execute() e finish(). Depois, é possível invocar uma classe de lote usando o método Database.executeBatch. Por exemplo, o código a seguir cria uma classe que permite a execução em lote, que processa todas as contas de uma organização e envia um email quando termina de fazer isso.

global class MyBatchableClass implements
            Database.Batchable<sObject>,
            Database.Stateful {
    // Used to record the total number of Accounts processed
    global Integer numOfRecs = 0;
    // Used to gather the records that will be passed to the interface method
    // This method will only be called once and will return either a
    // Database.QueryLocator object or an Iterable that contains the records
    // or objects passed to the job.
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT Id, Name FROM Account');
    }
    // This is where the actual processing occurs as data is chunked into
    // batches and the default batch size is 200.
    global void execute(Database.BatchableContext bc, List<Account> scope) {
        for (Account acc : scope) {
            // Do some processing here
            // and then increment the counter variable
            numOfRecs = numOfRecs + 1;
        }
    }
    // Used to execute any post-processing that may need to happen. This
    // is called only once and after all the batches have finished.
    global void finish(Database.BatchableContext bc) {
        EmailManager.sendMail('someAddress@somewhere.com',
                              numOfRecs + ' Accounts were processed!',
                              'Meet me at the bar for drinks to celebrate');
    }
}

Nesse caso, você poderia invocar a classe de lote usando um código anônimo como esse:

MyBatchableClass myBatchObject = new MyBatchableClass();
Database.executeBatch(myBatchObject);
Nota

Não cobrimos especificamente o Apex agendado nesta unidade, mas ele é parecido com a interface que permite a execução em lote. Ele implementa a interface passível de agendamento, que pode ser usada para invocar o Apex em momentos específicos. Para saber mais sobre isso, confira o módulo Apex assíncrono.

Limitações da interface que permite a execução em lote

A interface que permite a execução em lote é excelente. No entanto, como tudo, ela também tem suas limitações.

  • A solução de problemas pode ser problemática.
  • Os trabalhos ficam em fila e estão sujeitos à disponibilidade de servidor, que às vezes pode demorar mais do que o esperado.
  • Já falamos dos limites?

E então surgiu o Apex que permite a execução em fila

Durante muito tempo, os métodos futuros e a interface que permite a execução em lote foram os métodos principais de os desenvolvedores fazerem o processamento assíncrono. Mas você se lembra de todas as limitações que apresentamos? Bem, elas estavam causando problemas para alguns desenvolvedores, que clamaram por uma solução melhor.

No inverno de 2015, o Salesforce atendeu ao pedido com o Apex que permite a execução em fila. Ele representa o melhor dos métodos futuros e da interface que permite a execução em lote, tudo reunido numa única superferramenta assíncrona. Os desenvolvedores que eram forçados a usar a interface, que permite a execução em lote, mais lenta para contornar as limitações dos métodos futuros podiam retornar a uma ferramenta que fazia mais sentido. O Apex que permite a execução em fila oferece os benefícios a seguir para os métodos futuros.

  • Tipos não primitivos – As classes podem aceitar variáveis de parâmetro de tipos de dados não primitivos, como sObjects ou tipos personalizados do Apex.
  • Monitoramento – Quando você envia o trabalho, é retornada uma jobId que pode ser usada para identificar o trabalho e monitorar seu progresso.
  • Encadeamento de trabalhos – É possível encadear um trabalho a outro iniciando o segundo trabalho a partir do trabalho em execução. O encadeamento de trabalhos é útil para o processamento sequencial.

Então como isso funciona? Ainda bem que você perguntou.

Como o Apex que permite a execução em fila contém o melhor dos métodos futuros, ele é muito mais fácil de implementar do que o Apex de lote. Ele não tem essas limitações incômodas que apresentamos aqui. Para demonstrar como ele funciona, vamos aproveitar o código de exemplo que usa um método futuro para fazer um callout da web e implementá-lo usando o Apex que permite a execução em fila.

public class MyQueueableClass implements Queueable {
    private List<Contact> contacts;
    // Constructor for the class, where we pass
    // in the list of contacts that we want to process
    public MyQueueableClass(List<Contact> myContacts) {
        contacts = myContacts;
    }
    public void execute(QueueableContext context) {
        // Loop through the contacts passed in through
        // the constructor and call a method
        // which contains the code to do the actual callout
        for (Contact con: contacts) {
            String response = anotherClass.calloutMethod(con.Id,
                    con.FirstName,
                    con.LastName,
                    con.Email);
            // May still want to add some code here to log
            // the response to a custom object
        }
    }
}

Para invocar o Apex que permite a execução em fila, você precisa de algo mais ou menos assim:

List<Contact> contacts = [SELECT Id, LastName, FirstName, Email
    FROM Contact WHERE Is_Active__c = true];
Id jobId = System.enqueueJob(new MyQueueableClass(contacts));

Quero saber mais

Além das interfaces que permitem a execução em fila, o Salesforce também introduziu a Apex Flex Queue na primavera de 2015, que eliminou a limitação de cinco lotes concomitantes. Ela também permite que os desenvolvedores monitorem e administrem a ordem dos trabalhos em fila. Confira os links em Resources para saber mais.

Este módulo apresentou aos desenvolvedores .NET as opções assíncronas disponíveis na plataforma do Lightning. Para mergulhar fundo nesse tópico, aprendendo sobre testes, monitoramento de trabalhos e melhores práticas, confira o módulo Apex assíncrono.

Recursos

Compartilhe seu feedback do Trailhead usando a Ajuda do Salesforce.

Queremos saber sobre sua experiência com o Trailhead. Agora você pode acessar o novo formulário de feedback, a qualquer momento, no site Ajuda do Salesforce.

Saiba mais Continue compartilhando feedback