You need to sign in to do that
Don't have an account?
Justin Behnke
Refactor Existing Code to handle Query Limits
Hello All!
Can someone help me understand how I can refactor this code (pasted below) to handle query limits?
I am expecting to use some sort of tool like Batchable or Queueable. I have reviewed the Async Apex trailheads but the examples are difficult for me to map to what I am trying to do here.
This method must return the performance records based on ALL query results before returning. I am hoping that there is a way to query the records and then operate on all of the results from the query at once.
You can see that the limit is set to 10,000 but when refactored it will need to handle hundreds of thousands of records at one time. I have a few other classes that behave like this one for other metrics but if I can fix this one I'll be able to fix the others also.
Warm regards,
Justin Behnke
Can someone help me understand how I can refactor this code (pasted below) to handle query limits?
I am expecting to use some sort of tool like Batchable or Queueable. I have reviewed the Async Apex trailheads but the examples are difficult for me to map to what I am trying to do here.
This method must return the performance records based on ALL query results before returning. I am hoping that there is a way to query the records and then operate on all of the results from the query at once.
You can see that the limit is set to 10,000 but when refactored it will need to handle hundreds of thousands of records at one time. I have a few other classes that behave like this one for other metrics but if I can fix this one I'll be able to fix the others also.
Warm regards,
Justin Behnke
/** * Created by justin on 1/7/19. */ public with sharing class SkillDataFetcher implements Data_Based.IR_ISkillDataFetcher { private static final String CONTACTS_NAME = 'Attempted Contacts'; private static final String ANSWER_RATE_NAME = 'Answer Rate'; private static final String DISCOVERY_NAME = 'Discovery'; private static final String WIN_RATE_NAME = 'Win Rate'; private static final String AVG_DEAL_SIZE_NAME = 'Average Deal Size'; /** * For all of the areas that performance is measured for a given representative, * gather all of the skill performance metrics for all of the users associated * with the user ids that are passed in. * * All skill performances are derived from Tasks, Leads, and Opportunities that * have a last modified date between the start and end date times * * All skill mappings are associated with an id found in the skillMappings parameter. * * @param startDateTime the date of the last synchronization with DataBased * @param endDateTime a date that will be used as the new last synced date with DataBased * @param userIds a list of UserIds received from DataBased * @param skillMappings a list of Objects containing customer facing names and the internal Id's that DataBased has for * the skills that DataBased is prepared to analyze * @return a list of skill performances that represent how a rep did on a given skill on a given date */ public List<Data_Based.IR_SkillPerformance> getSkillPerformances( Datetime startDateTime, Datetime endDateTime, List<Id> userIds, List<Data_Based.IR_SkillMapping> skillMappings) { if (skillMappings.isEmpty()) { throw new System.InvalidParameterValueException('skillMappings','Empty'); } List<Data_Based.IR_SkillPerformance> skillPerformances = new List<Data_Based.IR_SkillPerformance>(); /* PROSPECTING PERFORMANCES */ List<Lead> allLeads = [ SELECT Id, OwnerId, IsConverted, IsDeleted, ConvertedDate, ConvertedOpportunityId, LastModifiedDate FROM Lead WHERE IsDeleted = FALSE ORDER BY ConvertedDate ASC LIMIT 10000]; Map<Id, Lead> leadsByIds = new Map<Id, Lead>(); for (Lead l : allLeads) { leadsByIds.put(l.Id, l); } Set<Id> ids = leadsByIds.keySet(); List<Task> callsPlaced = [ SELECT LastModifiedDate, OwnerId, ActivityDate, IsClosed, IsDeleted, Status, Subject, WhoId FROM Task WHERE WhoId IN :ids AND OwnerId IN :userIds AND LastModifiedDate > :startDateTime AND LastModifiedDate < :endDateTime AND (Status = 'Completed - Not Answered' OR Status = 'Completed - Answered') AND Subject = 'Call' AND IsDeleted = FALSE]; Data_Based.PerformanceBuilder attemptedContactsPerformanceBuilder = new Data_Based.PerformanceBuilder(false, CONTACTS_NAME, skillMappings); Data_Based.PerformanceBuilder callsAnsweredPerformanceBuilder = new Data_Based.PerformanceBuilder(false, ANSWER_RATE_NAME, skillMappings); for (Task c : callsPlaced) { Lead l = leadsByIds.get(c.WhoId); if ((l.IsConverted && c.ActivityDate <= l.ConvertedDate) || (!l.IsConverted)) { attemptedContactsPerformanceBuilder.incrementCount(c.OwnerId, c.ActivityDate); if (c.Status.equals('Completed - Answered')) { callsAnsweredPerformanceBuilder.incrementCount(c.OwnerId, c.ActivityDate); } } } skillPerformances.addAll(attemptedContactsPerformanceBuilder.getPerformances(skillMappings)); skillPerformances.addAll(callsAnsweredPerformanceBuilder.getPerformances(skillMappings)); /* OPPORTUNITY BASED PERFORMANCES */ List<Opportunity> allOpportunities = [ SELECT IsWon, Amount, CloseDate, CreatedDate, LastModifiedDate, OwnerId FROM Opportunity WHERE LastModifiedDate >= :startDateTime AND LastModifiedDate < :endDateTime AND OwnerId IN :userIds AND IsDeleted = FALSE]; Data_Based.PerformanceBuilder discoveryPerformanceBuilder = new Data_Based.PerformanceBuilder(false, DISCOVERY_NAME, skillMappings); Data_Based.PerformanceBuilder winRatePerformanceBuilder = new Data_Based.PerformanceBuilder(false, WIN_RATE_NAME, skillMappings); Data_Based.PerformanceBuilder averageDealSizePerformanceBuilder = new Data_Based.PerformanceBuilder(true, AVG_DEAL_SIZE_NAME, skillMappings); for (Opportunity o : allOpportunities) { discoveryPerformanceBuilder.incrementCount(o.OwnerId, o.CreatedDate.date()); if (o.IsWon) { winRatePerformanceBuilder.incrementCount(o.OwnerId, o.CloseDate); averageDealSizePerformanceBuilder.addToSum(o.OwnerId, o.CloseDate, o.Amount); } } skillPerformances.addAll(discoveryPerformanceBuilder.getPerformances(skillMappings)); skillPerformances.addAll(winRatePerformanceBuilder.getPerformances(skillMappings)); skillPerformances.addAll(averageDealSizePerformanceBuilder.getPerformances(skillMappings)); return skillPerformances; } }