jamessimone / apex-rollup

Fast, configurable, elastically scaling custom rollup solution. Apex Invocable action, one-liner Apex trigger/CMDT-driven logic, and scheduled Apex-ready.
MIT License
202 stars 27 forks source link

Incorrect rollup calculations when child records are inserted in separate transactions at the same time #579

Closed puneetagarwal2971 closed 1 month ago

puneetagarwal2971 commented 3 months ago

Recreate issue: Bulk Insert child records with a smaller batch size(let's say 1) and use multiple threads, the rollup calculations get messed up. This is because the parent record update is performed in an Async Queueable context unlike the parent record being locked for sometime in native salesforce roll-ups. Eventually, each thread tries to update the parent record rollup field parallelly but does not wait for either. E.g. Initial Count() - 0 Try inserting 2 records parallelly, then both try to update Count to 1 instead of 1+1 = 2.

Use Case: We have integrations that are pushing records in smaller chunks in separate transactions.

jamessimone commented 3 months ago

@puneetagarwal2971 what is your Max Parent Rows Updated At Once value and is that lower than your Batch Chunk Size? The parent updates shouldn't be happening in a separate queueable unless that condition is true, and if they're updated at the same time as each batch chunk is committed the proper values should be applied

puneetagarwal2971 commented 3 months ago

@jamessimone In my scenario, I'm inserting 100 child records all linked to one single parent. But the only tweak I'm doing is batch size = 1, and threads = 6 while inserting data. image

Now, the rollup count result should be 100 but instead, it is a lot lesser.

The same happens if I delete all the related child records. Let's say we have Rollup Count = 100, and we delete all 100 child records in batch size = 1. The Rollup Count should become 0, but again that's not the result I'm getting. Its count is decreasing but not to zero.

jamessimone commented 3 months ago

Have you tried setting the Is Full Record Set flag on your rollup metadata?

puneetagarwal2971 commented 3 months ago

Yes, thanks @jamessimone! The numbers the accurate now with above query-based rollup setting.

But for some records, I still see the error: UNABLE_TO_LOCK_ROW: unable to obtain exclusive access to this record or 1 records which points to the parent record ID. I'm thinking of moving to a schedule-based rollup to avoid lock-row issues. Please let me know if there's a better approach to this. Also, thanks for building this awesome rollup package!

jamessimone commented 3 months ago

With a batch size that small, I could see row locks being intermittent - reason being that children associated with the same parent sent through will be contending for the update at the same time. As you said, a schedule-based rollup may be more appropriate if you can't increase your batch size for other reasons.