From 63ed889598cbf301486019345d8a97a7d1329aa9 Mon Sep 17 00:00:00 2001
From: James Simone <16430727+jamessimone@users.noreply.github.com>
Date: Mon, 4 Nov 2024 23:31:01 -0500
Subject: [PATCH] v1.7.0 - Improve Memory Management for LDV Full
Recalculations (#636)
* Actual fixes for #615 - this time with 100% better memory management! This involves a cutover to Database.Cursor as well as a DataWeave script
* Fixes #638 by addressing a classic DST issue in RollupDateLiteral. Slight cleanup of RollupFinalizer and RollupParentResetProcessor
---
README.md | 11 +-
extra-tests/classes/InvocableDrivenTests.cls | 2 +-
.../classes/RollupCalcItemSorterTests.cls | 2 +-
extra-tests/classes/RollupCalculatorTests.cls | 64 ++-
.../classes/RollupCurrencyInfoTests.cls | 2 +-
extra-tests/classes/RollupEvaluatorTests.cls | 2 +-
extra-tests/classes/RollupFinalizerTests.cls | 26 +-
.../classes/RollupFlowFullRecalcTests.cls | 4 +-
extra-tests/classes/RollupFullRecalcTests.cls | 117 +++---
.../classes/RollupIntegrationTests.cls | 75 ++--
.../classes/RollupQueryBuilderTests.cls | 8 +-
extra-tests/classes/RollupStateTests.cls | 370 +++++++++++++++++
.../classes/RollupStateTests.cls-meta.xml | 5 +
extra-tests/classes/RollupTestUtils.cls | 12 +-
extra-tests/classes/RollupTests.cls | 15 +-
.../ApexRollupTestSuite.testSuite-meta.xml | 1 +
package.json | 2 +-
plugins/ExtraCodeCoverage/README.md | 4 +-
plugins/RollupCallback/README.md | 2 +-
rollup-namespaced/README.md | 4 +-
rollup-namespaced/sfdx-project.json | 18 +-
rollup/app/applications/Rollup.app-meta.xml | 1 +
.../See_Rollup_App.permissionset-meta.xml | 80 +++-
rollup/app/tabs/RollupState__c.tab-meta.xml | 5 +
rollup/core/classes/Rollup.cls | 48 ++-
rollup/core/classes/RollupAsyncProcessor.cls | 181 ++++----
.../core/classes/RollupCalcItemReplacer.cls | 4 +-
rollup/core/classes/RollupCalculator.cls | 102 ++---
rollup/core/classes/RollupCurrencyInfo.cls | 6 +-
rollup/core/classes/RollupDateLiteral.cls | 4 +-
rollup/core/classes/RollupFinalizer.cls | 68 ++-
.../core/classes/RollupFlowBulkProcessor.cls | 2 +-
.../classes/RollupFullBatchRecalculator.cls | 41 +-
.../classes/RollupFullRecalcProcessor.cls | 60 ++-
rollup/core/classes/RollupLogger.cls | 2 +-
.../classes/RollupParentResetProcessor.cls | 61 ++-
.../classes/RollupRelationshipFieldFinder.cls | 16 +-
rollup/core/classes/RollupRepository.cls | 5 +
rollup/core/classes/RollupSObjectUpdater.cls | 53 ++-
rollup/core/classes/RollupState.cls | 392 ++++++++++++++++--
rollup/core/dw/jsonToRollupState.dwl | 19 +
rollup/core/dw/jsonToRollupState.dwl-meta.xml | 7 +
.../Rollup_State.flexipage-meta.xml | 263 ++++++++++++
.../RollupState__c.object-meta.xml | 61 +++
.../fields/Body0__c.field-meta.xml | 11 +
.../fields/RelatedJobId__c.field-meta.xml | 13 +
.../RelatedRecordKeys0__c.field-meta.xml | 13 +
.../RelatedRecordKeys10__c.field-meta.xml | 13 +
.../RelatedRecordKeys1__c.field-meta.xml | 13 +
.../RelatedRecordKeys2__c.field-meta.xml | 13 +
.../RelatedRecordKeys3__c.field-meta.xml | 13 +
.../RelatedRecordKeys4__c.field-meta.xml | 13 +
.../RelatedRecordKeys5__c.field-meta.xml | 13 +
.../RelatedRecordKeys6__c.field-meta.xml | 13 +
.../RelatedRecordKeys7__c.field-meta.xml | 13 +
.../RelatedRecordKeys8__c.field-meta.xml | 13 +
.../RelatedRecordKeys9__c.field-meta.xml | 13 +
.../listViews/All.listView-meta.xml | 21 +
.../MyRollupStates.listView-meta.xml | 21 +
rollup/core/profiles/Admin.profile-meta.xml | 74 ++++
scripts/convert-dlrs-rules-namespaced.apex | 38 +-
scripts/convert-dlrs-rules.apex | 32 +-
...ivate-converted-dlrs-rules-namespaced.apex | 4 +-
scripts/deactivate-converted-dlrs-rules.apex | 4 +-
sfdx-project.json | 15 +-
65 files changed, 2102 insertions(+), 501 deletions(-)
create mode 100644 extra-tests/classes/RollupStateTests.cls
create mode 100644 extra-tests/classes/RollupStateTests.cls-meta.xml
create mode 100644 rollup/app/tabs/RollupState__c.tab-meta.xml
create mode 100644 rollup/core/dw/jsonToRollupState.dwl
create mode 100644 rollup/core/dw/jsonToRollupState.dwl-meta.xml
create mode 100644 rollup/core/flexipages/Rollup_State.flexipage-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/RollupState__c.object-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/Body0__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedJobId__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys0__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys10__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys1__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys2__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys3__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys4__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys5__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys6__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys7__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys8__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/fields/RelatedRecordKeys9__c.field-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/listViews/All.listView-meta.xml
create mode 100644 rollup/core/objects/RollupState__c/listViews/MyRollupStates.listView-meta.xml
diff --git a/README.md b/README.md
index 93e2b511..97e2bf6e 100644
--- a/README.md
+++ b/README.md
@@ -24,16 +24,13 @@ As well, don't miss [the Wiki](../../wiki), which includes even more info for co
## Deployment & Setup
-
-
+
+
-
-
+
+
-
diff --git a/extra-tests/classes/InvocableDrivenTests.cls b/extra-tests/classes/InvocableDrivenTests.cls
index 4ac4cdfb..bf5dd279 100644
--- a/extra-tests/classes/InvocableDrivenTests.cls
+++ b/extra-tests/classes/InvocableDrivenTests.cls
@@ -42,7 +42,7 @@ private class InvocableDrivenTests {
@IsTest
static void shouldWorkWhenBatchedFromRefresh() {
- Rollup.defaultControl = new RollupControl__mdt(MaxLookupRowsBeforeBatching__c = 1, IsRollupLoggingEnabled__c = true);
+ Rollup.defaultControl = new RollupControl__mdt(MaxLookupRowsBeforeBatching__c = 1);
// Driven by extra-tests/flows/Rollup_Integration_Multiple_Deferred_Case_Rollups.flow-meta.xml
Account acc = [SELECT Id FROM Account];
// Description and Subject both are referenced in the Flow
diff --git a/extra-tests/classes/RollupCalcItemSorterTests.cls b/extra-tests/classes/RollupCalcItemSorterTests.cls
index 44037d26..16daab5f 100644
--- a/extra-tests/classes/RollupCalcItemSorterTests.cls
+++ b/extra-tests/classes/RollupCalcItemSorterTests.cls
@@ -162,7 +162,7 @@ private class RollupCalcItemSorterTests {
new Opportunity(StageName = 'One')
};
- itemsToSort.sort(new RollupCalcItemSorter(new List{ Opportunity.Name.getDescribe().getName(), Opportunity.StageName.getDescribe().getName() }));
+ itemsToSort.sort(new RollupCalcItemSorter(new List{ Opportunity.Name.toString(), Opportunity.StageName.toString() }));
System.assertEquals(null, itemsToSort.get(0).StageName);
System.assertEquals('One', itemsToSort.get(1).StageName);
diff --git a/extra-tests/classes/RollupCalculatorTests.cls b/extra-tests/classes/RollupCalculatorTests.cls
index 3a6f526e..943d4b7f 100644
--- a/extra-tests/classes/RollupCalculatorTests.cls
+++ b/extra-tests/classes/RollupCalculatorTests.cls
@@ -245,9 +245,8 @@ private class RollupCalculatorTests {
Rollup__mdt metadata = configureOrderByMetadata(new Rollup__mdt(), 'Name');
RollupCalculator calc = getCalculator(0, Rollup.Op.FIRST, Opportunity.Amount, Account.AnnualRevenue, metadata, lookupKey, Account.Id);
RollupState outerState = new RollupState();
- RollupState.SObjectInfo info = new RollupState.SObjectInfo();
+ RollupState.SObjectInfo info = (RollupState.SObjectInfo) outerState.getState(lookupKey, metadata, RollupState.SObjectInfo.class);
info.setItem(new Opportunity(Name = 'a', Amount = 3));
- outerState.setState(lookupKey, info);
calc.setState(outerState);
calc.performRollup(
@@ -724,17 +723,17 @@ private class RollupCalculatorTests {
static void mostRespectsStateValues() {
Account acc = [SELECT Id FROM Account];
Integer priorVal = 50;
- RollupState.MostInfo info = new RollupState.MostInfo();
- info.setLargestPointCounter(2);
RollupState outerState = new RollupState();
- outerState.setState(acc.Id, info);
+ Rollup__mdt metaKey = new Rollup__mdt();
+ RollupState.MostInfo info = (RollupState.MostInfo) outerState.getState(acc.Id, metaKey, RollupState.MostInfo.class);
+ info.setValues(2, priorVal);
RollupCalculator calc = getCalculator(
priorVal,
Rollup.Op.MOST,
ContactPointAddress.PreferenceRank,
Account.AnnualRevenue,
- new Rollup__mdt(),
+ metaKey,
acc.Id,
ContactPointAddress.ParentId
);
@@ -886,6 +885,49 @@ private class RollupCalculatorTests {
System.assertEquals(null, calc.getReturnValue());
}
+ @IsTest
+ static void correctlyAppliesStatefulSums() {
+ Rollup__mdt metaKey = new Rollup__mdt();
+ String accountKey = '0011g00003VDGbF002';
+ Integer value = 1;
+ RollupCalculator calc = getCalculator(null, Rollup.Op.SUM, Opportunity.Amount, Account.AnnualRevenue, metaKey, accountKey, Opportunity.AccountId);
+ RollupState outerState = new RollupState();
+ RollupState.GenericInfo info = (RollupState.GenericInfo) outerState.getState(accountKey, metaKey, RollupState.GenericInfo.class);
+ info.value = value;
+ calc.setState(outerState);
+
+ Opportunity one = new Opportunity(Id = '0066g00003VDGbF001', Amount = 5, AccountId = accountKey);
+ Opportunity two = new Opportunity(Id = '0066g00003VDGbF002', Amount = 5, AccountId = accountKey);
+
+ calc.performRollup(new List{ one, two }, new Map());
+
+ System.assertEquals(one.Amount + two.Amount + value, calc.getReturnValue());
+ System.assertEquals(one.Amount + two.Amount + value, info.value);
+ }
+
+ @IsTest
+ static void doesNotResetParentValueWhenOnlyStatefulSumMatches() {
+ Rollup__mdt metaKey = new Rollup__mdt();
+ String accountKey = '0011g00003VDGbF002';
+ Integer value = 1;
+ RollupCalculator calc = getCalculator(null, Rollup.Op.SUM, Opportunity.Amount, Account.AnnualRevenue, metaKey, accountKey, Opportunity.AccountId);
+ RollupState outerState = new RollupState();
+ RollupState.GenericInfo info = (RollupState.GenericInfo) outerState.getState(accountKey, metaKey, RollupState.GenericInfo.class);
+ info.value = value;
+
+ calc.setState(outerState);
+ calc.setFullRecalc(true);
+ calc.setEvaluator(new RollupEvaluator.WhereFieldEvaluator('Amount = 0', Opportunity.SObjectType));
+
+ Opportunity one = new Opportunity(Id = '0066g00003VDGbF001', Amount = 5, AccountId = accountKey);
+ Opportunity two = new Opportunity(Id = '0066g00003VDGbF002', Amount = 5, AccountId = accountKey);
+
+ calc.performRollup(new List{ one, two }, new Map());
+
+ System.assertEquals(value, calc.getReturnValue());
+ System.assertEquals(value, info.value);
+ }
+
// CONCAT tests
@IsTest
@@ -2177,8 +2219,10 @@ private class RollupCalculatorTests {
@IsTest
static void averageFactorsInBatchState() {
+ Rollup__mdt meta = new Rollup__mdt();
String lookupKey = RollupTestUtils.createId(Account.SObjectType);
- RollupState.AverageInfo state = new RollupState.AverageInfo();
+ RollupState outerState = new RollupState();
+ RollupState.AverageInfo state = (RollupState.AverageInfo) outerState.getState(lookupKey, meta, RollupState.AverageInfo.class);
state.denominator = 15;
state.numerator = 75;
RollupCalculator calc = getCalculator(
@@ -2186,14 +2230,12 @@ private class RollupCalculatorTests {
Rollup.Op.AVERAGE,
Opportunity.Amount,
Account.Description,
- new Rollup__mdt(),
+ meta,
lookupKey,
Account.Id
);
-
- RollupState outerState = new RollupState();
- outerState.setState(lookupKey, state);
calc.setState(outerState);
+
calc.performRollup(
new List{
new Opportunity(Amount = 15),
diff --git a/extra-tests/classes/RollupCurrencyInfoTests.cls b/extra-tests/classes/RollupCurrencyInfoTests.cls
index d6256a94..4c55a072 100644
--- a/extra-tests/classes/RollupCurrencyInfoTests.cls
+++ b/extra-tests/classes/RollupCurrencyInfoTests.cls
@@ -206,7 +206,7 @@ private class RollupCurrencyInfoTests {
);
List olis = new List{ oliToUpdate };
- RollupCurrencyInfo.overrideDatedMultiCurrency(olis.getSObjectType().getDescribe().getName(), new List{ 'Opportunity', 'CloseDate' });
+ RollupCurrencyInfo.overrideDatedMultiCurrency(olis.getSObjectType().toString(), new List{ 'Opportunity', 'CloseDate' });
RollupCurrencyInfo.transform(olis, OpportunityLineItem.TotalPrice, eurPeriodOne.IsoCode, new List());
OpportunityLineItem oli = (OpportunityLineItem) RollupCurrencyInfo.getCalcItem(oliToUpdate, eurPeriodOne.IsoCode);
diff --git a/extra-tests/classes/RollupEvaluatorTests.cls b/extra-tests/classes/RollupEvaluatorTests.cls
index 18516c0c..98f502f8 100644
--- a/extra-tests/classes/RollupEvaluatorTests.cls
+++ b/extra-tests/classes/RollupEvaluatorTests.cls
@@ -1129,7 +1129,7 @@ private class RollupEvaluatorTests {
@IsTest
static void pascalCaseForFieldNamesIsNotRequired() {
- String poorlyCasedFieldName = Opportunity.IsClosed.getDescribe().getName().toLowerCase();
+ String poorlyCasedFieldName = Opportunity.IsClosed.toString().toLowerCase();
Opportunity isClosedFalse = (Opportunity) JSON.deserialize('{ "IsClosed": false }', Opportunity.class);
OpportunityLineItem target = new OpportunityLineItem(Opportunity = isClosedFalse);
diff --git a/extra-tests/classes/RollupFinalizerTests.cls b/extra-tests/classes/RollupFinalizerTests.cls
index 8de43d52..3ed813d4 100644
--- a/extra-tests/classes/RollupFinalizerTests.cls
+++ b/extra-tests/classes/RollupFinalizerTests.cls
@@ -1,19 +1,31 @@
@IsTest
private class RollupFinalizerTests {
- @TestSetup
- static void setup() {
- upsert new RollupSettings__c(IsEnabled__c = true);
- insert new Account(Name = RollupFinalizerTests.class.getName());
+ public class ExampleFinalizerContext implements System.FinalizerContext {
+ public Id getAsyncApexJobId() {
+ return RollupTestUtils.createId(AsyncApexJob.SObjectType);
+ }
+
+ public String getRequestId() {
+ return System.Request.getCurrent().getRequestId();
+ }
+
+ public ParentJobResult getResult() {
+ return ParentJobResult.UNHANDLED_EXCEPTION;
+ }
+
+ public Exception getException() {
+ return new DmlException();
+ }
}
@IsTest
static void shouldGracefullyLogUnhandledException() {
- RollupFinalizer.testResult = ParentJobResult.UNHANDLED_EXCEPTION;
+ System.FinalizerContext fc = new ExampleFinalizerContext();
Test.startTest();
- new RollupFinalizer().execute(null);
+ new RollupFinalizer().execute(fc);
Test.stopTest();
- System.assertEquals(true, RollupFinalizer.wasCalled);
+ System.assertEquals(true, RollupFinalizer.wasExceptionLogged);
}
}
diff --git a/extra-tests/classes/RollupFlowFullRecalcTests.cls b/extra-tests/classes/RollupFlowFullRecalcTests.cls
index 2e9e80fd..a8498024 100644
--- a/extra-tests/classes/RollupFlowFullRecalcTests.cls
+++ b/extra-tests/classes/RollupFlowFullRecalcTests.cls
@@ -28,8 +28,8 @@ private class RollupFlowFullRecalcTests {
List flowInputs = RollupTestUtils.prepareFlowTest(apps, 'REFRESH', 'SUM');
flowInputs[0].ultimateParentLookup = 'ParentId';
flowInputs[0].rollupToUltimateParent = true;
- flowInputs[0].lookupFieldOnCalcItem = Application__c.ParentApplication__c.getDescribe().getName();
- flowInputs[0].rollupFieldOnCalcItem = Application__c.Engagement_Score__c.getDescribe().getName();
+ flowInputs[0].lookupFieldOnCalcItem = Application__c.ParentApplication__c.toString();
+ flowInputs[0].rollupFieldOnCalcItem = Application__c.Engagement_Score__c.toString();
flowInputs[0].grandparentRelationshipFieldPath = RollupTestUtils.getRelationshipPath(
new List{ Application__c.ParentApplication__c, ParentApplication__c.Account__c, Account.AnnualRevenue }
);
diff --git a/extra-tests/classes/RollupFullRecalcTests.cls b/extra-tests/classes/RollupFullRecalcTests.cls
index e2a5e655..356d2e66 100644
--- a/extra-tests/classes/RollupFullRecalcTests.cls
+++ b/extra-tests/classes/RollupFullRecalcTests.cls
@@ -10,11 +10,7 @@ private class RollupFullRecalcTests {
@IsTest
static void correctlyOrdersGrandparentRollupQueryString() {
- Rollup.defaultControl = new RollupControl__mdt(
- IsRollupLoggingEnabled__c = true,
- MaxLookupRowsBeforeBatching__c = 0,
- ShouldRunAs__c = RollupMetaPicklists.ShouldRunAs.Batchable
- );
+ Rollup.defaultControl = new RollupControl__mdt(IsRollupLoggingEnabled__c = true, MaxLookupRowsBeforeBatching__c = 0);
insert new Contact(LastName = 'grandparent rollup query string');
Rollup.performBulkFullRecalc(
@@ -35,7 +31,7 @@ private class RollupFullRecalcTests {
System.assertEquals(1, Rollup.CACHED_FULL_RECALCS.size());
List queryParts = Rollup.CACHED_FULL_RECALCS.get(0).start(null).getQuery().split('\n');
- System.assertEquals('ORDER BY ReportsTo.Account.Id,ReportsToId', queryParts.get(queryParts.size() - 1));
+ System.assertEquals('ORDER BY ReportsTo.Account.Id,ReportsToId,Id', queryParts.get(queryParts.size() - 1));
}
@IsTest
@@ -128,14 +124,14 @@ private class RollupFullRecalcTests {
List metadata = new List{
new Rollup__mdt(
- CalcItem__c = Application__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName(),
+ CalcItem__c = Application__c.SObjectType.toString(),
LookupObject__c = 'Account',
RollupToUltimateParent__c = true,
- LookupFieldOnCalcItem__c = Application__c.ParentApplication__c.getDescribe().getName(),
+ LookupFieldOnCalcItem__c = Application__c.ParentApplication__c.toString(),
UltimateParentLookup__c = 'ParentId',
RollupOperation__c = 'SUM',
RollupFieldOnLookupObject__c = 'AnnualRevenue',
- RollupFieldOnCalcItem__c = Application__c.Engagement_Score__c.getDescribe().getName(),
+ RollupFieldOnCalcItem__c = Application__c.Engagement_Score__c.toString(),
LookupFieldOnLookupObject__c = 'Id',
GrandparentRelationshipFieldPath__c = RollupTestUtils.getRelationshipPath(
new List{ Application__c.ParentApplication__c, ParentApplication__c.Account__c, Account.AnnualRevenue }
@@ -172,12 +168,12 @@ private class RollupFullRecalcTests {
List metadata = new List{
new Rollup__mdt(
- CalcItem__c = Application__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName(),
+ CalcItem__c = Application__c.SObjectType.toString(),
LookupObject__c = 'Individual',
- LookupFieldOnCalcItem__c = Application__c.ParentApplication__c.getDescribe().getName(),
+ LookupFieldOnCalcItem__c = Application__c.ParentApplication__c.toString(),
RollupOperation__c = 'SUM',
RollupFieldOnLookupObject__c = 'ConsumerCreditScore',
- RollupFieldOnCalcItem__c = Application__c.Engagement_Score__c.getDescribe().getName(),
+ RollupFieldOnCalcItem__c = Application__c.Engagement_Score__c.toString(),
LookupFieldOnLookupObject__c = 'Id',
GrandparentRelationshipFieldPath__c = String.valueOf(Application__c.ParentApplication__c).replace('__r', '__c') +
'.' +
@@ -915,8 +911,11 @@ private class RollupFullRecalcTests {
insert cpas;
Rollup.defaultControl = new RollupControl__mdt(
+ // prove that it works with multiple chunks
+ BatchChunkSize__c = 2,
MaxLookupRowsBeforeBatching__c = 1,
- ShouldRunAs__c = RollupMetaPicklists.ShouldRunAs.Queueable, // validate that it still batches
+ // validate that it still batches
+ ShouldRunAs__c = RollupMetaPicklists.ShouldRunAs.Queueable,
IsRollupLoggingEnabled__c = true
);
@@ -937,7 +936,16 @@ private class RollupFullRecalcTests {
acc = [SELECT AnnualRevenue FROM Account];
System.assertEquals(6, acc.AnnualRevenue);
- System.assertEquals('Completed', [SELECT Status FROM AsyncApexJob WHERE JobType = 'BatchApexWorker'].Status);
+ System.assertEquals(
+ 'Completed',
+ [
+ SELECT Status
+ FROM AsyncApexJob
+ WHERE JobType = 'Queueable' AND ApexClass.Name = :getNamespaceSafeClassName(RollupFullBatchRecalculator.class)
+ LIMIT 1
+ ]
+ ?.Status
+ );
}
@IsTest
@@ -959,7 +967,8 @@ private class RollupFullRecalcTests {
Rollup.defaultControl = new RollupControl__mdt(
MaxLookupRowsBeforeBatching__c = 1,
- ShouldRunAs__c = RollupMetaPicklists.ShouldRunAs.Queueable, // validate that it still batches
+ // validate that it still batches
+ ShouldRunAs__c = RollupMetaPicklists.ShouldRunAs.Queueable,
IsRollupLoggingEnabled__c = true
);
Rollup.specificControl = new RollupControl__mdt(BatchChunkSize__c = 1);
@@ -979,11 +988,14 @@ private class RollupFullRecalcTests {
Rollup.performFullRecalculation(meta);
Test.stopTest();
- List jobs = [SELECT Status, JobItemsProcessed FROM AsyncApexJob WHERE JobType = 'BatchApexWorker'];
+ List jobs = [
+ SELECT Status
+ FROM AsyncApexJob
+ WHERE JobType = 'Queueable' AND ApexClass.Name = :getNamespaceSafeClassName(RollupFullBatchRecalculator.class)
+ ];
System.assertEquals(false, jobs.isEmpty());
for (AsyncApexJob job : jobs) {
System.assertEquals('Completed', job.Status);
- System.assertEquals(1, job.JobItemsProcessed);
}
}
@@ -1195,12 +1207,12 @@ private class RollupFullRecalcTests {
List metas = new List{
new Rollup__mdt(
- CalcItem__c = RollupChild__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName(),
- RollupFieldOnCalcItem__c = RollupChild__c.NumberField__c.getDescribe().getName(),
- LookupFieldOnCalcItem__c = RollupChild__c.RollupParent__c.getDescribe().getName(),
- LookupObject__c = RollupGrandparent__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName(),
- LookupFieldOnLookupObject__c = RollupGrandparent__c.Id.getDescribe().getName(),
- RollupFieldOnLookupObject__c = RollupGrandparent__c.AmountFromChildren__c.getDescribe().getName(),
+ CalcItem__c = RollupChild__c.SObjectType.toString(),
+ RollupFieldOnCalcItem__c = RollupChild__c.NumberField__c.toString(),
+ LookupFieldOnCalcItem__c = RollupChild__c.RollupParent__c.toString(),
+ LookupObject__c = RollupGrandparent__c.SObjectType.toString(),
+ LookupFieldOnLookupObject__c = RollupGrandparent__c.Id.toString(),
+ RollupFieldOnLookupObject__c = RollupGrandparent__c.AmountFromChildren__c.toString(),
RollupOperation__c = 'SUM',
CalcItemWhereClause__c = ' ||| ' +
RollupTestUtils.getRelationshipPath(
@@ -1223,7 +1235,8 @@ private class RollupFullRecalcTests {
@IsTest
static void shouldNotBlowUpOnMassiveQuery() {
- String endOfWhereClause = '2'.repeat(100001);
+ Integer maxLength = ContactPointAddress.PreferenceRank.getDescribe().getDigits();
+ String endOfWhereClause = '2'.repeat(maxLength);
Rollup__mdt meta = new Rollup__mdt(
CalcItem__c = 'ContactPointAddress',
RollupFieldOnCalcItem__c = 'PreferenceRank',
@@ -1232,7 +1245,7 @@ private class RollupFullRecalcTests {
RollupFieldOnLookupObject__c = 'AnnualRevenue',
LookupObject__c = 'Account',
RollupOperation__c = 'SUM',
- CalcItemWhereClause__c = 'PreferenceRank = ' + endOfWhereClause
+ CalcItemWhereClause__c = ('PreferenceRank = ' + endOfWhereClause + ' AND ').repeat(200).removeEnd(' AND ')
);
Test.startTest();
@@ -1490,7 +1503,7 @@ private class RollupFullRecalcTests {
}
@IsTest
- static void shouldResetParentValuesWithoutMatchingChildrenFromBulkRouteUnderQueryLimit() {
+ static void shouldResetParentValuesWithoutMatchingChildrenFromBulkRouteUnderQueryLimitSync() {
Account acc = [SELECT Id FROM Account];
acc.AccountNumber = 'someString';
acc.AnnualRevenue = 5;
@@ -1522,9 +1535,7 @@ private class RollupFullRecalcTests {
)
};
- Test.startTest();
Rollup.performBulkFullRecalc(metas, Rollup.InvocationPoint.FROM_FULL_RECALC_LWC.name());
- Test.stopTest();
List accounts = [SELECT AccountNumber, AnnualRevenue, Name FROM Account];
for (Account updatedAcc : accounts) {
@@ -1605,12 +1616,21 @@ private class RollupFullRecalcTests {
System.assertEquals(null, updatedAcc.AnnualRevenue, 'AnnualRevenue should have been reset: ' + updatedAcc);
System.assertEquals(null, updatedAcc.AccountNumber, 'AccountNumber should have been reset: ' + updatedAcc);
}
+ System.assertEquals(
+ 'Completed',
+ [
+ SELECT Status
+ FROM AsyncApexJob
+ WHERE JobType = 'Queueable' AND ApexClass.Name = :getNamespaceSafeClassName(RollupParentResetProcessor.class)
+ LIMIT 1
+ ]
+ ?.Status
+ );
}
@IsTest
static void shouldResetParentValuesWithoutMatchingChildrenFromBulkRouteOverLimitWithBatching() {
RollupParentResetProcessor.maxQueryRows = 0;
- Rollup.defaultControl = new RollupControl__mdt(ShouldRunAs__c = RollupMetaPicklists.ShouldRunAs.Batchable, IsRollupLoggingEnabled__c = true);
Account acc = [SELECT Id FROM Account];
acc.AccountNumber = 'someString';
acc.AnnualRevenue = 5;
@@ -1646,12 +1666,9 @@ private class RollupFullRecalcTests {
Rollup.performBulkFullRecalc(metas, Rollup.InvocationPoint.FROM_FULL_RECALC_LWC.name());
Test.stopTest();
- List accounts = [SELECT AnnualRevenue, Name FROM Account];
+ List accounts = [SELECT AnnualRevenue, Name, AccountNumber FROM Account];
for (Account updatedAcc : accounts) {
- // for this set of tests, since we can't add more than one queueable job to the stack in a test context
- // and because each full reset is processed separately, we can only validate that the first Rollup__mdt record
- // had the parents associated with it reset. It's possible that this will be revisited in the future to consolidate full
- // resets into singular jobs
+ System.assertEquals(null, updatedAcc.AccountNumber, 'AccountNumber should have been reset: ' + updatedAcc);
System.assertEquals(null, updatedAcc.AnnualRevenue, 'AnnualRevenue should have been reset: ' + updatedAcc);
}
}
@@ -1925,7 +1942,6 @@ private class RollupFullRecalcTests {
@IsTest
static void shouldFullRecalcWithInWhereClauses() {
RollupParentResetProcessor.maxQueryRows = 0;
- Rollup.defaultControl = new RollupControl__mdt(ShouldRunAs__c = RollupMetaPicklists.ShouldRunAs.Batchable);
Account acc = [SELECT Id FROM Account];
insert new List{
@@ -2349,15 +2365,10 @@ private class RollupFullRecalcTests {
);
Test.stopTest();
- Assert.areEqual(
- 1,
- [SELECT COUNT() FROM AsyncApexJob WHERE JobType = 'Queueable' AND ApexClass.Name = :getNamespaceSafeClassName(RollupAsyncProcessor.class)],
- 'Conductor should begin async as queueable'
- );
Assert.areEqual(
2,
- [SELECT COUNT() FROM AsyncApexJob WHERE JobType = 'BatchApexWorker' AND ApexClass.Name = :getNamespaceSafeClassName(RollupFullBatchRecalculator.class)],
- 'Only two batch classes should have run'
+ [SELECT COUNT() FROM AsyncApexJob WHERE JobType = 'Queueable' AND ApexClass.Name = :getNamespaceSafeClassName(RollupFullBatchRecalculator.class)],
+ 'Exactly two batch full recalcs should have run'
);
parentOne = [SELECT AnnualRevenue, Description, NumberOfEmployees FROM Account WHERE Id = :parentOne.Id];
Assert.areEqual(childOne.PreferenceRank, parentOne.AnnualRevenue);
@@ -2367,6 +2378,7 @@ private class RollupFullRecalcTests {
Assert.areEqual(null, parentTwo.AnnualRevenue);
Assert.areEqual('Concat, Two', parentTwo.Description);
Assert.areEqual(10, parentTwo.NumberOfEmployees);
+ Assert.areEqual(0, [SELECT COUNT() FROM RollupState__c], '' + [SELECT COUNT(Id), RelatedJobId__c FROM RollupState__c GROUP BY RelatedJobId__c]);
}
@IsTest
@@ -2434,8 +2446,8 @@ private class RollupFullRecalcTests {
Assert.areEqual(
2,
- [SELECT COUNT() FROM AsyncApexJob WHERE JobType = 'BatchApexWorker' AND ApexClass.Name = :getNamespaceSafeClassName(RollupFullBatchRecalculator.class)],
- 'Only two batch classes should have run'
+ [SELECT COUNT() FROM AsyncApexJob WHERE JobType = 'Queueable' AND ApexClass.Name = :getNamespaceSafeClassName(RollupFullBatchRecalculator.class)],
+ 'Exactly two batch full recalcs should have run'
);
parentOne = [SELECT AnnualRevenue, Description, NumberOfEmployees FROM Account WHERE Id = :parentOne.Id];
Assert.areEqual(childOne.PreferenceRank, parentOne.AnnualRevenue);
@@ -2445,6 +2457,7 @@ private class RollupFullRecalcTests {
Assert.areEqual(null, parentTwo.AnnualRevenue);
Assert.areEqual('Concat, Two', parentTwo.Description);
Assert.areEqual(10, parentTwo.NumberOfEmployees);
+ Assert.areEqual(0, [SELECT COUNT() FROM RollupState__c]);
}
@IsTest
@@ -2452,9 +2465,14 @@ private class RollupFullRecalcTests {
// an interesting one because it's again an implementation detail - this time,
// of the batch "caboose" process. if the full recalc is BELOW the batch limit,
// the queueable will already correctly handle everything since the shared parent field will only be reset once.
- // batch processes, on the other hand, would otherwise simply see the existing value on the parent as something
+ // batch queueables, on the other hand, would otherwise simply see the existing value on the parent as something
// that needs to be cleared out
- Rollup.defaultControl = new RollupControl__mdt(MaxRollupRetries__c = 100, MaxLookupRowsBeforeBatching__c = 1, IsRollupLoggingEnabled__c = true);
+ Rollup.defaultControl = new RollupControl__mdt(
+ MaxRollupRetries__c = 100,
+ MaxLookupRowsBeforeBatching__c = 1,
+ IsRollupLoggingEnabled__c = true,
+ BatchChunkSize__c = 3
+ );
Rollup.onlyUseMockMetadata = true;
Account parent = [SELECT Id FROM Account];
@@ -2501,12 +2519,13 @@ private class RollupFullRecalcTests {
Assert.areEqual(
2,
- [SELECT COUNT() FROM AsyncApexJob WHERE JobType = 'BatchApexWorker' AND ApexClass.Name = :getNamespaceSafeClassName(RollupFullBatchRecalculator.class)],
- 'Test requires batch apex to have been the full recalc mechanism'
+ [SELECT COUNT() FROM AsyncApexJob WHERE JobType = 'Queueable' AND ApexClass.Name = :getNamespaceSafeClassName(RollupFullBatchRecalculator.class)],
+ 'Test requires RollupFullBatchRecalculator to have been used'
);
parent = [SELECT AnnualRevenue, NumberOfEmployees FROM Account WHERE Id = :parent.Id];
Assert.areEqual(40, parent.AnnualRevenue, 'Both children types should have correctly summed to one field in batch recalc');
Assert.areEqual(25, parent.NumberOfEmployees, 'Additional field on parent should have been queried successfully in second rollup');
+ Assert.areEqual(0, [SELECT COUNT() FROM RollupState__c]);
}
@IsTest
@@ -2551,7 +2570,7 @@ private class RollupFullRecalcTests {
Assert.areEqual(
1,
- [SELECT COUNT() FROM AsyncApexJob WHERE JobType = 'Queueable' AND ApexClass.Name = :getNamespaceSafeClassName(RollupAsyncProcessor.class)],
+ [SELECT COUNT() FROM AsyncApexJob WHERE JobType = 'Queueable' AND ApexClass.Name = :getNamespaceSafeClassName(RollupDeferredFullRecalcProcessor.class)],
JSON.serializePretty([SELECT JobType, ApexClass.Name FROM AsyncApexJob])
);
parent = [SELECT AnnualRevenue FROM Account WHERE Id = :parent.Id];
diff --git a/extra-tests/classes/RollupIntegrationTests.cls b/extra-tests/classes/RollupIntegrationTests.cls
index 5ec7919d..922227b0 100644
--- a/extra-tests/classes/RollupIntegrationTests.cls
+++ b/extra-tests/classes/RollupIntegrationTests.cls
@@ -36,8 +36,8 @@ private class RollupIntegrationTests {
new Rollup__mdt(
RollupFieldOnCalcItem__c = 'Amount',
LookupObject__c = 'Account',
- LookupFieldOnCalcItem__c = Opportunity.AccountIdText__c.getDescribe().getName(),
- LookupFieldOnLookupObject__c = Account.AccountIdText__c.getDescribe().getName(),
+ LookupFieldOnCalcItem__c = Opportunity.AccountIdText__c.toString(),
+ LookupFieldOnLookupObject__c = Account.AccountIdText__c.toString(),
RollupFieldOnLookupObject__c = 'AnnualRevenue',
RollupOperation__c = 'MAX',
CalcItem__c = 'Opportunity'
@@ -68,7 +68,7 @@ private class RollupIntegrationTests {
Rollup.rollupMetadata = new List{
new Rollup__mdt(
- RollupFieldOnCalcItem__c = Opportunity.AmountFormula__c.getDescribe().getName(),
+ RollupFieldOnCalcItem__c = Opportunity.AmountFormula__c.toString(),
LookupObject__c = 'Account',
LookupFieldOnCalcItem__c = 'AccountId',
LookupFieldOnLookupObject__c = 'Id',
@@ -150,19 +150,15 @@ private class RollupIntegrationTests {
Rollup.records = applications;
Rollup.FlowInput input = new Rollup.FlowInput();
- input.lookupFieldOnCalcItem = Application__c.ParentApplication__c.getDescribe().getName();
+ input.lookupFieldOnCalcItem = Application__c.ParentApplication__c.toString();
input.lookupFieldOnOpObject = 'Id';
input.recordsToRollup = applications;
input.rollupContext = 'INSERT';
- input.rollupFieldOnCalcItem = Application__c.Engagement_Score__c.getDescribe().getName();
- input.rollupFieldOnOpObject = ParentApplication__c.Engagement_Rollup__c.getDescribe().getName();
+ input.rollupFieldOnCalcItem = Application__c.Engagement_Score__c.toString();
+ input.rollupFieldOnOpObject = ParentApplication__c.Engagement_Rollup__c.toString();
input.rollupOperation = 'AVERAGE';
- input.rollupSObjectName = ParentApplication__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName();
- input.calcItemWhereClause =
- Application__c.Something_With_Underscores__c.getDescribe().getName() +
- ' != \'' +
- applications[0].Something_With_Underscores__c +
- '\'';
+ input.rollupSObjectName = ParentApplication__c.SObjectType.toString();
+ input.calcItemWhereClause = Application__c.Something_With_Underscores__c.toString() + ' != \'' + applications[0].Something_With_Underscores__c + '\'';
Test.startTest();
Rollup.performRollup(new List{ input });
@@ -188,16 +184,16 @@ private class RollupIntegrationTests {
insert apps;
Rollup.FlowInput input = new Rollup.FlowInput();
- input.lookupFieldOnCalcItem = Application__c.ParentApplication__c.getDescribe().getName();
+ input.lookupFieldOnCalcItem = Application__c.ParentApplication__c.toString();
input.lookupFieldOnOpObject = 'Id';
input.recordsToRollup = new List{ parentApp };
input.rollupContext = 'INSERT';
- input.rollupFieldOnCalcItem = Application__c.Engagement_Score__c.getDescribe().getName();
- input.rollupFieldOnOpObject = ParentApplication__c.Engagement_Rollup__c.getDescribe().getName();
+ input.rollupFieldOnCalcItem = Application__c.Engagement_Score__c.toString();
+ input.rollupFieldOnOpObject = ParentApplication__c.Engagement_Rollup__c.toString();
input.rollupOperation = 'SUM';
- input.rollupSObjectName = ParentApplication__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName();
+ input.rollupSObjectName = ParentApplication__c.SObjectType.toString();
input.isRollupStartedFromParent = true;
- input.calcItemTypeWhenRollupStartedFromParent = Application__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName();
+ input.calcItemTypeWhenRollupStartedFromParent = Application__c.SObjectType.toString();
Test.startTest();
Rollup.performRollup(new List{ input });
@@ -283,9 +279,9 @@ private class RollupIntegrationTests {
Rollup.records = appLogs;
Rollup.rollupMetadata = new List{
new Rollup__mdt(
- CalcItem__c = ApplicationLog__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName(),
- RollupFieldOnCalcItem__c = ApplicationLog__c.Object__c.getDescribe().getName(),
- LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.getDescribe().getName(),
+ CalcItem__c = ApplicationLog__c.SObjectType.toString(),
+ RollupFieldOnCalcItem__c = ApplicationLog__c.Object__c.toString(),
+ LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.toString(),
LookupObject__c = 'Account',
LookupFieldOnLookupObject__c = 'Id',
RollupFieldOnLookupObject__c = 'Name',
@@ -411,9 +407,9 @@ private class RollupIntegrationTests {
Rollup.shouldFlattenAsyncProcesses = true;
Rollup.rollupMetadata = new List{
new Rollup__mdt(
- CalcItem__c = ApplicationLog__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName(),
+ CalcItem__c = ApplicationLog__c.SObjectType.toString(),
RollupFieldOnCalcItem__c = 'Name',
- LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.getDescribe().getName(),
+ LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.toString(),
LookupObject__c = 'Account',
LookupFieldOnLookupObject__c = 'Id',
RollupFieldOnLookupObject__c = 'Name',
@@ -464,9 +460,9 @@ private class RollupIntegrationTests {
Rollup.shouldFlattenAsyncProcesses = true;
Rollup.rollupMetadata = new List{
new Rollup__mdt(
- CalcItem__c = ApplicationLog__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName(),
+ CalcItem__c = ApplicationLog__c.SObjectType.toString(),
RollupFieldOnCalcItem__c = 'Name',
- LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.getDescribe().getName(),
+ LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.toString(),
LookupObject__c = 'Account',
LookupFieldOnLookupObject__c = 'Id',
RollupFieldOnLookupObject__c = 'Name',
@@ -534,9 +530,9 @@ private class RollupIntegrationTests {
Rollup.rollupMetadata = new List{
new Rollup__mdt(
- CalcItem__c = ApplicationLog__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName(),
+ CalcItem__c = ApplicationLog__c.SObjectType.toString(),
RollupFieldOnCalcItem__c = 'Name',
- LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.getDescribe().getName(),
+ LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.toString(),
LookupObject__c = 'Account',
LookupFieldOnLookupObject__c = 'Id',
RollupFieldOnLookupObject__c = 'Name',
@@ -584,9 +580,9 @@ private class RollupIntegrationTests {
Rollup.shouldRun = true;
Rollup.FlowInput input = new Rollup.FlowInput();
input.recordsToRollup = parentApps;
- input.calcItemTypeWhenRollupStartedFromParent = ApplicationLog__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName();
- input.rollupFieldOnCalcItem = ApplicationLog__c.Name.getDescribe().getName();
- input.lookupFieldOnCalcItem = ApplicationLog__c.Application__c.getDescribe().getName();
+ input.calcItemTypeWhenRollupStartedFromParent = ApplicationLog__c.SObjectType.toString();
+ input.rollupFieldOnCalcItem = ApplicationLog__c.Name.toString();
+ input.lookupFieldOnCalcItem = ApplicationLog__c.Application__c.toString();
input.rollupSObjectName = 'Account';
input.lookupFieldOnOpObject = 'Id';
input.rollupFieldOnOpObject = 'Name';
@@ -638,9 +634,9 @@ private class RollupIntegrationTests {
Rollup.records = appLogs;
Rollup.rollupMetadata = new List{
new Rollup__mdt(
- CalcItem__c = ApplicationLog__c.getSObjectType().getDescribe().getName(),
- RollupFieldOnCalcItem__c = ApplicationLog__c.Name.getDescribe().getName(),
- LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.getDescribe().getName(),
+ CalcItem__c = ApplicationLog__c.getSObjectType().toString(),
+ RollupFieldOnCalcItem__c = ApplicationLog__c.Name.toString(),
+ LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.toString(),
LookupObject__c = 'Account',
LookupFieldOnLookupObject__c = 'Id',
RollupFieldOnLookupObject__c = 'Name',
@@ -683,9 +679,9 @@ private class RollupIntegrationTests {
Rollup.shouldFlattenAsyncProcesses = true;
Rollup.rollupMetadata = new List{
new Rollup__mdt(
- CalcItem__c = ApplicationLog__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName(),
+ CalcItem__c = ApplicationLog__c.SObjectType.toString(),
RollupFieldOnCalcItem__c = 'Name',
- LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.getDescribe().getName(),
+ LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.toString(),
LookupObject__c = 'Account',
LookupFieldOnLookupObject__c = 'Id',
RollupFieldOnLookupObject__c = 'AnnualRevenue',
@@ -925,7 +921,7 @@ private class RollupIntegrationTests {
null,
new Rollup__mdt(
RollupOperation__c = Rollup.Op.UPDATE_CONCAT_DISTINCT.name(),
- RollupFieldOnCalcItem__c = Opportunity.AmountFormula__c.getDescribe().getName(),
+ RollupFieldOnCalcItem__c = Opportunity.AmountFormula__c.toString(),
LookupFieldOnCalcItem__c = 'AccountId'
),
new Map(),
@@ -940,7 +936,7 @@ private class RollupIntegrationTests {
null,
new Rollup__mdt(
RollupOperation__c = Rollup.Op.UPDATE_CONCAT_DISTINCT.name(),
- RollupFieldOnCalcItem__c = Opportunity.AmountFormula__c.getDescribe().getName(),
+ RollupFieldOnCalcItem__c = Opportunity.AmountFormula__c.toString(),
LookupFieldOnCalcItem__c = 'AccountId'
),
new Map(),
@@ -1690,7 +1686,7 @@ private class RollupIntegrationTests {
Rollup.records = new List{ cpa };
Rollup.shouldRun = true;
Rollup.apexContext = TriggerOperation.AFTER_INSERT;
- Rollup.defaultControl = new RollupControl__mdt(MaxParentRowsUpdatedAtOnce__c = 0, ShouldRunAs__c = RollupMetaPicklists.ShouldRunAs.Batchable);
+ Rollup.defaultControl = new RollupControl__mdt(MaxParentRowsUpdatedAtOnce__c = 0);
Test.startTest();
Rollup.sumFromApex(ContactPointAddress.PreferenceRank, ContactPointAddress.ParentId, Account.Id, Account.AnnualRevenue, Account.SObjectType).runCalc();
@@ -1886,8 +1882,7 @@ private class RollupIntegrationTests {
static void shouldFilterNonMatchingRollupsOutOfBatch() {
Contact con = new Contact(FirstName = 'Something', LastName = 'Required');
insert con;
- RollupControl__mdt control = RollupControl__mdt.getInstance(Rollup.CONTROL_ORG_DEFAULTS).clone();
- control.ShouldRunAs__c = RollupMetaPicklists.ShouldRunAs.Batchable;
+
Rollup.FilterResults results = new Rollup.FilterResults();
results.matchingItemIds.add(con.Id);
RollupAsyncProcessor batchProcessor = new RollupAsyncProcessor(
@@ -1900,7 +1895,7 @@ private class RollupIntegrationTests {
Contact.SObjectType,
Rollup.Op.CONCAT,
Rollup.InvocationPoint.FROM_APEX,
- control,
+ RollupControl__mdt.getInstance(Rollup.CONTROL_ORG_DEFAULTS).clone(),
new Rollup__mdt(
CalcItem__c = 'Contact',
RollupFieldOnCalcItem__c = 'FirstName',
diff --git a/extra-tests/classes/RollupQueryBuilderTests.cls b/extra-tests/classes/RollupQueryBuilderTests.cls
index ea5ca498..4aab8c87 100644
--- a/extra-tests/classes/RollupQueryBuilderTests.cls
+++ b/extra-tests/classes/RollupQueryBuilderTests.cls
@@ -57,7 +57,7 @@ private class RollupQueryBuilderTests {
String queryString = RollupQueryBuilder.Current.getQuery(
Event.SObjectType,
new List{ 'Subject', 'WhatId' },
- Event.WhatId.getDescribe().getName(),
+ Event.WhatId.toString(),
'!=',
'(((What.Type = \'Account\') AND What.Owner.Id = :recordIds))'
);
@@ -81,7 +81,7 @@ private class RollupQueryBuilderTests {
String queryString = RollupQueryBuilder.Current.getQuery(
Event.SObjectType,
new List{ 'Subject', 'WhatId' },
- Event.WhatId.getDescribe().getName(),
+ Event.WhatId.toString(),
'!=',
'(((What.Type = \'Account\') OR What.Owner.Id = :recordIds))'
);
@@ -98,7 +98,7 @@ private class RollupQueryBuilderTests {
String queryString = RollupQueryBuilder.Current.getQuery(
Opportunity.SObjectType,
new List{ 'Amount' },
- Opportunity.AccountId.getDescribe().getName(),
+ Opportunity.AccountId.toString(),
'=',
'Amount > 0 OR CloseDate = YESTERDAY'
);
@@ -108,7 +108,7 @@ private class RollupQueryBuilderTests {
@IsTest
static void correctlyPutsAllRowsAtEnd() {
String queryString =
- RollupQueryBuilder.Current.getQuery(Event.SObjectType, new List{ 'Subject', 'WhatId' }, Event.WhatId.getDescribe().getName(), '!=') + '\nLIMIT 1';
+ RollupQueryBuilder.Current.getQuery(Event.SObjectType, new List{ 'Subject', 'WhatId' }, Event.WhatId.toString(), '!=') + '\nLIMIT 1';
System.assertEquals(true, queryString.contains(RollupQueryBuilder.ALL_ROWS), 'Needs to have all rows in order to be valid');
queryString = RollupQueryBuilder.Current.getAllRowSafeQuery(Event.SObjectType, queryString);
diff --git a/extra-tests/classes/RollupStateTests.cls b/extra-tests/classes/RollupStateTests.cls
new file mode 100644
index 00000000..8b02d8a6
--- /dev/null
+++ b/extra-tests/classes/RollupStateTests.cls
@@ -0,0 +1,370 @@
+@IsTest
+private class RollupStateTests {
+ @IsTest
+ static void commitsAndLoadsStateProperly() {
+ RollupState state = new RollupState();
+ String stubAccountId = RollupTestUtils.createId(Account.SObjectType);
+ RollupState.GenericInfo info = (RollupState.GenericInfo) state.getState(
+ stubAccountId,
+ new Rollup__mdt(RollupOperation__c = 'SUM'),
+ RollupState.GenericInfo.class
+ );
+ info.value = 5;
+ RollupState.AverageInfo averageInfo = (RollupState.AverageInfo) state.getState(
+ stubAccountId,
+ new Rollup__mdt(RollupOperation__c = 'CONCAT'),
+ RollupState.AverageInfo.class
+ );
+ averageInfo.increment(10);
+ RollupState.SObjectInfo sObjectInfo = (RollupState.SObjectInfo) state.getState(
+ stubAccountId,
+ new Rollup__mdt(RollupOperation__c = 'FIRST'),
+ RollupState.SObjectInfo.class
+ );
+ sObjectInfo.setItem(new Account(AnnualRevenue = 1000));
+ String secondStubId = RollupTestUtils.createId(Contact.SObjectType);
+ RollupState.MostInfo mostInfo = (RollupState.MostInfo) state.getState(
+ secondStubId,
+ new Rollup__mdt(RollupOperation__c = 'MOST'),
+ RollupState.MostInfo.class
+ );
+ mostInfo.setValues(5, 'some string');
+ // populate a null state value to be sure if the last iteration is "empty" the body is still properly committed
+ state.getState(secondStubId, new Rollup__mdt(RollupOperation__c = 'LAST'), RollupState.GenericInfo.class);
+ Id stubJobId = RollupTestUtils.createId(AsyncApexJob.SObjectType);
+ Set relatedRecordKeys = new Set{ '%' + stubAccountId + '%', '%' + secondStubId + '%' };
+
+ state.commitState(stubJobId);
+ state.loadState(stubJobId, new Set{ stubAccountId, secondStubId });
+ info = (RollupState.GenericInfo) state.getState(stubAccountId, new Rollup__mdt(RollupOperation__c = 'SUM'), RollupState.GenericInfo.class);
+ info.value = 6;
+ state.commitState(stubJobId);
+
+ RollupState__c insertedState = [
+ SELECT Id, Body0__c
+ FROM RollupState__c
+ WHERE RelatedRecordKeys0__c LIKE :relatedRecordKeys
+ ];
+ Assert.isNotNull(insertedState.Body0__c, 'Serialized representation of generic state should be present');
+
+ state.loadState(stubJobId, new Set{ stubAccountId, secondStubId });
+ Set