Dynamic Planning for Async Processing

Introduction

As explained in the last 2 entries, asynchronous processing and execution planning capabilities on Salesforce are very useful and powerful.

But nonetheless, in some complex scenarios, you will find some limitations that can be overcome easily.

Let me explain how, with some Apex Developing and using standard capabilities, you can get a quite powerful Dynamic Planner to sort out those limitations.

My goal on this entry is to describe the current limitations on the platform, explain how they can be solved, and hope they are useful and make some contribution to improve your knowledge in this key area.

Continue reading “Dynamic Planning for Async Processing”

Apex Connector Framework – Usar un servicio externo como un Objeto Nativo

Vimos en las entradas anteriores sobre el uso de oData en Salesforce con Connect, pero dejé para más adelante el Apex Connector Framework (ACF), y ha llegado la hora.

Con un caso de uso que espero entretenido e interesante, muestro como el ACF nos abre un fácil integración con sistemas externos que sin él tendría un coste muy elevado, abriendo las capacidades internas de Salesforce Connect.

Si no conoces el ACF, no te preocupes, realizaré una pequeña introducción, y si lo conoces, quizás te intereses saber algo más de criptomonedas 😉

Continue reading “Apex Connector Framework – Usar un servicio externo como un Objeto Nativo”

Planificador Dinámico para Procesos Asíncronos

Introducción

Como hemos visto en las 2 entradas anteriores, las capacidades asíncronas de Salesforce y su planificación son de gran ayuda.

Aún así, vimos que podemos encontrar una carencia: si nuestros procesos asíncronos tiene ncondiciones funcionales o técnicas de las que depende lanzar su ejecución.

Mi objetivo es explicar la idea, ofreciendo una prueba de concepto funcional, para que puedas darle la vuelta, mejorarlo y ampliarlo para tus necesidades.

Continue reading “Planificador Dinámico para Procesos Asíncronos”

Casos de uso para Apex asíncrono

Partiendo del artículo anterior donde vimos como Salesforce gestiona la ejecución de los procesos asíncronos  veamos como seleccionar el/los método/s  más adecuado/s en casos de uso reales.

Introducción

Recordemos las posibilidades que tenemos:

  1. Utilización de la anotación @Future
  2. Implementación de la interfaz Schedulable
  3. Implementación de la interfaz Queueable
  4. Implementación de la interfaz Batchable

Empezaré por los más fáciles para evolucionar los casos de uso, a situaciones más complejas con las que me he encontrado.

Si al principio te aburres no dejes de leer, quizás lo encuentres más interesante a medida que avanzan los casos de uso, y please envíame tus comentarios para que podamos aportar nuevas opciones.

Si por el contrario, crees no tener mucho conocimiento, no es problema, la complejidad de los escenarios, va aumentado, pero siempre de forma escalada.

Espero ayudar así a todos los niveles de conocimiento.

Se requiere ejecutar un proceso asíncrono modificando levemente mi código

Anotación Future para métodos estáticos

Habitualmente este será el caso en el que ya tengamos un método en nuestra clase o vayamos a programar uno nuevo para realizar una operación concreta de forma asíncrona, para no bloquear la operativa del usuario. Ejemplos típicos son realizar una operación compleja sobre datos o invocar un Web Service cuya respuesta no podemos asegurar que sea inmediata.

En este caso la anotación @Future es la candidata ideal, para un método que debe ser estático. La transformación es casi inmediata y seguramente con pocos cambios, podremos tener unos Tests adecuados.

Se requiere que un método de una clase se transforme en asíncrono que reciba como argumentos sObjects

Desafortunadamente una limitación de los Jobs anotados con @Future, es: parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types. Methods with the future annotation cannot take sObjects or objects as arguments.

Por tanto deberemos optar por la creación de una clase que implemente la interfaz Queueable o Batchable.

Se requiere que un método de una clase se transforme en asíncrono y devuelva X o no sea estático

Análogamente al caso anterior, una limitación de los métodos Future es: must be static methods, and can only return a void type.

Se requiere que un Job se ejecute a una hora concreta

Async Apex mediante la interfaz Schedulable

En este caso la mejor opción es la creación de una clase que implemente la interfaz Schedulable.

Aunque poco comentado habitualmente, es posible la implementación conjunta de las interfaces Schedulable y Batchable en la misma clase, obteniendo la capacidad de ejecución de un proceso Batchable pero con ejecución programada (en un caso posterior adjunto captura de pantalla de un ejemplo).

Se requiere un Job se ejecute de forma recurrente

Igual que el anterior, solo es necesaria adoptar la expresión CRON adecuada. Para la construcción de expresiones CRON existen múltiples webs.

Se requiere la ejecución de varios Jobs de forma secuencial, sin concurrencia por dependencia funcional

Existen 2 opciones:

La opción 1: Creación de una clase que implemente la interfaz Queueable y como última sentencia del método execute, lanzar el siguiente proceso mediante System.EnqueueJob(new ProcesoSiguiente()), lo que llamamos habitualmente Job Chaining.

La opción 2: Menos común y documentado, existe la posibilidad  de crear de una clase que implemente la interfaz Batchable y como última sentencia del método finish, lanzar el siguiente proceso mediante Database.executeBatch(new Proceso_Siguiente()), que es el mismo concepto de Chaining visto anteriormente, pero con las capacidades de Batchable.

Se requiere un único Job sobre una gran cantidad de registros pero en segmentos secuenciales

Async Apex con job rellamándose asimismo para gestionar un volumen de datos elevado secuencialmente

Este caso de uso, es una idea original de Scott Lee, explicado en Pluralsight.

Este caso simula una ejecución iterativa sobre una misma clase (laxamente hablando), sobre un conjunto de registros (podría ser muy elevado) utilizando un índice para determinar los paquetes que aún no han sido tratados.

Como creo que No se entiende nada, intento explicarme mediante un ejemplo:

  • Supongamos que tenemos 1 Millón de registros de Accounts. Estas Accounts tienen un Custom field, provincia.
  • El requerimiento consiste en procesar la información (para realizar un cálculo cualquiera) secuencialmente por provincias ordenado:
    • primero debemos considerar solo los Accounts de Álava
    • al haber finalizado ese proceso debemos abordar los de Albacete
    • al haber finalizado ese proceso los de Alicante
    • … y así hasta finalizar con todas las provincias hasta finalizar

Es decir solo cambian los datos, pero el Job siempre es el mismo, no queremos concurrencia, dado que podríamos estar accediendo a un recurso limitado (por ejemplo un Web Service, o una transacción que no admite concurrencia, etc.). Esto se puede solucionar creando una clase con la siguiente firma y ejecución donde la clase se invoca a ella misma:

Esta clase permite, gestionar un gran volumen de datos, mediante la ejecución iterativa, y además puede ser invocada mediante una llamada Cron.

Se requiere procesar N millones de registros (siendo N<50 millones)

Job asíncrono para gestionar millones de registros

Existen varias opciones, y enumero el orden de mi preferencia:

Opción 1: una clase que implemente la interfaz Batchable. Esta es mi opción preferida, porque es la más simple (KISS), y deja en manos de la plataforma la creación de los procesos internos y reporta de forma centralizada los resultados en el ApexAsyncJob en una sola entrada. Es fácil reportar, analizar, y diagnosticar, pero puede no ser la más eficiente.

Alternativamente como opción 2: una clase que implemente la interfaz Batchable, pero con esquema de ejecución distinto.

  • Aquí enviamos a la Flex Queue 5 instanciaciones de la clase con un volumen proporcional para cada instancia, alrededor del 20% en cada una.
  • Dado que la plataforma soporta hasta 100 procesos Batch en estado Holding, y 5 procesos en Activo (esto es Queued, Preparing ó Processing) conseguimos la máxima paralelización de los procesos. Existen varios inconvenientes en mi opinión para este esquema que no sea mi preferida:
    1. La monitorización del proceso está dividida en 5 procesos técnicos
    2. Podemos provocar, o seguro provocaremos retardo en el resto de los procesos asíncronos de la ORG, dado que consumimos los 5 slots posibles (por supuesto disminuir ese número alivia esta situación) para procesos activos
    3. Un acceso tan concurrente sobre un objeto/s puede provocar ciertos bloqueos en en el caso de operaciones de DML (debe valorarse en cada caso el controlar la ordenación de los registros por clave, etc.) que pueden ralentizar los tiempos de ejecución

Como opción 3: implementación de una clase con la interfaz Queueable mediante el uso de auto-Chaining, aplicando el método comentado anteriormente. Por supuesto el proceso es mucho más lento, pero al ejecutarlo secuencial por paquetes, podemos obtener ciertos beneficios de menor concurrencia, control temprano de errores, etc.

Como opción 4: otra alternativa con mejor rendimiento, consiste en un esquema de ejecución tal que, lanzar tantos Jobs de esta clase como conjuntos de datos querramos. Es decir, nuevamente encolamos 5 o N ejecuciones de esta clase. En el momento en que la plataforma disponga de recursos esos Jobs se ejecutarán en paralelo hasta un grado máximo de 5.

  • Esta implementación puede ser apetecible para usar Queueable (evitar cambios de código) y segmentar el proceso en N jobs. Eso si, la segmentación de los datos y encolamiento requiere una preparación previa, pero no modificar el código existente.

Se requiere procesar N millones de registros (siendo N>=50 millones)

Async Apex para volúmenes superiores a los 50 millones de registros

Las alternativas son las mismas que el apartado anterior, pero creando tantos procesos de tipo Batchable o Queueable que conformen el volumen total, sin superar los límites de la plataforma.

Aunque la documentación oficial alienta al uso de Jobs Batchable, que también es mi opción preferencial, un Chaining con Queueable en sus  variantes anteriores también consiguen el procesamiento de grandes volúmenes de datos.

Mi preferencia sigue siendo el uso de varios Batchable y dejar que la plataforma gestione el job de forma completa.

Se requiere el máximo rendimiento sin afectación ninguna sobre el rendimiento de los procesos existentes

Heroku y Heroku Connect como alternativa a la ejecución de procesos complejos fuera de la plataforma para no afectar el rendimiento
Heroku y Heroku Connect como alternativa a la ejecución de procesos complejos fuera de la plataforma para no afectar el rendimiento

Mi opción preferida obliga al uso de recursos externos, y creo que idealmente usando Heroku. Cualquier otra IaSS o PaSS requiere de movimiento de datos que descartan un buen rendimiento excepto si estuviéramos usando Salesforce Connect para acceso a esos datos y la ejecución la lleváramos a cabo en la plataforma externa.

Heroku y Heroku Connect poseen capacidades no presentes en Force.com:

  • podemos aumentar/disminuir la capacidad de computación en base a nuestras necesidades o a condiciones circunstanciales puntuales
  • podemos modificar la funcionalidad sin necesidad de cambios en la ORG (desplegamos nuevas versiones de nuestro código en Heroku)
  • mantenemos la capacidad de cambios en los datos bidireccionalmente
  • programamos en el lenguaje y utilizamos las herramientas de desarrollo que dominamos

Tiene un coste asociado dado que la ejecución se realiza fuera de la plataforma y se usan recursos en Heroku.

Se requiere ejecutar un Job al cabo de 6 horas de su última ejecución (que no es lo mismo que un Job se ejecute cada 6 horas)

Ejecutar_Apex_Job_Cada_Ciertas_Horas

Existen varias opciones. La opción 1: consiste en Implementar un Job con la interfaz Schedulable conjuntamente con Queueable/Batchable.

  1. En caso de Queueable la última instrucción del método execute será una llamada a System.scheduleBatch con una expresión CRON que sea del momento actual + 6 horas.
  2. En el caso de Batchable lo haremos en la última línea del método finish.

La opción 2 consiste en que, al finalizar el proceso, lanzar un Platform Event que un Trigger recojerá para ejecutar el mismo System.scheduleBatch comentado.

Esta opción, aunque parece más rebuscada, permite un tratamiento de datos o coordinación con otros procesos antes de la planificación que nos pueda interesar.

Se requiere la ejecución condicionada de un Job sólo si otros procesos “ancestros” se han ejecutado previamente

Solo puedo ejectuarme cuando otros procesos, que denominados Ancestros, han finalizado su ejecución

Un ejemplo: el proceso de envío de nóminas solo debe ejecutarse, si previamente han finalizado 2 procesos: (1) el de cálculo de Bonus por ventas realizadas y (2) el de cálculo compensaciones familiares.

Inicialmente podríamos pensar que encolando 3 procesos de forma secuencia sería suficiente, se ejecutarán en secuencia. Este es un error común que no recuerda que la plataforma puede ejecutar hasta 5 procesos concurrentes. Por tanto necesitamos, un “coordinador” que compruebe la ejecución de los ancestros, previa ejecución del proceso dependiente.

No considero una opción válida la planificación del proceso dependiente, validando en su método constructor si sus padres se han ejecutado, y ejecutarse en caso positivo o replanificarse en caso negativo, ya que es un Prueba-Error con consumo innecesario de recursos.

No es una opción óptima el encadenamiento de los 3 procesos mediante Chaining, dado que los procesos de tickets de comida y de cálculos familiares pueden ejecutarse en concurrencia, lo que supone no aprovechas los recursos del sistema.

En general, la ejecución condicionada  de un Job a la finalización de otros procesos, se resuelve correctamente con:

  1. Lanzamiento de eventos de plataforma avisando de finalización del proceso
  2. Se introducen Triggers que escuchan estos Eventos y ejecutamos lógica de validación de las condiciones mediante el acceso a AsyncApexJob, donde encontramos el historia de ejecuciones de los procesos asíncronos.
  3. Cuando el último de los procesos finaliza, la lógica comprobará que en ApexAsyncJob todos los procesos ancestros han sido ejecutados, e incluso podemos validar su finalización, y ejecutar el proceso hijo.

Esta solución que solventa el caso de uso, se convierte en una maraña de Triggers y procesos de control cuando son muchos los procesos y varias las condiciones a cumplir.

Por ello,  IMHO ya tenemos las primeras señales de la necesidad que nos acercamos a los límites funcionales de las capacidades de planificación de la plataforma y debemos abordar el diseño de un planificador dinámico.

Casos de uso no cubiertos por la Plataforma

Casos de Async Apex no cubiertos por la plataforma – Homer y yo le damos vueltas al tema

Supongamos que debemos ejecutar el proceso X a las 3.00 de la mañana con las máximas garantías de ejecución (es decir, debemos garantizar que a las 3.00, al menos queda 1 slot libre de los 5 disponibles) cuando tenemos otros tantos procesos en posible ejecución

  • Aunque podemos preparar un calendario para intentar asegurar que a las 3.00 hora no tengamos 5 procesos activos, esta no es la situación idónea, dado que por circunstancias X pueda ser que no se cumpla. Si somos muy conservadores, estaremos desaprovechando capacidades de la plataforma.
  • Por ello, aquí detectamos la necesidad de establecer un control de las ejecuciones, de sus dependencias y sus condiciones de ejecución, para controlar el flujo de ejecución, conocer el estado de la plataforma, y con toda esta información construir un planificador dinámico propio que tome la decisión de creación o no de los procesos que estén parametrizados.

Si has llegado hasta aquí, te mereces un premio!!

Conclusiones

Las capacidades asíncronas y el rendimiento obtenido en Salesforce son excelentes, y nos permiten delegar en recursos especializados tareas que podrían comportar problemas de rendimiento para el usuario online.

Por experiencia propia, es importante notar que estos procesos se ejecutan cuando la plataforma tiene recursos disponibles, que es muy a menudo, pero no debemos diseñar pensando que tendremos ejecuciones en cierto momento, con cierto tiempo de respuesta, porque en algunos casos puede ser una experiencia frustrante (recordemos que estamos en un entorno multi-tenant).

En términos generales, mi preferencia es inicialmente la implementación  de la interfaz Batchable, dadas sus capacidades y simplicidad de uso, reporting y seguimiento incluso combinándola con Schedulable para programar su ejecución.

El uso de la anotación Future, está circunscrito a casos muy concretos o limitar el refactoring del código para implementar una interfaz, que en la mayoría de los casos no es complejo, y en cambio aporta unas capacidades muy superiores.

El concepto de Chaining es poderoso, y esquemas de ejecución como el de Scott, aportan ideas para estrujar la plataforma mediante código elegante y mantenible.

Como no, la siguiente entrada será un ejemplo de un Planificador Dinámico que da respuesta al caso de uso  que hemos visto, que la plataforma no cubre, pero eso lo veremos un poquito más adelante.

Por favor, no dudes en enviarme tus comentarios, opinar sobre los casos de uso, sobre mis preferencias, etc., es muy enriquecedor obtener los puntos de vista de otras personas.

Empezando Apex Asíncrono por las colas

1. Introducción

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.

Continue reading “Empezando Apex Asíncrono por las colas”

Introducción a la Arquitectura de Eventos en Salesforce

“Four years from now, ‘mere mortals’ Will begin to adopt an event-driven architecture (EDA) for the sort of complex event processing that has been attempted only by software gurus [until now]’
—Roy Schulte (Gartner), 2003

En esta primera entrada de una serie, intento situar, cuales son los mecanismos existentes en Salesforce, cuyo core es el uso de Eventos, e intento compararlos y ubicarlos en sus casos de uso.

Podría decirse que esta es una entrada 101 en Eventos de Salesforce.

En mi experiencia, no es trivial entender los “productos/mecanismos” que ofrece y ofrecerá Salesforce sobre eventos (Streaming API, Platform Events, etc.), y las tecnologías (Kafka, Bayeaux, Long Polling, etc.)  asociadas y los casos de uso a que dan respuesta.

Por ejemplo, el título de esta entrada es incorrecto, ya que debería ser algo así como: Introducción a los mecanismos de la Salesforce Enterprise Messaging Platform (pero con ese nombre …), espero pues, que el resto del artículo no sea como el título ;-).

Continue reading “Introducción a la Arquitectura de Eventos en Salesforce”

BULK API v2: 2 veces más rápida con la mitad de código

Una de las novedades que quizás pasaron inadvertidas en la última release de Winter ’18, fue la nueva versión de la BULK API, denominada BULK API v2, disponible en v41.0.

Esta nueva versión, sigue siendo una API REST, que utiliza los verbos HTTP para crear Jobs, cerrar/abortar, eliminar y obtener información al respecto, aportando novedades para el programador y una mejora del rendimiento para el usuario final.

En esta entrada, se muestran las diferencias entre ambas versiones y se compara el rendimiento.

Continue reading “BULK API v2: 2 veces más rápida con la mitad de código”

Backup en Salesforce: Opciones disponibles y Alternativas

58% of downtime incidents are caused by human error alone (Boston Computing Network)

Every Minute 3,535 data Records are lost (breachlevelindex)

En este artículo, se enumeran los mecanismos nativos en Salesforce para la realización del Backup de datos, y su recuperación. También se analizan los puntos débiles de estas mecanismos ante los casos de uso más habituales de pérdida de datos.

Continue reading “Backup en Salesforce: Opciones disponibles y Alternativas”

Las Named Credentials simplifican el código Apex de Callouts mediante configuración estándar

La mayoría de los proyectos de Salesforce requieren Callouts para integrarse e invocar servicios en sistemas externos. Habitualmente estos Callouts, requieren de código Apex, el cual, puede volverse costoso, voluminoso y engorroso de mantener si desconocemos las Named Credentials.

Continue reading “Las Named Credentials simplifican el código Apex de Callouts mediante configuración estándar”

Replicar cambios en Salesforce hacia sistemas externos – Opciones y alternativas

No creo que sea casualidad que, en cada nueva versión, Salesforce introduzca mejoras sustanciales, a la permeabilización de sus datos y en especial, intentar hacerlo de forma eficiente, estándar y cada vez más simple.

Hasta hace relativamente pocos años, la integración entre Salesforce y sistemas externos, estaba limitada a unos escenarios concretos y a unas APIs reducidas.

Continue reading “Replicar cambios en Salesforce hacia sistemas externos – Opciones y alternativas”

Big Objects: Contenedores de Datos – un quiero y quizás puedo de almacenamiento masivo en Salesforce

En la entrada anterior, describía el caso de uso de cómo acceder a una gran volumen de datos desde nuestra ORG via External Objects, y dejaba la puerta abierta a la alternativa a la funcionalidad nativa de Big Objects en Salesforce.

Esta entrada describe qué son, en qué casos de uso pueden aplicarse, cómo crearlos, insertar datos (con Data Loader que parece ser un caso poco documentado) y describir sus características y restricciones, que no son pocas.

Continue reading “Big Objects: Contenedores de Datos – un quiero y quizás puedo de almacenamiento masivo en Salesforce”

Reporting sobre una Arquitectura Híbrida: Amazon-Salesforce usando Salesforce Connect

Una de las limitaciones que existian en referencia al uso de External Objects, era su limitada capacidad de Reporting.

En un artículo de Mark Kovacevich, Salesforce Connect Reporting, explicaba un workaround mediante programación en APEX:

  • Mostrando una List View con un Controller básico
  • VisualForce que con un Custom Controller muestra los registros y pinta un par de diagramas.

Continue reading “Reporting sobre una Arquitectura Híbrida: Amazon-Salesforce usando Salesforce Connect”

Salesforce Connect para acceder a datos en Amazon RDS via oData

Supongamos el siguiente caso de uso:

  • Queremos acceder a una gran cantidad de datos, que están fuera de nuestra ORG de Salesforce (presumiblemente en una base de datos en nuestro CPD)
  • Queremos acceder a estos datos, sin interfaces ni APIs
  • Queremos realizar reporting y análisis, cruzando esta base de datos con nuestros objetos declarados en nuestra ORG

Continue reading “Salesforce Connect para acceder a datos en Amazon RDS via oData”

Integración Continua en Salesforce (5): Conclusiones Finales

Partimos inicialmente con el deseo y con la convicción de que la Integración Contínua en Salesforce es completamente necesaria, y esa convicción, a pesar de los retos y condicionantes observados,  sigue intacta.

Lo que ha cambiado completamente, es la simplificación con la que se habla y se predica la adopción de este proceso en modo DIY (Do it Yourself).

Continue reading “Integración Continua en Salesforce (5): Conclusiones Finales”

Integración Continua en Salesforce (3): proceso y uso de la herramienta de despliegue

El proceso

Despliegue por diferencias

El proceso de despliegue en Salesforce, a diferencia de, por ejemplo, en el mundo Java, no se realiza desplegando un fichero .ear/.war que contiene todos los componentes y sustituye de forma completa al anterior , sinó que se realiza mediante el despliegue de los componentes añadidos/modificados y listando aquellos que queremos eliminar, lo que se suele llamar incremental, por diferencias (en adelante usaré este último término).

Continue reading “Integración Continua en Salesforce (3): proceso y uso de la herramienta de despliegue”

Una posible adopción de gitFlow en proyectos Salesforce

Vincent Driessen en su blog GitFlow- A successfull Branching Model, describe el casi proceso de facto que aplican muchos equipos de desarrollo para la gestión de ramas (aunque prefiero la explicación y gráficos de AtlassiangitFlow Workflow.)-.

En esta entrada, intento explicar por qué, al menos en mi caso, no es directa su aplicación en un proyecto de Salesforce y las consideraciones adicionales y conclusiones a las que he llegado.

Continue reading “Una posible adopción de gitFlow en proyectos Salesforce”

Skinny Tables para la mejora de rendimiento Salesforce

Supongamos que después de haber seguido las buenas prácticas de diseño, programación, aplicado índices donde era necesario, seguimos teniendo problemas de rendimiento de un Report/Dashboard o SOQL concreta.

Como almacena Salesforce la información internamente

Continue reading “Skinny Tables para la mejora de rendimiento Salesforce”

Mi lista de Limitaciones en Integraciones de Salesforce

Creo que todos lo hemos sufrido -> “Salesforce no soporta FTP nativo” -> Mala cara.

Integración de Salesforce

De mi background como arquitecto de Integración esa afirmación sorprende, pero cuando conoces las capacidades de Integración de Salesforce y otros aspectos como su Seguridad, Fiabilidad, Documentación, Comunidad, etc., se te pasa el susto.

Mantengo una lista de las limitaciones (no en el aspecto negativo) que comparto por si pueden ser de ayuda a alguien y ahorrar algo de tiempo. Por favor, si hay alguna incorrecta (lo siento de antemano) o me faltara alguna, pido por favor mencionarlo, para tener una lista mejor.

  1. Salesforce no tiene un BUS de Integración propio (aunque con Platform Events, Lightning Connect, Streaming API, etc., se da respuesta a muchos casos de uso)
  2. Salesforce no soporta transacciones ACID
  3. Salesforce no soporta WS-Security (https://en.wikipe
  4. dia.org/wiki/WS-Security)
  5. Salesforce no implementa WS-ReliableMessaging (https://en.wikipedia.org/wiki/WS-ReliableMessaging) – que utilizando Outboung Messaging queda mitigado por la lógica de los reintentos cada 10” durante 24h
  6. Salesforce no soporta WS-Addressing, lo que complica el enrutamiento dinámico, en un escenario de Orquestacion empresarial con BUS de Integración disponible
  7. Con Outbound Messaging, no podemos invocar servicios REST (pero hy abierta Idea 08730000000DhyEAAS)
  8. Con Outbound Messaging si al cabo de 10” no hay respuesta se reenvia la petición (hay que certificar Idempotencia en el diálogo)
  9. Con Outbound Messaging solo es posible enviar datos de un objeto, aunque puede recibirse del objeto y de sus objetos relacionados
  10. Las Workflow Rules no son aplicables el borrado de un registro, por lo tanto, no podemos invocar a un servicio externo directamente (existe Workaround mediante trigger)
  11.  Entornos con grandes volúmenes de datos, típicos de un Patrón de Batch, que requieran el uso de BULK API tanto en modo Serial como Parallel, con o sin Chunking, son difíciles de abordar sin herramientas ETL de terceros (que habitualmente tienen un CTO elevado). Nosotros utilizamos Informatica Cloud, aunque ODI y estoy seguro que otras facilitan el uso de BULK API.
  12. Los certificados para comunicación segura con Salesforce deben renovarse anualmente (un poco tedioso para los compañeros de sistemas)
  13. No hay una versión oficial de Data Loader para Linux (es una herramienta de escritorio para Windows y Mac, pero la posibilidad de usarlo como carga masiva usando la BULK API en servidores empresariales Linux es siempre muy tentador y podría…)
  14. Salesforce no proporciona una herramienta de escritorio de ETL simple para que el equipo de negocio pueda cargar datos transformándolos mínimamente (Mass Loader/Update y herramientas como Jitterbit y Dataloader.io, pueden suplir en parte esta carencia)
  15. El Force.com Excel Connector dejó de soportarse hace mucho tiempo, y muchos usuarios preguntan por funcionalidad similar

No menciono los Governor Limits, pq creo que son protecciones necesarias en un entorno Multi-tenant, y en muchos casos, romperlos implica que la solución adoptada no es la adecuada.

Seguramente tenemos otras de muy bajo nivel técnico, pero mi intención es solo compartir mi lista y si es posible mejorarla.

*Si perteneces a Salesforce y lees este artículo, no fruncir el ceño por favor, no hay mejor elogio para un fabricante, que sus clientes utilicen sus herramietnas y la conozcan bien.

Crédito de la imagen para: elearningindustry.com

Data Loader en CLI en Linux/Unix/Mac OS

Data Loader es una herramienta creada en Java, con su código disponible en gitHub, lo que nos permite descargar su código, y montar sus artefactos mediante maven.

 

Todos conocemos la interfaz gráfica, pero como se explica en la documentación del mismo Repositorio de gitHub, también ofrece una clase (com.salesforce.dataloader.process.ProcessRunner) para la invocación por línea de comandos  (CLI – Command Line Interface) en cualquier sistema operativo que disponga de una máquina virtual Java instalada.

Esto permite, por ejemplo, planificar (mediante CRON) cargas/descargas desde servidores empresariales Linux/Unix, y haciendo uso de Bulk API (hay otros muchos casos de uso ).

Utilizar Data Loader via CLI es muy senzillo y se describe en la documentación de Salesforce. Resumiendo son 3 pasos:

  1. Generar nuestro password encritpado en 2 pasos
  2. Crear el mapeo de los campos entre el fichero que cargaremos y el objeto destino
  3. Crear el fichero process-conf.xml q contiene el detalle del proceso a ejecutar (Operación, uso de BULK API, etc.)

Pero si además, estos 3 pasos nos parecen complejos/tediosos existe una herramienta llamada CLIq, que nos automatiza esta generació. Esta herramienta también está disponible en gitHub.

En la imagen adjunto, se observa la ejecución que realizo en el Linux más raro que he tenido nunca, Bash de Ubuntu en Windows, gracias al Windows Linux Subsystem, lo que demuestra que mientras haya disponible una máquina virtual de Java instalada, podemos ejecutar Data Loader y conseguir una nueva herramienta en nuestro arsenal de Integración.

Ejecución de Data Loader en Bash Ubuntu Windows Linux Subsystem
Ejecución de Data Loader en Bash Ubuntu Windows Linux Subsystem

Documentación para profundizar:

Replication API para identificar cambios

La Replication API de Salesforce tiene como objetivo, identificar todos los objetos modificados duante un intervalo de tiempo.

Esta API SOAP, permite obtener en un interval de tiempo, aquellos objetos nuevos, modificados o eliminados en nuestra ORG.

Aunque también esto es posible accediendo a los campos Audit de los registros de los objetos, esta API tiene una característica muy importante: es accesible via 2 métodos de la clase Database: getUpdated(), getDeleted() y es transversal a todos ellos.

En concreto se obtiene, un array de IDs de los registros  nuevos/modificados o eliminados, y la hora en la que se ha realizado la consulta (para poder encadenar posteriormente otra).

Esta API, y supongo de ahí el nombre que le puso Salesforce (y que en mi opinión no es del identificador de su funcionalidad), está dirigida a la Integración de sistemas (obtener los cambios realizados para sincronizar con otro sistemas). Pero existen otros escenarios donde puede ser útil: la  auditoría de cambios durante un evento especial, reconciliación datos etc.

Ejemplo básico de utilización:

Captura de pantalla de uso de la Replication API de Salesforce
Captura de pantalla de uso de la Replication API de Salesforce

Enlaces para saber más: