1

This question may asked in many posts and blogs but this became nightmare for me now. Please help me to overcome this issue Issue is

Apex Heap Size Limit Exception while Saving a Record

We have trigger in Asset Object to fire whenever it is updated. Apex class is called inside the trigger. So the logic is below

public override void beforeUpdate() {
    setUpdatedAssetLastValidatedFields();
}

public static void setUpdatedAssetLastValidatedFields() {
    Transient String logicHistory;

    for (Asset assetProcess : (List<Asset>) Trigger.new) {

        Asset oldAsset = (Asset) Trigger.oldMap.get(assetProcess.id);
            logicHistory = assetProcess.assetLastValidatedLogicHistory__c +
                    'Timestamp                                     = ' + System.now() + '\n' +
                    'User ID                                       = ' + UserInfo.getUserId() + '\n' +
                    'User Name                                     = ' + UserInfo.getUserName() + '\n' +
                    'INPUTS:\n' +
                    'old Install_Street1__c                        = ' + oldAsset.Install_Street1__c + '\n' +
                    'old Install_Street2__c                        = ' + oldAsset.Install_Street2__c + '\n' +
                    'old Install_City__c                           = ' + oldAsset.Install_City__c + '\n' +
                    'old Install_State_Province__c                 = ' + oldAsset.Install_State_Province__c + '\n' +
                    'old Install_Zip_Code__c                       = ' + oldAsset.Install_Zip_Code__c + '\n' +
                    'old Install_Country__c                        = ' + oldAsset.Install_Country__c + '\n' +
                    'new Install_Street1__c                        = ' + assetProcess.Install_Street1__c + '\n' +
                    'new Install_Street2__c                        = ' + assetProcess.Install_Street2__c + '\n' +
                    'new Install_City__c                           = ' + assetProcess.Install_City__c + '\n' +
                    'new Install_State_Province__c                 = ' + assetProcess.Install_State_Province__c + '\n' +
                    'new Install_Zip_Code__c                       = ' + assetProcess.Install_Zip_Code__c + '\n' +
                    'new Install_Country__c                        = ' + assetProcess.Install_Country__c + '\n' +
                    'LOGIC DECISIONS:\n';

        assetProcess.assetLastValidatedLogicHistory__c = logicHistory.right(131072);
}

So the problem is, when I have above 50 records to update, then the string 'logicHistory' is keep building the heap size. So is there any workaround to overcome this?.

I am already using Transient keyword in the string variable but it is not reducing the size.

  • 1
    try to directly assign the value to this field assetProcess.assetLastValidatedLogicHistory__c second option is declare the string inside for loop. – Tushar Sharma Oct 24 '16 at 9:30
  • @TusharSharma - I tried these both the ways but problem continues. I tried declaring the variable inside loop and as well as direct assignment. – Prince Oct 24 '16 at 9:38
  • How long is that string in average/max case? Is that only logic in trigger? – kurunve Oct 24 '16 at 9:43
  • @kurunve - There are logics inside the trigger. This is one of the before update method in the trigger. Before this method current heap size is just 1090 but after this method it is reaching 10345982. Which is exceeding the 6MB of heap size – Prince Oct 24 '16 at 9:49
  • @Prince sorry, missed that part where you're always appending log string into previous value. in that case, answer below is only possible one I think. Probably, you can make few queueable jobs with few records in each and string which needs to be appended as parameter to that job. That can save you some heap size. – kurunve Oct 24 '16 at 9:54
1

You can change the approach for creating logs.

Instead of actions performed in setUpdatedAssetLastValidatedFields you can put the pair (via DML): assetProcess, oldProcess along with userId, timestamp to new object AssetLastValidatedLogicHistory__c and build the result string afterwards (separately for each record or chunk of records via async/batch process).

  • By your answer, I can understand that you are saying to move the things to Batch Class instead of normal class. No other possible ways?. – Prince Oct 24 '16 at 9:03
  • Batch or queueable apex... you just cannot process this amount of data in single transaction. The great solution could be formula field (to build the log string) but they also have limits (length). – Marcin Sz. Oct 24 '16 at 9:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.