function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Shawn Reichner 29Shawn Reichner 29 

How to Do Scheduable and Batchable Apex Class

Hello awesome Devs, 

I have the following scheduled class that has been running fine but all of a sudden I am now getting an Apex Time Out error when this runs each morning.  After doing some research it looks like this class although is being scheduled it is still running syncronously and hittong the goveror limits. How can I update the followign code to be both Schedulable and Batchable to try and get arounf the timing issue?

Thanks for any advise or reworkign of my code that you can help out with,


Shawn

Trigger Code:
 
global class AMPCurrentAmountBatching Implements Schedulable {

    global void execute(SchedulableContext sc){
        AMPCurrentAmountBatching();
    }
    @future
    static public void AMPCurrentAmountBatching(){
        
       List<Opportunity> opps = new List<Opportunity>();
       Set<String> mySet = new Set<String>();
       Integer recordCount = [SELECT Count() FROM Zuora__Subscription__c WHERE OpportunityId__c != null AND LastModifiedDate = LAST_N_DAYS:60];
       Integer sizeBlock = recordCount/2000 + (math.mod(recordCount,2000)!=0?1:0);
        
        For(Integer i=0;i<sizeBlock;i++){
        For(AggregateResult objar : [SELECT OpportunityId__c Oid, SUM(Total_Booking_Amount__c) Amt
                                    FROM Zuora__Subscription__c WHERE OpportunityId__c !=null AND LastModifiedDate = LAST_N_DAYS:60
                                    AND OpportunityId__c NOT IN:mySet GROUP BY OpportunityId__c LIMIT 2000])
        {
        
        Decimal d = (Decimal)objar.get('Amt');
        
            Opportunity Opp = new Opportunity();
            Opp.Id = (Id)objar.get('Oid');
            Opp.Current_Value__c = (Decimal)objar.get('Amt');
            opps.add(Opp); 
            mySet.add(Opp.Id);
        }
        }
        
        If(opps.size()>0){
           update opps;
        }
        
        
    }
    
    
}

 
Ravi Dutt SharmaRavi Dutt Sharma
Hi,

The design looks bad to me. From a schedulable class, you should call a batch class and do the entire processing in the batch class instead  of a future method. 
A for loop inside a for loop is again a bad design, try to avoid this. I am not able to understand  the logic of doing  the same SOQL inside the for loop again and again until the sizeBlock condition is met. If you move this to a batch, you can probably skip this.
Shawn Reichner 29Shawn Reichner 29
Ravi, thanks for the comments sir.  Can you provide some examples on how you would write this class, as I am a beginner and am trying here :)  I made the 2000 batch to attempt to get rid of the apex time out issue if I could batch in smaller chunks.  Can you help sir?
 
Shawn Reichner 29Shawn Reichner 29
Ravi,
Thanks again for your comments, have you had any luck with an example for me to work off of, or a rework to my existing code to help out?  Ohana!