Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

W-9259597: pkBanding POC (CCS) #6628

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions force-app/main/default/classes/RD2_DatabaseService.cls
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public without sharing class RD2_DatabaseService {

private ERR_Handler.Errors errorResult = new ERR_Handler.Errors();
private Set<Id> failedRDIds = new Set<Id>();
private Map<Id,String> failedRDIdsMap = new Map<Id,String>();

/***
* @description Creates specified records
Expand Down Expand Up @@ -135,14 +136,31 @@ public without sharing class RD2_DatabaseService {
: ((Database.DeleteResult)dmlResults[i]).isSuccess();

if (!isSuccess) {
List<Database.Error> lErr = dmlResults[i] instanceof Database.SaveResult
? ((Database.SaveResult)dmlResults[i]).getErrors()
: ((Database.DeleteResult)dmlResults[i]).getErrors();
String sErr;
// Operation failed, so get all errors
for (Database.Error err : lErr) {
sErr = String.isBlank(sErr)
? err.getMessage()
: sErr + ', ' + err.getMessage();
}

failedRDIds.add((Id) records[i].get('npe03__Recurring_Donation__c'));
if (records[i].get('npe03__Recurring_Donation__c')!=null) {
failedRDIdsMap.put((Id) records[i].get('npe03__Recurring_Donation__c'), sErr);
}
}
}

} else if (recordSObjectType == rdSObjectType) {
for (Error__c error : dmlErrors.errorRecords) {
for (Error__c error : dmlErrors.errorRecords) {
failedRDIds.add(error.Related_Record_ID__c);
}
if (error.Related_Record_ID__c!=null) {
failedRDIdsMap.put(error.Related_Record_ID__c, error.Full_Message__c);
}
}
}
}

Expand All @@ -166,4 +184,21 @@ public without sharing class RD2_DatabaseService {
return failedRDIds.size();
}

/***
* @description Returns Ids of failed Recurring Donations
* @return Set<Id>
*/
public Set<Id> getRecordsFailedId() {
failedRDIds.remove(null);
return failedRDIds;
}

/***
* @description Returns Map of failed Recurring Donations Id to error message
* @return Map<Id,String>
*/
public Map<Id,String> getRecordsFailedMap() {
return failedRDIdsMap;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,22 @@ public inherited sharing class RD2_OpportunityEvaluationService {
return dbService.getRecordsFailed();
}

/**
* @description Returns set of Ids with failed RDs
* @return Set<Id>
*/
public Set<Id> getRecordsFailedId() {
return dbService.getRecordsFailedId();
}

/**
* @description Returns Map of Ids and error messages for failed RDs
* @return Map<Id,String>
*/
public Map<Id,String> getRecordsFailedMap() {
return dbService.getRecordsFailedMap();
}

/**
* @description Returns true if any of the key fields used to create or manage installment
* Opportunities has been changed.
Expand Down
179 changes: 179 additions & 0 deletions force-app/main/default/classes/UTIL_pkBanding.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
public with sharing class UTIL_pkBanding {

public String querySelect = getQuery();
public String queryWhere;
public pkBandingService.dispatcherResponse resp = new pkBandingService.dispatcherResponse();

// should be interface
public String getQuery() {
return new UTIL_Query()
.withFrom(npe03__Recurring_Donation__c.SObjectType)
.withSelectFields(
new Set<String>{ 'Id' }
)
.build();
}

// should be interface
public sObject[] getNextBatch(){
SObject[] records = new List<SObject>();
resp.completed = false;

while (records.isEmpty() && !resp.completed){
records = queryNextBatch();
if (records.isEmpty()){
getStartOfNextCluster();
}
}
return records;
}

public SObject[] queryNextBatch(){
if (resp.cursor.offset == null){
resp.cursor.offset = getStartOfNextCluster();
resp.cursor.offset = idAdd(resp.cursor.offset, -1);
}
if (getBand(resp.cursor.offset, resp.cursor.partitionBits) != resp.cursor.band){
resp.cursor.offset = getStartOfNextChunkInBand(
resp.cursor.offset,
resp.cursor.band,
resp.cursor.partitionBits);
resp.cursor.offset = idAdd(resp.cursor.offset, -1);
}
String startOffset = resp.cursor.offset;
String endOfChunk = getNearestEndOfChunkInBand(
resp.cursor.offset,
resp.cursor.band,
resp.cursor.partitionBits);
Integer batchSize = resp.cursor.batchSize;

String nextBatchQuery = querySelect +
(String.isblank(queryWhere)?' ':' ' + queryWhere) +
(String.isblank(queryWhere)?' WHERE ':' AND ') +
' Id > \'' + startOffset + '\' AND '+
' Id <= \'' + endOfChunk + '\'' +
' ORDER BY Id ASC LIMIT '+batchSize;

System.debug('nextBatchQuery: ' + nextBatchQuery);

SObject[] sObjectList = Database.query(nextBatchQuery);

if (sObjectList.isEmpty()) {
resp.cursor.sparse = true;
}
if (sObjectList.size()<batchSize) {
resp.cursor.offset = endOfChunk;

} else { //sObjectList.size()==batchSize
resp.cursor.offset = sObjectList[sObjectList.size()-1].Id.to15();
}
return sObjectList;
}


public String getStartOfNextCluster(){
String offset = resp.cursor.offset;
String nextIdQuery = querySelect +
(String.isblank(queryWhere)?' ':' ' + queryWhere) +
(String.isblank(queryWhere)&&offset!=null?' WHERE ':'') +
(!String.isblank(queryWhere)&&offset!=null?' AND ':'') +
(offset!=null?' Id > :offset ':' ') +
' ORDER BY Id ASC LIMIT 1';
//System.assert(false, nextIdQuery);
sObject[] firstIdList = Database.query(nextIdQuery);
String minId;
If (!firstIdList.isEmpty()) {
minId = firstIdList[0].Id.to15();
resp.cursor.offset = minId;
resp.cursor.sparse = false;
} else {
resp.completed = true;
}
return minId;
}


public String getStartOfNextChunkInBand(String b62, Integer band, Integer bandBits) {
//TO DO: What if band is not 3 bits?
System.assert(bandBits == 3, 'Only 3-bit bands are currently suported');
System.assert(b62.length()==15,'b62 number must be exactly 15 chars long');
String IdPrefix = b62.left(6);
String chunkPrefix = b62.mid(6,6);
//TO DO: figure out if I need to add offset 1 or not based on actual band in key
Integer nextBandOffset = getBand(b62, bandBits)>=band?1:0;
//System.assert(false,'chunkprefix: '+chunkPrefix + 'nextBandOffset: '+ nextBandOffset);
chunkPrefix = longToB62(b62toLong(chunkPrefix)+nextBandOffset,6);
String bandStr = longToB62(band<<3,1);
b62 = IdPrefix + chunkPrefix + bandStr + '00';
return b62;
}


public String getNearestEndOfChunkInBand(String b62, Integer band, Integer bandBits) {
//TO DO: What if band is not 3 bits?
System.assert(bandBits == 3, 'Only 3-bit bands are currently suported');
System.assert(b62.length()==15,'b62 number must be exactly 15 chars long');
//b62 = getStartOfNextChunkInBand(b62, band, bandBits);
String IdPrefix = b62.left(6);
String chunkPrefix = b62.mid(6,6);
Integer nextBandOffset = getBand(b62, bandBits)>band?1:0;
chunkPrefix = longToB62(b62toLong(chunkPrefix)+nextBandOffset,6);
//TO DO: Cannot add 7 to band 111b or it will overflow!!! Subtract 10b?
Integer last3bits = band==7?5:7;
String bandStr = longToB62((band<<3)+last3bits,1);
b62 = IdPrefix + chunkPrefix + bandStr + 'zz';
return b62;
}


public Integer getBand(String b62, Integer bandBits){
System.assert(bandBits == 3, 'Only 3-bit bands are currently suported');
System.assert(b62.length()==15,'b62 number must be exactly 15 chars long');
Integer band;
band = (Integer)b62toLong(b62.mid(12,1));
band >>>=3;
return band;
}


public String idAdd(String b62, Long addend){
System.assert(b62.length()==15,'b62 number must be exactly 15 chars long');
String IdPrefix = b62.left(6);
String sequenceB62 = b62.mid(6,9);
Long sequenceDec = b62toLong(sequenceB62);
sequenceDec += addend;
System.assert(sequenceDec>=0,'Negative Ids are not valid');
sequenceB62 = longToB62(sequenceDec, 9);
b62 = IdPrefix + sequenceB62;
return b62;
}


public Long b62toLong(String b62){
System.assert(b62.length()<=10,'b62 string is too long');
String chars ='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; //[0-9A-Za-z]
Long sum=0;
for (String i: b62.split('')){
sum = sum*62;
sum += chars.indexOf(i);
}
return sum;
}


public String longToB62(Long lng, Integer length) {
System.assert(lng >= 0, 'Cannot convert negative number to base62');
System.assert(length <= 10, 'Largest supported base62 length is 10');
String chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; //[0-9A-Za-z]
String b62 = '';
while (lng > 0) {
Integer lchar = (Integer) Math.mod(lng, 62);
b62 = chars.mid(lchar, 1) + b62;
lng = lng / 62;
}
b62 = b62.leftPad(length, '0');
System.assert(b62.length() <= length, 'b62 conversion OVERFLOW: ' + b62);
return b62;
}

}
5 changes: 5 additions & 0 deletions force-app/main/default/classes/UTIL_pkBanding.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>52.0</apiVersion>
<status>Active</status>
</ApexClass>
Loading