1

What is the best way about getting the final sObject state from an update? I realise I could create an event that would trigger after commit to get a very likely final state but I want to get the absolute final state so I can push this out to another service.

2 Answers 2

1

I would go with the Platform Event approach, as both you and @sfdcfox have mentioned.

However, bear in mind that a trigger can be invoked multiple times for the same DML action (and before/after phase) for the same record in the same DML flow (let alone in the over-all transaction) if you have any non-Apex automation (flows, process builders, workflows) that updates the record, as per step 14 in the Triggers and Order of Execution processing.

As such, I recommend you have a static set of IDs for records for which you have already created and published a Platform Event (you will need to only do this in the after phase to ensure an ID is available) and suppress creating and publishing any more for those IDs in the current transaction.

You should use an After Commit publish behaviour. That way the platform events will only be dealt with after successful completion of the over-all transaction against Salesforce (so when the SObject DML actions are finalized in the database).

Note that if this platform event handling is implemented using a trigger-based subscriber then the PE daily limits are not applied (these apply to CometD and EMP only as per the documentation). These executions are also not counted towards async executions either (though therefore have synchronous processing limits applied to them).

You'll then need to perform some form of callout to send the details to the external system.

Being based on a trigger, you cannot directly perform callouts and will have to actually handle that in async processing (e.g. via a future or queueable fired from the trigger-based subscriber) and this is then when you face your daily limits. The good news is that the platform events are processed in chunks (of up to 2000 at a time) and you can leverage this if you are able to construct composite callouts to your external system, sending the up to 2000 "final SObjects" in a single callout (callout payload maximum size and external system willing; see also the callout limits and limitations documentation).

Salesforce may even aggregate up platform events published in separate calls to EventBus.publish that happen in the same over-all transaction, for passing to your trigger-based subscriber (I've not verified this though).

12
  • 2
    One caveat to keep in mind depending on what this solution is intended to provide, platform event messages (and change data capture events) are not guaranteed to be delivered. They may be published and silently never received by any subscriber (including apex subscribers).
    – Mark Pond
    Commented Mar 17, 2021 at 23:58
  • The main purpose of this is that we have an external tool we use for timesheets and expenses etc we want any updates to this data on salesforce to be pushed out to this external platform as they happen but we have hit the issue of using triggers only not giving us 100% consistent output based on OOE and multiples sent. Commented Mar 18, 2021 at 1:49
  • @markpond please reference where it is documented that apex subscribers are not guaranteed delivery. I have not heard this before.
    – Phil W
    Commented Mar 18, 2021 at 7:13
  • The closest I know of is in this doc which discusses persistence at the end; I suggest this is to cover the unlikely event of a server failure, and subsequent loss of queue content, rather than something likely to occur. So, yes, there is a very small chance events could be lost.
    – Phil W
    Commented Mar 18, 2021 at 7:46
  • 1
    @PhilW it is much more than a small chance of failure to deliver, I've seen it first hand a significant amount. The statement at the end of the considerations docs for both PE and CDC is very recently added (v49?) as a direct result of utilizing those features in a solution that required guaranteed delivery and then seeing that not all messages were being delivered. (real world use case: don't use PE or CDC for building something like an audit logger for compliance, where every 'message' is critical)
    – Mark Pond
    Commented Mar 18, 2021 at 17:56
0

You have many options available to you. You can use a @future method, a Queueable class, a Workflow Outbound Message, a Capture Data Change trigger, or an After Commit Platform Event, or third-party support such as an Enterprise Service Bus or replication service using the Updated sObject/getUpdated resources.

Which is "best" is a bit arbitrary, as it depends on what capabilities you have both in Salesforce and the third-party service, but these are all potential solutions depending on data volume. Basically, anything that can run after the final commit is a viable option, and all of these can (or by their very nature, do) run only on the final state of an sObject.

The future/queueable option has a limit of 250,000 transactions per day, outbound messaging should be 1,000/hour (24,000/day), CDC and Platform Events are 10k-50k per day depending on Salesforce Edition, and off-server solutions are only limited by your API rate limits, which are much higher for most orgs. You'll want to consider how much code you want/are willing to develop, how large the expected data volume is, etc.

1
  • we need it to be as "real-time" as possible I don't mind the code but this is for timesheets expenses etc. it makes calling this from an external platform not really useable. Commented Mar 18, 2021 at 1:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .