Avoid making 2 callouts for the same record

apexasynchronouscalloutplatform-event

After a record is updated, i need to perform a callout to an external system, in order to synchronize the data. For that purpose, i have created a record-triggered flow for my custom object that:

  • After record is updated
  • invokes an Apex invocable method (asynchronously) to perform the callout.

I will describe what i am trying to achieve with an example:

  1. User goes to the record, changes data and clicks the save button
  2. Record Triggered flow is triggered to make the callout (We don't know when the callout will be performed)
  3. User goes again immediately and updates again the record
  4. Record Triggered flow is triggered to make the callout (We don't know when the callout will be performed)

What i want to achieve is avoiding making the second callout if the first hasn't been performed yet.My goal is to avoid invoking multiple times the external system for the "same" dataset. Is there a way to handle this somehow? Could Platform events help handle this somehow?

Best Answer

I would handle this with platform cache. Your invocable Apex should do the following high-level steps:

  1. define a cachebuilder class. See (https://github.com/trailheadapps/apex-recipes/blob/main/force-app/main/default/classes/Platform%20Cache%20Recipes/PlatformCacheBuilderRecipes.cls) for details. This cachebuilder class should store 'status' (enum) and 'result' properties in addition to the unique key
  2. Immediately on entrance to the invocable method, look up or create a cachebuilder instance.
  3. if the returned cachebuilder instance has status = status.INPROGRESS, return doing nothing further.
  4. if the returned cachebuilder instance has status = status.COMPLETE, return the cached result property. (remember to set your cache timeout)
  5. if the returned cachebuilder instance has status = status.NEW, invoke the callout and update the cachebuilder instance.

Some benefits of this approach:

  1. you're not doing DML on records, so you're avoiding the potential for recursive triggers/record triggered flow situations.
  2. this allows you to also cache the resulting data from your third party service for a period of time. This may be a two-edged sword, depending on what the third party service is doing.
  3. every org gets a bit of platform cache, so this is effectively using the platform to your advantage.

All of this hinges on a good understanding of the platform cache and cachebuilder class interface. The Apex-recipes link above is a great example of how to use cachebuilder but be sure to also look at it's corresponding test class. (https://github.com/trailheadapps/apex-recipes/blob/main/force-app/tests/Platform%20Cache%20Recipes/PlatformCacheBuilderRecipes_Tests.cls)

Related Topic