Empezando Apex Asíncrono por las colas

En esta entrada me centraré, en cómo diseñar la ejecución de Procesos Asíncronos Apex (en adelante Apex Async), aprovechando las capacidades de la plataforma.

Pero lo haré de manera invertida a como se hace habitualmente, donde se explica como programar los mecanismos de programación. Pero en IMMO, si los desarrolladores, arquitectos y administradores, entendemos bien como gestiona Salesforce los procesos asíncronos, sus colas de Espera y Ejecución, sus límites asociados, etc., la elección del mecanismo de programación, es muy sencilla u obvia.

En el contexto asíncrono, un diseño centrado en la programación y no en las capacidades de la plataforma, puede suponer limitar el rendimiento y las prestaciones de nuestro proyecto.

Y  es que si lo hubieras sabido, te hubieras cortado el pelo antes, y  no hubieras ido con tu compañero.

  1. Introducción
  2. Back to Basics: ¿Qué és un proceso Apex asíncrono?
  3. Estados de un Job Apex asíncrono
  4. Apex Flex Queue(s) y la Apex Jobs Queue
    4.1. Apex Flex Queue
    4.1.1. Orden de inserción en la Flex Queue y reordenación de prioridades
    4.2. Test-Context Queue (la otra Flex Queue)
    4.3. Apex Jobs Queue
  5. Límites de las colas
  6. Monitorización de las colas
    6.1. Mediante Interfaz de usuario
    6.2. Mediante el objeto AsyncApexJob
    6.3. Mediante CronTrigger y CronJobDetail para los Jobs Scheduled
  7. Retos reales no cubiertos por la plataforma
  8. Conclusiones

2. Back to Basics: ¿Qué és un proceso Apex asíncrono?

Un Job de Apex con naturaleza asíncrona (en adelante Apex Async ó Job Async), se ejecuta cuando la plataforma tiene recursos disponibles (lo que sucede muy a menudo) sin ninguna horquilla de finalización ni ANS o ETC (Service Level Agreement – Estimated Time to Complete), y siempre sin perjudicar al ámbito síncrono, donde trabaja el usuario final que se ejecuta con prioridad.

En contrapartida, los límites para un Job Async son límites superiores que para un proceso síncrono. Así un Job asíncrono posee:

La gestión de los procesos asícronos por parte de Salesforce se realiza mediante un sistema de colas.

Recalco, no existe ETC por parte de Salesforce, y por tanto, nuestro diseño no puede suponer ninguno de los aspectos siguientes:

  1. Cuando se iniciará el proceso
  2. Cuanto durará el proceso
  3. Cuando estarán disponibles los resultados de la ejecución

Ejecución de Apex Asíncrono basado en colas

Existen diferentes tipos de Jobs Apex Async, seguro que has visto algún método con la anotación @Future, pero siendo muy útil y práctico, ese es el hermano menor de todos.

Existen 3 mecanismos adicionales, implementados mediante Interfaces (no asustarse es muy simple):

  1. @Queueable
  2. @Schedulable
  3. @Batchable

Pero como viste en la imagen anterior, se gestionan mediante colas. Por tanto, aquí empieza el Rock&Roll, veamos los estados de un proceso y como la plataforma gestiona los Jobs asíncronos mediante las colas.

Salesforce Queues para Apex Async

3. Estados de un Job Apex asíncrono

Los estados de un proceso (Job) Apex Async, transcurre por los siguientes estados:

Estado que reporta la plataforma Descripción y Cola en la que reside el Proceso Es un estado finalista?
Holding El proceso Batch se ha enviado correctamente, pero queda pendiente de ser ejecutado, cuando hay recursos disponibles, que permitan su ejecución. El proceso reside en la cola Flex. No
Queued La ejecución es inminente. El proceso se transfiere de la cola Flex a la cola Jobs, y se mantendrá en esta cola hasta la finalización. No
Preparing El método start es ejecutado, ha empezado el Rock&Roll. No
Processing Se ejecuta la lógica completa del proceso. No
Aborted Es un estado finalista, al que se llega si se decide abortar la ejecución de manera voluntaria. Si
Completed El proceso ha finalizado, pueden existir errores o finalización totalmente correcta. Si
Failed Estado que indica que algo salió mal a nivel de plataforma, y el proceso no fue finalizado correctamente. Si

Veamos como se relaciona la ejecución de un Job con las colas de la plataforma.

4. La Apex Flex Queue(s) y la Apex Jobs Queue

La plataforma Salesforce, ofrece 3 colas, para la gestión de los procesos asíncronos:

  1. Apex Flex Queue (Flex por Flexible)
  2. Test-Context Queue (es la homóloga de Flex para Testing)
  3. Apex Jobs Queue (previamente Apex Batch Queue)

Nota: cuando Salesforce liberó la funcionalidad de la cola Apex Jobs en 2015, se hablaba de la Batch Queue, actualmente este término está deprecado y lleva a confusión, con lo que no usaré esta terminología en este artículo, sinó estricatamente la actual.

4.1. Apex Flex Queue

Esta cola, se destina a encolar los procesos de tipo Batch previa a su inserción en la cola de ejecución de procesos Apex. Permite, la pacificación y la reordenación de estos procesos.

El procedimiento que sigue la plaraforma es el siguiente:

  1. Crear el Job, serializarlo para ubicarlo en las colas de sistema. Si la creación se realizó con éxito (límites, etc.), el sistema retorna un ID identificador del Job (este ID permite inspeccionar las características del Job)
  2. Solo los procesos de tipo Batch, se colocan en la cola Flex Queue, con estado Holding – esto implica que no se está ejecutando – ninguno de sus métodos ha sido invocado excepto el constructor de la clase (esto es importante). En cuanto la plataforma tenga recursos disponibles, ejecutará el Job y lo moverá de la cola Flex a la cola Apex Jobs.
  3. Los procesos asíncronos no Batch, se insertan directamente en la cola Apex Jobs, sin pasar por la cola Flex

En la cola Flex, el proceso posee todos los atributos (15) de ejecución: Job Type, Summitted By, Apex Class, Apex Method, etc., que podemos consultar.

Campos Descriptivos Job Flex Queue

4.1.1. Orden de inserción en la Flex Queue y reordenación de prioridades

El orden de inserción en la cola es fundamental, ya que indicará como el sistema iniciará la ejecución de los Jobs. Por tanto, el orden de inserción marcará el lanzamiento de la ejecución del Job.

Un error común, es considerar que los procesos Batch se ejecutarán uno detrás de otro. Dado que la plataforma puede ejecutar hasta 5 procesos concurrentes simultáneamente, puede que se ejecuten en paralelo aprovechando los recursos disponibles. Por tanto el diseñador de la solución, debe considerar que:

  1. Los Jobs se iniciarán mediante el esquema FIFO (First In First Out).
  2. Los Jobs pueden ejecutarse simultáneamente y se desconoce el orden de finalización, dado que son procesos asíncronos usando recursos compartidos.

Mientras el Job Batch está presente en la cola Flex, sin haber iniciado su ejecución, tanto el administrador mediante interfaz de usuario, como el programador mediante código, pueden alterar el orden de los procesos, y de esta manera alteramos el esquema FIFO.

El Administrador dispone de una interfaz de Monitorización de la cola:

Detalle de la Flex Queue y Opciones disponibles en la interfaz de usuario.

Por su parte, el Programador tiene acceso a 4 métodos de la clase FlexQueue:

  1. moveAfterJob(jobToMoveId, jobInQueueId)
  2. moveBeforeJob(jobToMoveId, jobInQueueId)
  3. moveJobToEnd(jobId)
  4. moveJobToFront(jobId)

4.2. Test-Context Queue (la otra Flex Queue)

La plataforma proporciona una cola adicional, para que los programadores puedan realizar Tests del encolamiento en la Flex Queue. Estos métodos pertenecientes a la clase Test son:

  1. enqueueBatchJobs(numberOfJobs)que permite enviar a la cola el número indicado de jobs
  2. getFlexQueueOrder()que devuelve la lista de los identificadores de los Jobs presentes en la cola

Un ejemplo:

Ejemplo de uso de la Test Flex Queue

4.3. Apex Jobs Queue

Alberga todos los Jobs del sistema, tanto en estados intermedios como no finalistas (ver apartado anterior), tanto Jobs internos de Salesforce como los creados mediante código. Estos son:

Jobs asíncronos:

  1. Future
  2. Queueable
  3. ScheduledApex
  4. BatchApex

Jobs creados por Salesforce para la gestión interna del sistema:

  1. SharingRecalculation
  2. BatchApexWorker
  3. TestRequest
  4. TestWorker
  5. ApexToken

Aunque no documentado por Salesforce (como comenta Pedro Espada en la Success Community) los procesos anotados con @Future se ejecutan prioritariamente, por delante de Queueable y Batchable.

5. Límites de las colas

Es imprescindible conocer los límites sobre las colas y Jobs. En mi opinión lo más importantes son:

Límites Apex Async más importantes para el correcto diseño de la solución
  1. Pueden existir hasta 100 Jobs en estado Holding. Por tanto la profundidad máxima de la cola Flex, es 100 Jobs.
  2. Solo pueden existir 5 Jobs Activos, donde Activos significa en los estados: Queued, Preparing, Processing
Error al superar el límite de 100 Procesos
  1. Hasta 50 Jobs pueden enviarse a la cola Apex Job con la sentencia System.enqueueJob
  2. Análogamente para Jobs @Future también tenemos la limitación de 50 Jobs
Si tratamos de insertar +50 Jobs mediante System.Enqueue en la cola de ejecución Apex Job, obtendremos una excepción

Cualquier inserción en las colas que pretenda superar estos límites, recibe una excepción del sistema, y se rechaza como puede verse en las imágenes anteriores.

6. Cómo se Monitorizan las colas

6.1. Mediante la Interfaz de usuario

La interfaz de Salesforce proporciona acceso a los procesos de la Flex Queue y a la Apex Jobs.

Acceso a los interfaces de Monitorización de las colas

En el caso de la cola Flex además permite la reordenación de los Jobs y acceder a sus características. La reordenación se realiza indicando en qué posición se desea colocar el Job.

6.2. Mediante consultas sobre el objeto AsyncApexJob

Además de la interfaz, la plataforma proporciona un objeto, AsyncApexJob, donde cada registro describe un Job, con todos sus atributos. Este registro se actualiza a medida que el Job va transcurriendo por su ciclo de vida.

Este objeto accesible via SOQL que nos permite:

  • obtener información sobre cuantos Jobs tenemos
  • cuantos son de cada tipo
  • cuantos están en un determinado estado
  • obtener la duración de los finalizados
  • ver las características de un Job concreto, etc.

Los procesos que residen en la cola Flex, también están presentes en AsyncApexJob, ya que son Jobs asíncronos como el resto, aunque en un estado determinado.

Consulta del objeto ApexJobAsync para mostrar los Jobs en Proceso y Completados

6.3. Mediante CronTrigger y CronJobDetail para los Jobs Scheduled

Para los Jobs de tipo Scheduled, la plataforma proporciona además, los objetos CronTrigger y CronJobDetail (existe mucha documentación en Trailhead y la documentación de API de su uso).
A continuación comento lo que considero básico:

  1. Para CronTrigger deben conocerse los campos PreviousFireTime, TimesTriggered, State, NextFireTime, etc., que contienen la información básica de las ejecuciones del Job respecto a sus ejecuciones
  2. CronJobDetail contiene 2 miembros: JobType y Name

7. Retos no cubiertos por la plataforma

Casos de uso que requieren adaptaciones de la plataforma

Reto 1: Tengo procesos dependientes funcionalmente que deben ejecutarse en serie

Conociendo el ciclo de vida de un Job y las colas empleadas para su gestión, podemos encontrar una limitación muy rápidamente: ¿Cómo asegurar que un Job se ejecute y complete previamente a otro, dado que existe una dependencia funcional de negocio entre ellos?

Si consideramos al Job inicial como «Job padre» y el dependiente como «Job hijo», podemos traducir el caso de uso a la inserción del Job Hijo en la Flex Queue no debe realizarse hasta haber concluido la ejecución del proceso Padre.

Para ello tenemos varias alternativas:

  1. Si tenemos Jobs de tipo Queueable podemos utilizar Job Chaining
  2. Si tenemos Jobs de tipo Batchable, en el finish() del padre, podemos lanzar el Job hijo, es decir, aplicar el mismo esquema que Job Chaining pero para Batchable
  3. Sincronizamos la ejecución de los Jobs vía Platform Events: cuando el Job Padre finaliza, lanza un evento para que el Job hijo sea insertado en la Job Queue.

Los 3 esquemas anteriores, sufren de un defecto, ¿qué sucede si el hijo no tiene solo la dependencia de un padre sinó varias dependencias, por ejemplo tener varios ancestros, y/o ancestros pero no iniciarse antes  de las 22.00 aunque sus ancestros estuvieran todos finalizados a las 20.00?

Por tanto, a medida que vamos ampliando nuestros requerimientos de sincronización, vemos que la funcionalidad estándar nos limita, por eso, Para mi la solución es la programación de un planificador dinámico, que veremos en esta entrada.

Reto 2: Tengo Jobs Scheduled que deben ejecutarse a una hora concreta o periódicamente de forma garantizada

Este caso es algo más complejo. Su descripción a lenguaje más clarificador es: **Cuando llegue el momento de ejecución del proceso, debe existir un slot disponible, de los 5 posibles, para su ejecución, y así tener las máximas garantías (no la seguridad total) de que ese proceso podrá ejecutarse (recordar que nunca podemos saber cuando se inicia/finaliza un proceso asíncrono y no hay SLA ni ETC asociados).

Para ello, debemos tener un control de los procesos que están activos en la cola Apex Jobs y de los procesos en la Flex Queue.

Este caso de uso, bajo mi conocimiento, nuevamente un planificador dinámico que controle de forma adecuada ambas colas y su ocupación puede solucionar este reto.

8. Conclusiones

No sé si lo habré conseguido, pero en esta entrada, he intentado proporcionar una visión simple de los tipos de procesos asíncronos y sus principales diferencias con los procesos síncronos, como los gestiona la plataforma mediante colas, como monitorizar su ejecución a lo largo de su ciclo de vida y he finalizado analizando ciertos escenarios que no resuelve directamente la plataforma.

En las siguientes entradas seguiré tratando el procesamiento asíncrono:

Espero que te sea de ayuda, cualquier comentario es bienvenido.

Enlaces interesantes

  1. Asynchronous Processing in Force com – Lectura y comprensión obligatoria
  2. Asynchronous Processing Basics
  3. Monitor Asynchronous Apex
  4. Monitoring the Apex Flex Queue
  5. Monitoring the Apex Job Queue
  6. SOAP API Developer Guide for AsyncApexJob
  7. Differences between job types for ‘AsyncApexJob’ object
  8. Trailhead – Async Apex
  9. Trailhead – Control Processes with Queueable Apex
Anuncio publicitario

4 comentarios sobre “Empezando Apex Asíncrono por las colas

  1. Magnífico blog, no conocía de su existencia. Me ha aclarado el concepto al detalle. Ya tienes un seguidor más en Linkedin y de paso voy a echarle un ojo al libro de los logs, qué bueno encontrar explicaciones tan comprensibles y detalladas en castellano.

    Me gusta

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.