3

I have this Schedulable Class that finds all Email Campaigns of a certain age and sends that age to an external service. I am pretty sure I am doing it wrong. First I want to pull the values for the integer array from a custom label.email_campaign_ages, but cant seem to make that happen, so I hard coded the values in.

global class SGsegUPDT implements schedulable {
// set cron for everyday at 10pm
    public static String CRON_EXP = '0 0 10 1/1 * ? *';
// Days to send emails  
String label = system.label.email_campaign_ages;
public Static Integer[] ecAges = new Integer[]{0, 3, 22, 52, 112, 202, 382};
// made it this way to only sendRequest once instead of once per age group
global static List<Map<String, Object>> jsonMAP = new List<Map<String, Object>>();
// not sure if this is needed.
global static String scheduleIt() {
    SGsegUPDT segUP = new SGsegUPDT();
    return System.schedule('Sendgrid Daily update', CRON_EXP, segUP);
}

    global void execute(SchedulableContext ctx) {
        //get all leads
        for (Integer i : ecAges) { System.debug(i);
                for (email_campaign__c ec : [
                SELECT email__c, First_Name__c, Last_Name__c , Campaign_Age__c , Agency_Type__c
                FROM email_campaign__c
                WHERE Campaign_Age__c  = :i]) {
                    Map<String, Object> mapped = new Map<String, Object>{ //they are flipped at serailization 
                        'type' => ec.Agency_Type__c,                          //to come out correct listed in reverse
                        'age' => ec.Campaign_Age__c,
                        'last_name' => ec.Last_Name__c,
                        'first_name' => ec.First_Name__c,
                        'email' => ec.Email__c
                    };
                        jsonMAP.add(mapped); system.debug(mapped);  
                }
            }     
                 String jsonString = JSON.serialize(jsonMAP);  
                //send the jsonpayload, endpoint uri, and verb
                SendGridAPI.sendRequest(jsonString,'/v3/contactdb/recipients', 'PATCH'); system.debug(jsonString);                
}    
}

I feel like I am going to get some limit errors, should this be done in batch instead? I know its working on a small scale as is. Just not sure when its running thousands or records a night what will happen...

3

Here is the complete approach.

Create a List of String upon parsing customLabel and then create a List of Integer.

If you are defining custom label as 0, 3, 22, 52, 112, 202, 382

Don't forget to trim individual String item before converting to Integer as follows, otherwise you will get - System.TypeException Invalid Integer, this the catch

ecAges.add(Integer.valueOf(str.trim()));

You could run SOQL out of the for loop upon passing ecAges in the WHERE clause.

global class SGsegUPDT implements schedulable {
// set cron for everyday at 10pm
    public static String CRON_EXP = '0 0 10 1/1 * ? *';
// Days to send emails  
String customlabel = system.label.email_campaign_ages;

//public Static Integer[] ecAges = new Integer[]{0, 3 22, 52, 112, 202, 382};


// made it this way to only sendRequest once instead of once per age group
global static List<Map<String, Object>> jsonMAP = new List<Map<String, Object>>();
// not sure if this is needed.
global static String scheduleIt() {
    SGsegUPDT segUP = new SGsegUPDT();
    return System.schedule('Sendgrid Daily update', CRON_EXP, segUP);
}

    global void execute(SchedulableContext ctx) 
    {
        //split the custom label
        List<String> labelStr = customlabel.split(',');

        //put it into List<Integer>
        List<Integer> ecAges = new List<Integer>();
        for(String str:labelStr)
        {
            ecAges.add(Integer.valueOf(str.trim())); //mind to trim() the String, otherwise you will receive error.
        }

        //get all leads

        for (email_campaign__c ec : [SELECT email__c, First_Name__c, Last_Name__c , Campaign_Age__c , Agency_Type__c
                                    FROM email_campaign__c
                                    WHERE Campaign_Age__c  IN:ecAges]) 
        {
            Map<String, Object> mapped = new Map<String, Object>{ //they are flipped at serailization 
                'type' => ec.Agency_Type__c,                          //to come out correct listed in reverse
                'age' => ec.Campaign_Age__c,
                'last_name' => ec.Last_Name__c,
                'first_name' => ec.First_Name__c,
                'email' => ec.Email__c
            };
                jsonMAP.add(mapped); 
                system.debug(mapped);  
        }

        String jsonString = JSON.serialize(jsonMAP);  
        //send the jsonpayload, endpoint uri, and verb
        SendGridAPI.sendRequest(jsonString,'/v3/contactdb/recipients', 'PATCH'); system.debug(jsonString);                
    }    
}
2

Instead of running the query in the loop for each of the ecAges, you could query for all the campaigns together and build payload by looping once through the results:

global void execute(SchedulableContext ctx) {
    email_campaign__c[] emailCampaigns = [
        SELECT email__c, First_Name__c, Last_Name__c, Campaign_Age__c, Agency_Type__c
        FROM email_campaign__c
        WHERE Campaign_Age__c  IN :ecAges
        ORDER BY Campaign_Age__c
    ];

    for (email_campaign__c[] ec : emailCampaigns) {
        Map<String, Object> mapped = new Map<String, Object> {
            'type' => ec.Agency_Type__c,
            'age' => ec.Campaign_Age__c,
            'last_name' => ec.Last_Name__c,
            'first_name' => ec.First_Name__c,
            'email' => ec.Email__c
        };

        jsonMAP.add(mapped); system.debug(mapped);  
    }

    String jsonString = JSON.serialize(jsonMAP);
    SendGridAPI.sendRequest(jsonString,'/v3/contactdb/recipients', 'PATCH');
}

As for scaling, you should be able to query up to 50,000 records, so if you are expecting more than that then you should consider using Batch.

To parse the label for days to send you split the string and convert the individual values to integers:

// Assuming label has value: 0,3,22,52,112,202,382
Integer[] ecAges = new Integer[0];
for (String ecAge : label.split(',')) {
    ecAges.add(Integer.valueOf(ecAge);
}

You might also want to consider using CustomSettings for this.

  • Thanks for the advice, it's seems so logical now lol. What about converting the system.label.email_campaign_ages to an int[]? – Roger Morris Sep 6 '17 at 17:40
  • @RogerMorris Updated with example for converting string label to int[] – Alan Morey Sep 6 '17 at 17:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.