Skip to content

Commit

Permalink
Eliminate RIB query from list processing
Browse files Browse the repository at this point in the history
  • Loading branch information
LawrenceLoz committed Nov 24, 2024
1 parent 5d4a1db commit 50e0740
Show file tree
Hide file tree
Showing 15 changed files with 151 additions and 64 deletions.
20 changes: 14 additions & 6 deletions fs-core/main/default/classes/FormulaShareBatchService.cls
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@ public virtual inherited sharing class FormulaShareBatchService {
}

// Create metrics for the execute context for any rules which don't have them already
List<FormulaShare_Metrics__c> metrics = createMetricsForNewRules();
uow.registerNew(metrics);
// Note that 'n/a' indicates a query wasn't run and a batch start error was encountered (logBatchStartError will be run)
if(query != 'n/a') {
setProcessingStartedAndCreateMetricsForNewRules(uow);
}

uow.commitWork();
}
Expand Down Expand Up @@ -396,7 +398,8 @@ public virtual inherited sharing class FormulaShareBatchService {
}


private List<FormulaShare_Metrics__c> createMetricsForNewRules() {
private void setProcessingStartedAndCreateMetricsForNewRules(fflib_ISObjectUnitOfWork uow) {
Datetime timeNow = Datetime.now();

// Make a set of rules which haven't had metrics records created already
Set<String> ruleNames = new Set<String>();
Expand All @@ -406,13 +409,18 @@ public virtual inherited sharing class FormulaShareBatchService {
FormulaShareMetricsSelector fsmSelector = new FormulaShareMetricsSelector();
List<FormulaShare_Metrics__c> existingMetrics = fsmSelector.getMetricsForRulesAndContext(ruleNames, executeContext);
for(FormulaShare_Metrics__c m : existingMetrics) {
m.Processing_Started__c = timeNow;
m.Processing_Finished__c = null; // Clear previous finish time
ruleNames.remove(m.FormulaShare_Rule_Name__c); // Take rules with metrics out of the set
}
uow.registerDirty(existingMetrics);

// Get list of blank metrics records for all rules which don't yet have batch metrics
List<FormulaShare_Metrics__c> allMetrics = FormulaShareMetrics.getBlankMetrics(ruleNames, executeContext);

return allMetrics;
List<FormulaShare_Metrics__c> newMetrics = FormulaShareMetrics.getBlankMetrics(ruleNames, executeContext);
for(FormulaShare_Metrics__c metrics : newMetrics) {
metrics.Processing_Started__c = timeNow;
}
uow.registerNew(newMetrics);
}

}
6 changes: 6 additions & 0 deletions fs-core/main/default/classes/FormulaShareMetrics.cls
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public inherited sharing class FormulaShareMetrics extends fflib_SObjectDomain {
public DateTime lastFailedOperation;
public DateTime LastSuccessfulBatch;
public DateTime lastFailedBatch;
public DateTime processingFinished;
}

public FormulaShareMetrics(List<FormulaShare_Metrics__c> sObjectList) {
Expand Down Expand Up @@ -110,6 +111,11 @@ public inherited sharing class FormulaShareMetrics extends fflib_SObjectDomain {
metrics.Last_Successful_Batch__c = inc.LastSuccessfulBatch;
metrics.Last_Failed_Batch__c = inc.lastFailedBatch;

// Override Processing Finished if explicitly provided
if(inc.processingFinished != null) {
metrics.Processing_Finished__c = inc.processingFinished;
}

if(metrics.Id == null) {
uow.registerNew(metrics);
}
Expand Down
5 changes: 4 additions & 1 deletion fs-core/main/default/classes/FormulaShareMetricsSelector.cls
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ public inherited sharing class FormulaShareMetricsSelector extends fflib_SObject
FormulaShare_Metrics__c.Successful_Inserts__c,
FormulaShare_Metrics__c.Context__c,
FormulaShare_Metrics__c.FormulaShare_Rule_Name__c,
FormulaShare_Metrics__c.Last_Batch_Run__c
FormulaShare_Metrics__c.Last_Batch_Run__c,
FormulaShare_Metrics__c.Processing_Started__c,
FormulaShare_Metrics__c.Processing_Finished__c,
FormulaShare_Metrics__c.LastModifiedDate
};
}

Expand Down
3 changes: 3 additions & 0 deletions fs-core/main/default/classes/FormulaShareProcessBatch.cls
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ public class FormulaShareProcessBatch implements Database.Batchable<sObject>, Da

this.batchService.createBatchAndRibLogs('n/a', this.batchSize);
this.batchService.logBatchStartError(this.batchStartError);

// Update list to clear "Processing..." label
EventBus.publish(new FormulaShare_List_Update__e());
}

return ql;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@

public inherited sharing class FormulaShareProcessedShareEventService {

static String context; // "Batch" and "Trigger" supported
static FormulaShare_Log__c batchLog;
static FormulaShare_Settings__mdt settings;
static fflib_ISObjectUnitOfWork uow;

// Metrics type names defined below.
// Typically we would expect each rule to have at most one metrics record for the following:
//
Expand All @@ -43,6 +38,11 @@ public inherited sharing class FormulaShareProcessedShareEventService {
public static final String triggerContext = 'Trigger Operations Since Last Batch';
public static final String batchFinishContext = 'Last Batch';

static String context;
static FormulaShare_Log__c batchLog;
static FormulaShare_Settings__mdt settings;
static fflib_ISObjectUnitOfWork uow;

private static Integer noRecordsSharingAppliedFirstTime;
private static Integer noRecordsAllSharingRemoved;
private static Integer noRecordsSharingUpdated;
Expand Down Expand Up @@ -225,10 +225,12 @@ public inherited sharing class FormulaShareProcessedShareEventService {

// Create a zero metric for each rule
Map<String,FormulaShareMetrics.Increment> metricsIncrements = new Map<String,FormulaShareMetrics.Increment>();
Datetime timeNow = Datetime.now();
for(String ruleName : ruleNamesSet) {
FormulaShareMetrics.Increment inc = new FormulaShareMetrics.Increment();
inc.noSuccessfulInserts = 0;
inc.noFailedInserts = 0;
inc.processingFinished = timeNow;
metricsIncrements.put(ruleName, inc);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,8 @@ public virtual inherited sharing class FormulaShareRemoveSharesSelector {
LIMIT 1];
}

public virtual Set<String> getObjectsWhereFullBatchUnsupported() {
return new Set<String>();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

public inherited sharing class FormulaShareRuleInBatchSelector extends fflib_SObjectSelector {

private final Integer QUERY_LIMIT = 10000;

public List<Schema.SObjectField> fields = new List<Schema.SObjectField>();

public FormulaShareRuleInBatchSelector(Boolean enforceObjectAndFieldSecurity) {
Expand Down Expand Up @@ -50,6 +52,7 @@ public inherited sharing class FormulaShareRuleInBatchSelector extends fflib_SOb
selectField('FormulaShare_Log__r.Processing_Finished__c').
selectField('FormulaShare_Log__r.Batch_Finish_Complete__c').
setCondition('FormulaShare_Rule_Name__c IN :ruleNames').
setLimit(QUERY_LIMIT).
toSOQL());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,33 +37,6 @@ public with sharing class FormulaShareRulesListViewController {
ruleNames.add(rule.developerName);
}

// Assess when last sharing calculation happened
FormulaShareRuleInBatchSelector ribSelector = new FormulaShareRuleInBatchSelector(true);
List<FormulaShareRuleInBatchSelector.RuleRunDetail> runDetails = ribSelector.getRuleRuns(ruleNames);
Map<String,FormulaShareRuleInBatchSelector.RuleRunDetail> ruleRunDetailMap = new Map<String,FormulaShareRuleInBatchSelector.RuleRunDetail>();

// Iterate through logs and build map of latest calculations
for(FormulaShareRuleInBatchSelector.RuleRunDetail runDetail : runDetails) {

// Consider only if rule was active when batch ran
if(runDetail.ruleActive) {

if(ruleRunDetailMap.containsKey(runDetail.developerName)) {
FormulaShareRuleInBatchSelector.RuleRunDetail thisDetail = ruleRunDetailMap.get(runDetail.developerName);

// If log is later than current latest, replace this (otherwise we'll keep the later log in the map)
if(thisDetail.processingStarted < runDetail.processingStarted) {
ruleRunDetailMap.put(runDetail.developerName, runDetail);
}
}

// If there wasn't already times in the map, record the details from this log
else {
ruleRunDetailMap.put(runDetail.developerName, runDetail);
}
}
}

// Build map of all metrics for rules
List<FormulaShare_Metrics__c> metricsList = FormulaShareMetricsSelector.construct().getAllMetricsForRules(new Set<String>(ruleNames));
Map<String,FormulaShare_Metrics__c> metricsMap = new Map<String,FormulaShare_Metrics__c>();
Expand Down Expand Up @@ -154,16 +127,32 @@ public with sharing class FormulaShareRulesListViewController {
}

// Set calculation status depending on most recent logs
if(!ruleRunDetailMap.containsKey(rw.developerName)) {
FormulaShare_Metrics__c batchMetrics = metricsMap.get(rw.developerName + FormulaShareProcessedShareEventService.batchContext);
FormulaShare_Metrics__c targetedJobMetrics = metricsMap.get(rw.developerName + FormulaShareProcessedShareEventService.targetedJobContext);

if(batchMetrics == null && targetedJobMetrics == null) {
rw.lastCalcStatus = 'Pending';
rw.iconName = 'standard:today';
rw.iconAlt = 'Pending';
}
}

else {
FormulaShareRuleInBatchSelector.RuleRunDetail runDetail = ruleRunDetailMap.get(rw.developerName);
if(runDetail.batchFinishComplete) {
rw.lastCalcStatus = runDetail.processingFinished.format();
FormulaShare_Metrics__c latestMetrics;
if(batchMetrics == null) {
latestMetrics = targetedJobMetrics;
}
else if(targetedJobMetrics == null) {
latestMetrics = batchMetrics;
}
else if(targetedJobMetrics.LastModifiedDate > batchMetrics.LastModifiedDate) {
latestMetrics = targetedJobMetrics;
}
else {
latestMetrics = batchMetrics;
}

if(latestMetrics.Processing_Finished__c != null) {
rw.lastCalcStatus = latestMetrics.Processing_Finished__c.format();
}

// If currently processing, indicate this against the field
Expand All @@ -184,8 +173,17 @@ public with sharing class FormulaShareRulesListViewController {

// Construct list of object wrappers with rules to return
List<ObjectRulesWrapper> orwList = new List<ObjectRulesWrapper>();

Datetime timeNow = DateTime.now();

// Get object which can only be calculated by targeted jobs (these don't allow Recalculate Sharing option)
FormulaShareRemoveSharesSelector selector = new FormulaShareInjectionService().getRemoveSharesSelector();
Set<String> objectsNotSupportingRecalculate = selector.getObjectsWhereFullBatchUnsupported();

for(String objectName : objectsWithRulesMap.keySet()) {
ObjectRulesWrapper orw = new ObjectRulesWrapper();
orw.refreshTime = timeNow;
orw.recalculateNotSupported = objectsNotSupportingRecalculate.contains(objectName);
List<RuleWrapper> rwList = objectsWithRulesMap.get(objectName);
rwList.sort();
for(RuleWrapper rw : rwList) {
Expand Down Expand Up @@ -242,6 +240,10 @@ public with sharing class FormulaShareRulesListViewController {
public List<RuleWrapper> items {get;set;}
@AuraEnabled
public String sharedObjectClass {get;set;}
@AuraEnabled
public Datetime refreshTime {get;set;}
@AuraEnabled
public Boolean recalculateNotSupported {get;set;}

// Comparable interface allows us to call sort
public Integer compareTo(Object compareTo) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,9 @@ public with sharing class FormulaShareRulesListViewControllerTest {
log.Processing_Started_Milliseconds__c = DateTime.now().getTime();
insert log;

FormulaShare_Rule_in_Batch__c rib = new FormulaShare_Rule_in_Batch__c();
rib.FormulaShare_Log__c = log.Id;
rib.FormulaShare_Rule_Name__c = fsRules[0].developerName;
rib.Rule_Active_for_Batch_Run__c = true;
insert rib;
FormulaShare_Metrics__c m1 = FormulaShareTestDataFactory.getBatchMetricsForRuleAndBatch(fsRules[0].developerName, log.Id);
m1.Processing_Started__c = DateTime.now().addMinutes(-5);
insert m1;

// Run core method
List<FormulaShareRulesListViewController.ObjectRulesWrapper> orwList = FormulaShareRulesListViewController.getTreeGridData();
Expand Down Expand Up @@ -135,7 +133,6 @@ public with sharing class FormulaShareRulesListViewControllerTest {
setMocks();

List<FormulaShareRule> fsRules = FormulaShareRulesSelector.construct().getAllRulesWithSecurityEnforced();

// Insert two logs and RIB records for the first rule indicating processing not yet complete
DateTime now = DateTime.now();
FormulaShare_Log__c log = new FormulaShare_Log__c();
Expand All @@ -149,16 +146,14 @@ public with sharing class FormulaShareRulesListViewControllerTest {
insert log;
insert log2;

FormulaShare_Rule_in_Batch__c rib = new FormulaShare_Rule_in_Batch__c();
FormulaShare_Rule_in_Batch__c rib2 = new FormulaShare_Rule_in_Batch__c();
rib.FormulaShare_Log__c = log.Id;
rib.FormulaShare_Rule_Name__c = fsRules[0].developerName;
rib.Rule_Active_for_Batch_Run__c = true;
rib2.FormulaShare_Log__c = log2.Id;
rib2.FormulaShare_Rule_Name__c = fsRules[0].developerName;
rib2.Rule_Active_for_Batch_Run__c = true;
insert rib;
insert rib2;
FormulaShare_Metrics__c m1 = FormulaShareTestDataFactory.getBatchMetricsForRuleAndBatch(fsRules[0].developerName, log.Id);
FormulaShare_Metrics__c m2 = FormulaShareTestDataFactory.getTargetedJobMetricsForRuleAndBatch(fsRules[0].developerName, log2.Id);
m1.Processing_Started__c = now.addDays(-1);
m1.Processing_Finished__c = now;
m2.Processing_Started__c = now.addDays(-2);
m2.Processing_Finished__c = now.addDays(-1);
insert m1;
insert m2;

// Run core method
List<FormulaShareRulesListViewController.ObjectRulesWrapper> orwList = FormulaShareRulesListViewController.getTreeGridData();
Expand Down
16 changes: 16 additions & 0 deletions fs-core/main/default/classes/FormulaShareTestDataFactory.cls
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ public inherited sharing class FormulaShareTestDataFactory {

static String batchContext = FormulaShareProcessedShareEventService.batchContext;
static String triggerContext = FormulaShareProcessedShareEventService.triggerContext;
static String targetedJobContext = FormulaShareProcessedShareEventService.targetedJobContext;
static String batchFinishContext = FormulaShareProcessedShareEventService.batchFinishContext;

static String userRuleName = FormulaShareRuleFactory.userRuleName;
Expand Down Expand Up @@ -164,6 +165,7 @@ public inherited sharing class FormulaShareTestDataFactory {
metrics.Failed_Inserts__c = 2;
metrics.Last_Successful_Operation__c = DateTime.now();
metrics.Last_Failed_Operation__c = DateTime.now();
metrics.Processing_Started__c = DateTime.now();
metrics.Last_Batch_Run__c = batchLogId;
return metrics;
}
Expand All @@ -176,6 +178,20 @@ public inherited sharing class FormulaShareTestDataFactory {
metrics.Failed_Inserts__c = 3;
metrics.Last_Successful_Operation__c = DateTime.now();
metrics.Last_Failed_Operation__c = DateTime.now();
metrics.Processing_Started__c = DateTime.now();
metrics.Last_Batch_Run__c = batchLogId;
return metrics;
}

public static FormulaShare_Metrics__c getTargetedJobMetricsForRuleAndBatch(String ruleName, Id batchLogId) {
FormulaShare_Metrics__c metrics = new FormulaShare_Metrics__c();
metrics.FormulaShare_Rule_Name__c = ruleName;
metrics.Context__c = targetedJobContext;
metrics.Successful_Inserts__c = 104;
metrics.Failed_Inserts__c = 4;
metrics.Last_Successful_Operation__c = DateTime.now();
metrics.Last_Failed_Operation__c = DateTime.now();
metrics.Processing_Started__c = DateTime.now();
metrics.Last_Batch_Run__c = batchLogId;
return metrics;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@
<behavior>Edit</behavior>
<field>Last_Batch_Run__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>Processing_Started__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>Processing_Finished__c</field>
</layoutItems>
</layoutColumns>
<layoutColumns>
<layoutItems>
Expand Down
Loading

0 comments on commit 50e0740

Please sign in to comment.