Skip to content

Commit

Permalink
Merge pull request #1492 from SFDO-Community/feature/1016-allow-disab…
Browse files Browse the repository at this point in the history
…le-of-problem-emails

Allow disable of problem emails and add logging
  • Loading branch information
aheber authored Sep 12, 2024
2 parents ce162ed + 6800a70 commit 3f37248
Show file tree
Hide file tree
Showing 12 changed files with 551 additions and 5 deletions.
35 changes: 35 additions & 0 deletions dlrs/main/classes/MessageService.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* A service class around the platform Messaging class
* Allowing us to capture send attempts and record them for test validation
*/
public with sharing class MessageService {
@TestVisible
static List<SentEmails> sentEmailList = new List<SentEmails>();

public static Messaging.SendEmailResult[] sendEmail(
Messaging.Email[] emails
) {
return sendEmail(emails, true);
}

public static Messaging.SendEmailResult[] sendEmail(
Messaging.Email[] emails,
Boolean allOrNothing
) {
if (Test.isRunningTest()) {
sentEmailList.add(new SentEmails(emails, allOrNothing));
}
return Messaging.sendEmail(emails, allOrNothing);
}

@TestVisible
private class SentEmails {
public Messaging.Email[] emails;
public Boolean allOrNothing;

public SentEmails(Messaging.Email[] emails, Boolean allOrNothing) {
this.emails = emails;
this.allOrNothing = allOrNothing;
}
}
}
5 changes: 5 additions & 0 deletions dlrs/main/classes/MessageService.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>61.0</apiVersion>
<status>Active</status>
</ApexClass>
28 changes: 27 additions & 1 deletion dlrs/main/classes/RollupCalculateJob.cls
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,32 @@ public with sharing class RollupCalculateJob implements Database.Batchable<sObje
new Map<Id, Sobject>(masterRecords).keySet()
);
} catch (Exception e) {
LookupRollupSummaryLog__c logEntry = new LookupRollupSummaryLog__c();
List<RollupSummary> rollup = new RollupSummariesSelector()
.selectById(new Set<String>{ lookupId });
logEntry.ParentId__c = lookupId;
if (!rollup.isEmpty()) {
// Log the failure updating the master record for review
logEntry.ParentObject__c = rollup[0]
.Record.getSObjectType()
.getDescribe()
.getName();
}

logEntry.ErrorMessage__c =
e.getMessage() +
' : ' +
e.getStackTraceString();

upsert logEntry ParentId__c;

if (
DeclarativeLookupRollupSummaries__c.getInstance()
.DisableProblemEmails__c
) {
// if emails are disabled then bail out
return;
}
// Ids in scope
List<String> ids = new List<String>();
for (Id recordId : new Map<Id, SObject>(masterRecords).keySet()) {
Expand All @@ -82,7 +108,7 @@ public with sharing class RollupCalculateJob implements Database.Batchable<sObje
new List<String>{ e.getMessage(), String.join(ids, ',') }
)
);
Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{ mail });
MessageService.sendEmail(new List<Messaging.SingleEmailMessage>{ mail });
}
}

Expand Down
33 changes: 30 additions & 3 deletions dlrs/main/classes/RollupCalculateJobSchedulable.cls
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,33 @@ public with sharing class RollupCalculateJobSchedulable implements Schedulable {
// Enqueue the job to recalcualte the given rollup parent records
RollupService.runJobToCalculate(rollupRecordId, masterWhereClause);
} catch (Exception e) {
LookupRollupSummaryLog__c logEntry = new LookupRollupSummaryLog__c();
List<RollupSummary> rollup = new RollupSummariesSelector()
.selectById(new Set<String>{ rollupRecordId });
logEntry.ParentId__c = rollupRecordId;
if (!rollup.isEmpty()) {
// Log the failure updating the master record for review
logEntry.ParentObject__c = rollup[0]
.Record.getSObjectType()
.getDescribe()
.getName();
}

logEntry.ErrorMessage__c =
e.getMessage() +
' : ' +
e.getStackTraceString();

upsert logEntry ParentId__c;

if (
DeclarativeLookupRollupSummaries__c.getInstance()
.DisableProblemEmails__c
) {
// if emails are disabled then bail out
return;
}

// Resolve the name of this job
Id triggerId = sc.getTriggerId();
Map<Id, String> jobNameByTriggerId = new CronJobDetailsSelector()
Expand All @@ -34,12 +61,12 @@ public with sharing class RollupCalculateJobSchedulable implements Schedulable {
mail.setPlainTextBody(
String.format(
'Error: {0} ' +
'Review the error, rollup definition and/or delete the Apex Scheduled job under Setup. ' +
'Check if the rollup still exists via the Manage Rollup Summaries and/or Lookup Rollup Summaries tabs. ',
'Review the error, rollup definition and/or delete the Apex Scheduled job under Setup. ' +
'Check if the rollup still exists via the Manage Rollup Summaries and/or Lookup Rollup Summaries tabs. ',
new List<String>{ e.getMessage() }
)
);
Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{ mail });
MessageService.sendEmail(new List<Messaging.SingleEmailMessage>{ mail });
}
}
}
85 changes: 85 additions & 0 deletions dlrs/main/classes/RollupCalculateJobSchedulableTest.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
@IsTest
private class RollupCalculateJobSchedulableTest {
@IsTest
private static void testScheduleCalculateJobWithFailure() {
LookupRollupSummary__c rollupSummary = new LookupRollupSummary__c();
rollupSummary.ParentObject__c = 'Account';
rollupSummary.ChildObject__c = 'Contact';
rollupSummary.RelationShipField__c = 'AccountId';
rollupSummary.FieldToAggregate__c = 'Id';
rollupSummary.AggregateOperation__c = RollupSummaries.AggregateOperation.Count.name();
rollupSummary.AggregateResultField__c = 'Description';
rollupSummary.Active__c = true;
rollupSummary.CalculationMode__c = 'Developer';
insert rollupSummary;

// mark the job already running so it throws an exception
RollupService.checkJobAlreadyRunning(rollupSummary.Id, rollupSummary.Name);

ApexPages.StandardController standardController = new ApexPages.StandardController(
rollupSummary
);
RollupScheduledCalculateController controller = new RollupScheduledCalculateController(
standardController
);

Test.startTest();
controller.scheduleCalculateJob();
Test.stopTest();

List<LookupRollupSummaryLog__c> logs = [
SELECT Id, ParentId__c, ParentObject__c
FROM LookupRollupSummaryLog__c
];
Assert.areEqual(1, logs.size());
Assert.areEqual(
Schema.LookupRollupSummary__c.getSObjectType().getDescribe().getName(),
logs[0].ParentObject__c
);
Assert.areEqual(rollupSummary.Id, logs[0].ParentId__c);
Assert.areEqual(1, MessageService.sentEmailList.size());
}

private testMethod static void testScheduleCalculateJobPreventEmail() {
LookupRollupSummary__c rollupSummary = new LookupRollupSummary__c();
rollupSummary.ParentObject__c = 'Account';
rollupSummary.ChildObject__c = 'Contact';
rollupSummary.RelationShipField__c = 'AccountId';
rollupSummary.FieldToAggregate__c = 'Id';
rollupSummary.AggregateOperation__c = RollupSummaries.AggregateOperation.Count.name();
rollupSummary.AggregateResultField__c = 'Description';
rollupSummary.Active__c = true;
rollupSummary.CalculationMode__c = 'Developer';
insert rollupSummary;

// mark the job already running so it throws an exception
RollupService.checkJobAlreadyRunning(rollupSummary.Id, rollupSummary.Name);

ApexPages.StandardController standardController = new ApexPages.StandardController(
rollupSummary
);
RollupScheduledCalculateController controller = new RollupScheduledCalculateController(
standardController
);
DeclarativeLookupRollupSummaries__c settings = new DeclarativeLookupRollupSummaries__c(
DisableProblemEmails__c = true
);
insert settings;

Test.startTest();
controller.scheduleCalculateJob();
Test.stopTest();

List<LookupRollupSummaryLog__c> logs = [
SELECT Id, ParentId__c, ParentObject__c
FROM LookupRollupSummaryLog__c
];
Assert.areEqual(1, logs.size());
Assert.areEqual(
Schema.LookupRollupSummary__c.getSObjectType().getDescribe().getName(),
logs[0].ParentObject__c
);
Assert.areEqual(rollupSummary.Id, logs[0].ParentId__c);
Assert.areEqual(0, MessageService.sentEmailList.size());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>61.0</apiVersion>
<status>Active</status>
</ApexClass>
141 changes: 141 additions & 0 deletions dlrs/main/classes/RollupCalculateJobTest.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
@IsTest
private class RollupCalculateJobTest {
@IsTest
static void testCrashHandlingWithEmail() {
String prefix = LookupRollupSummary2__mdt.sObjectType.getDescribe()
.getKeyPrefix();

LookupRollupSummary2__mdt rollupCfg = new LookupRollupSummary2__mdt(
Id = prefix + '00000000000000D',
Label = 'A Summary',
DeveloperName = 'A_Summary',
ParentObject__c = 'A',
ChildObject__c = 'X',
RelationshipField__c = '1',
CalculationMode__c = 'Realtime',
Active__c = true
);
RollupSummariesSelector.setRollupCache(
false,
false,
RollupSummary.toList(new List<LookupRollupSummary2__mdt>{ rollupCfg })
);

Account a = new Account(Name = 'Test');
insert a;

RollupCalculateJob job = new RollupCalculateJob(rollupCfg.Id);
Test.startTest();
job.execute(new MockBatchableContext(), new List<SObject>{ a });
Test.stopTest();

List<LookupRollupSummaryLog__c> logs = [
SELECT Id, ParentId__c, ParentObject__c
FROM LookupRollupSummaryLog__c
];
Assert.areEqual(1, logs.size());
Assert.areEqual(
Schema.LookupRollupSummary2__mdt.getSObjectType().getDescribe().getName(),
logs[0].ParentObject__c
);
Assert.areEqual(rollupCfg.Id, logs[0].ParentId__c);
Assert.areEqual(1, MessageService.sentEmailList.size());
}

@IsTest
static void testCrashHandlingWithoutEmail() {
String prefix = LookupRollupSummary2__mdt.sObjectType.getDescribe()
.getKeyPrefix();

LookupRollupSummary2__mdt rollupCfg = new LookupRollupSummary2__mdt(
Id = prefix + '00000000000000D',
Label = 'A Summary',
DeveloperName = 'A_Summary',
ParentObject__c = 'A',
ChildObject__c = 'X',
RelationshipField__c = '1',
CalculationMode__c = 'Realtime',
Active__c = true
);
RollupSummariesSelector.setRollupCache(
false,
false,
RollupSummary.toList(new List<LookupRollupSummary2__mdt>{ rollupCfg })
);

Account a = new Account(Name = 'Test');
insert a;

DeclarativeLookupRollupSummaries__c settings = new DeclarativeLookupRollupSummaries__c(
DisableProblemEmails__c = true
);
insert settings;

RollupCalculateJob job = new RollupCalculateJob(rollupCfg.Id);
Test.startTest();
job.execute(new MockBatchableContext(), new List<SObject>{ a });
Test.stopTest();

List<LookupRollupSummaryLog__c> logs = [
SELECT Id, ParentId__c, ParentObject__c
FROM LookupRollupSummaryLog__c
];
Assert.areEqual(1, logs.size());
Assert.areEqual(
Schema.LookupRollupSummary2__mdt.getSObjectType().getDescribe().getName(),
logs[0].ParentObject__c
);
Assert.areEqual(rollupCfg.Id, logs[0].ParentId__c);
Assert.areEqual(0, MessageService.sentEmailList.size());
}

@IsTest
static void testRunBatch() {
String prefix = LookupRollupSummary2__mdt.sObjectType.getDescribe()
.getKeyPrefix();

LookupRollupSummary2__mdt rollupCfg = new LookupRollupSummary2__mdt(
Id = prefix + '00000000000000D',
Label = 'A Summary',
DeveloperName = 'A_Summary',
ParentObject__c = 'Account',
ChildObject__c = 'Contact',
RelationshipField__c = 'AccountId',
AggregateOperation__c = RollupSummaries.AggregateOperation.Count.name(),
AggregateResultField__c = 'Description',
FieldToAggregate__c = 'Id',
CalculationMode__c = 'Realtime',
AggregateAllRows__c = false,
Active__c = true
);
RollupSummariesSelector.setRollupCache(
false,
false,
RollupSummary.toList(new List<LookupRollupSummary2__mdt>{ rollupCfg })
);

Account a = new Account(Name = 'Test');
insert a;

RollupCalculateJob job = new RollupCalculateJob(rollupCfg.Id, 'Id != NULL');
Test.startTest();
Database.executeBatch(job);
Test.stopTest();

List<LookupRollupSummaryLog__c> logs = [
SELECT Id, ParentId__c, ParentObject__c, ErrorMessage__c
FROM LookupRollupSummaryLog__c
];
Assert.areEqual(0, logs.size(), 'Found:' + JSON.serializePretty(logs));
}

public class MockBatchableContext implements Database.BatchableContext {
public Id getJobId() {
return '100000000000000';
}

public Id getChildJobId() {
return '100000000000000';
}
}
}
5 changes: 5 additions & 0 deletions dlrs/main/classes/RollupCalculateJobTest.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>61.0</apiVersion>
<status>Active</status>
</ApexClass>
Loading

0 comments on commit 3f37248

Please sign in to comment.