You need to sign in to do that
Don't have an account?
Trades_CascadeAccounts: System.LimitException: Too many code statements: 200001
Trades_CascadeAccounts had worked fine until about a week ago when our trade volume increased substantially. Can someone help me figure out why it's hitting governor limits?
public class Trades_CascadeAccounts { public Trades__c[] tradesOldList { set; get; } public Trades__c[] tradesNewList { set; get; } public Map<Id, Trades__c> tradesOldListMap { set; get; } public Trades_CascadeAccounts(Trades__c[] tradesOldList, Trades__c[] tradesNewList) { this.tradesNewList = tradesNewList == null ? new Trades__c[] {} : tradesNewList.clone(); this.tradesOldList = tradesOldList == null ? new Trades__c[] {} : tradesOldList.clone(); this.tradesOldListMap = new Map<Id, Trades__c>(this.tradesOldList); } public void execute() { Set<Id> tradesAccountIds = new Set<Id> {}; for(Trades__c tradesNew : tradesNewList) { Trades__c tradesOld = tradesOldListMap.get(tradesNew.Id); tradesOld = tradesOld == null ? new Trades__c() : tradesOld; tradesAccountIds.add(tradesOld.Resolved_Firm_Trading_ID__c); tradesAccountIds.add(tradesNew.Resolved_Firm_Trading_ID__c); } if (tradesAccountIds.size() == 0) return; Account[] accountList = new Account[] {}; for(Id accountId : tradesAccountIds) { if (accountId == null) continue; Account account = new Account(Id = accountId); account.Rollup_Trades__c = null; accountList.add(account); } update accountList; } }
Also, hear is the batch job if that helps:
global class Account_RollupTradesBatchable implements Database.Batchable<sObject>, Database.Stateful { global Database.QueryLocator start(Database.BatchableContext batchableContext){ return Database.getQueryLocator('select Id from Account where ParentId = null'); } global void execute(Database.BatchableContext batchableContext, Account[] accountList) { for(Account account : accountList) account.Rollup_Trades__c = null; update accountList; } global void finish(Database.BatchableContext batchableContext) { } }
You could do this in a batch, but for now, you can use this code:
If this is all correct (I don't have time to replicate the db model to test right now), this should reduce your script statements to approximately 2% of your current usage. The major killer was the 30 lines of variable assignment, which could have been done in a single line (as outlined above). I also took out the asserts and so on; they should never fail anyways, so they are redundant. I also optimized the if-then structure to take advantage of logic; if a date isn't in this year, then it won't be in this quarter, and a date not in this quarter won't be in this month. I figure this should save you about 30-40 lines of script per contact, and up to approximately 10 scripts per trade. You should be able to handle at least 10,000 trades per contact with this code, if my estimates are correct.
All Answers
I don't see how this code could be the problem; it's succinct. There are a few minor optimizations I could offer, but I don't think it'd do you much good. However, try it and see what you get:
If my maths are correct, this will optimize your code by up to 1,002 script statements per 200 records.
Wow this is great, thanks! I will try it out now.
The new Trades_CascadeAccounts worked fine, but now it's showing Contact_RollupTrades as hitting too many code statements:
You need to use the profiler to figure out where the bottleneck is; we could go through this class and fix it, too, but if that's not the problem, we'll just be going in a circle. Do this:
1) Click on Developer Console.
2) Click on Debug > Change Log Levels.
3) Set Profiling to Finest.
4) Attempt to run your code with the Developer Console open. This will show a new log.
5) Open the log file, and look at the cumulative usage at the bottom.
You'll see something like this:
(Function and class names have been changed to protect the innocent).
You'll see the functions that were executed most frequently, and using this data, you can then tell where you need to optimize. I can help you once we know what class we're supposed to be looking at.
Thanks for the response. This is basically all that is being displayed in the logs for profiling:
I've come to the conclusion that maybe a batch file to handle the roll-up fields calculation may be the best solution?
The problem is in the number of trades.
For instance, for 5 new added trades are maximum 5 related contacts (one for each)
The code:
1. sets the roll-up fields to 0 on all the contacts roll-up fields that should be calculated again.
2. then selects all the trades for these 5 contacts - line 78 (here we can have hundreds or thousands of trades). If the number of trades selected here is too big we receive an error for that block (that's why some trades parse correctly and go to the system and some others don't)
3. and then goes through all those trades to recalculate the roll-up fields on Contact (for year, month, quarter, previous year) the iteration on line 104
I think this last step should be handled with a batch file. How do I write a batch class using this last piece of code (from line 104 till the end) into a batch file and just send the list of trades selected here to the batch, that way the code will handle only max 200 records(trades) at a time?
You could do this in a batch, but for now, you can use this code:
If this is all correct (I don't have time to replicate the db model to test right now), this should reduce your script statements to approximately 2% of your current usage. The major killer was the 30 lines of variable assignment, which could have been done in a single line (as outlined above). I also took out the asserts and so on; they should never fail anyways, so they are redundant. I also optimized the if-then structure to take advantage of logic; if a date isn't in this year, then it won't be in this quarter, and a date not in this quarter won't be in this month. I figure this should save you about 30-40 lines of script per contact, and up to approximately 10 scripts per trade. You should be able to handle at least 10,000 trades per contact with this code, if my estimates are correct.
Wow thanks for taking the time to rewrite the code. I'm not as familiar with SObject (dynamic) methods. In lines 86 and 91 I added ">" as it seemed to be missing and it was throwing an error.
In line 101 it's giving me: Incompatible key type Schema.SObjectField for MAP <Id,Contact>
Is there a way to solve this easily?
This fixed the last problem.
I had to do some minute editing to your code, but it has now saved correctly. Thank you.
What do I need to change in these classes and triggers?
Changed Trigger to:
New Error:
Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger Trades_CascadeContacts caused an unexpected exception, contact your administrator: Trades_CascadeContacts: execution of AfterInsert caused by: System.DmlException: Update failed. First exception on row 0 with id 003J000000SmTU6IAN; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Contact_RollupTrades: execution of BeforeUpdate caused by: System.SObjectException: Contact.YTD_NS_HIT_Sales__c does not belong to SObject type Trades__c Class.Contact_RollupTrades.execute: line 99, column 1 Trigger.Contact_RollupTrades: line 3, column 1: []: Class.Trades_CascadeContacts.execute: line 37, column 1
Try this revision:
Line 75: Method does not exist or incorrect signature: [Integer].intValue()
Does this need to be changed to something like this?
Basically I've been having trouble with that set of code in particular and have been trying to fix it.
Changed line 75 to this:
it saves successfully, and when I post a trade in the Sandbox, it saves it, but the values are not effected. In other words the fields are not updating.
My trigger:
Associated Class:
Associated Trigger:
Here is the following code that worked:
Had to do a little bit of editing on this class:
And change this trigger to 'after update':
Thanks for all your help!
Yeah there's a lot going on in it. It was a good experience learning a bit of dynamic apex as well. Really appreciate the help!
I find it very strange that altering this code would affect another class. Especially a class that doesn't have much to do with trades except an updated Event when it happens. Is there an underlying issue you can think of?
Wrong trigger...sorry
Apologies. The developer I was working with that was running the trades test was running the test in production, not the sandbox, and didn't tell me. Everything it working well now.
I'm revisiting this because this code has worked for the past 2 years, but we've gotten into a situation where we have grown as a firm and added new products. What's happening now is that when an Account gets past 9000 trades, we start to hit some governor limits, specifically CPU Limit error. I'm not sure if you'll get this notification, but if so I'd love if you could help me modify my code again. This is in a batch job, which should allow for 60 seconds, but the debug log is only returning 10 seconds.
One class updates the trades into the system, the next sums the trades into the correlating Account page.
CPU Limit Error Line 94: 25000/10000
Sales Summary Class
Trigger:
Trades Class
Trigger: