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
222 stars 30 forks source link

Apex Schedule Job is not handling the bulk records. #639

Closed KomalJha01 closed 1 week ago

KomalJha01 commented 1 week ago

I have a field Year_of_Membership on Contact, which calculates the number of Memberships. In my environment, there are more the 2 million records so when I'm scheduling the job via an anonymous window. Using the script // Method signature: (String jobName, String cronExp, String query, String rollupObjectName, Evaluator eval) _Rollup.schedule( 'My example job name', 'my cron expression, like 0 0 0 ?', 'my SOQL query, like SELECT Id, Amount FROM Opportunity WHERE CreatedDate > YESTERDAY', 'The API name of the SObject associated with Rollup_mdt records configuring the rollup operation', null ); I'm getting this error "Too many query rows: 50001" I've investigated and found that the code fails in the schedule method where it is querying the records

So, I created my batch class for the query and called the roll.runCalc() directly in a similar way to the schedule method of Rollup. The only thing I changed in the Rollup class is that Making getRollupMetadataBySObject and getRollup Public.

jamessimone commented 1 week ago

You can do this much more easily by using scheduled flow in conjunction with the Full Recalc apex action (the one that accepts a comma-separated list of Custom Metadata developer names)

KomalJha01 commented 1 week ago

But in this case, It will run the whole membership(more than 2 million) at every scheduled time which is not effective, I want to calculate the Years_of_Memberships on the contact only when a new membership is added to any contact. so I created my custom class and called the roll.runCalc() directly in a similar way to the schedule method of Rollup. Making getRollupMetadataBySObject and getRollup method Public. so, can you make getRollupMetadataBySObject and getRollup Public?

jamessimone commented 1 week ago

But if you already have the list of records you want to pass to Apex Rollup, you can much more easily accomplish what you're currently doing by making your custom class the Schedulable and simply invoking Rollup.runFromApex with the list of records you're querying. I'd recommend reviewing the existing methods that are already exposed, as you shouldn't need to get so deep into the private stack to accomplish the calculation you're talking about!

KomalJha01 commented 1 week ago

Okay Thanks, I'll take a look into it.

KomalJha01 commented 22 hours ago

Hi @jamessimone I tried using other existing methods that are exposed (Rollup.runFromApex and others also) but

Handle bulk records for schedule job (1).pdf

Can you look into the PDF provided and suggest some alternative.

jamessimone commented 19 hours ago

@KomalJha01 here's what I would recommend:

That should handle everything for you

KomalJha01 commented 19 hours ago

I agree but in this case, logic will fail here. Suppose, earlier we had 6 Memberships related to the Contact and one created yesterday then after running the Full Recalc CMDT-driven Invocablerollup action. As per the where clause, it will pick only the membership created yesterday and update the field to 1. But as the Total number of memberships is now 7. so, it should update to 7.

jamessimone commented 17 hours ago

@KomalJha01 I see. I think the piece of context that I was missing previously was that you're only trying to process a subset of records and that subset happens to be over the query limits within a synchronous transaction. Let me take a look at this.

KomalJha01 commented 4 hours ago

Thanks @jamessimone please have a look at this. Yes query in parent whose child has been created yesterday and then with the parentRecordId, total number of Memberships we have. I need getRollupMetadataBySObject and getRollup method Public.