First, here are a couple of usage examples. These can be run in an "Execute Anonymous" window in the developer console or Force.com IDE.
// 1. schedule a process to delete old accounts and email myself when complete System.schedule('Account Cleanup', '0 0 0 1 * *', new SF_Batch('Delete old accounts', SF_Batch.OP.OP_DELETE, 'SELECT Id FROM Account WHERE CreatedDate != THIS_YEAR', new String[] {'scox67@gmail.com'}));
// 2. mark all my cases as 'TEST' class AccountNameUpdater implements SF_Batch.Handler { public void handle(SObject[] scope) { for (Case c : (Case[])scope) { c.Name += ' TEST'; } } } Database.executeBatch(new SF_Batch('Mark Test Cases', SF_Batch.OP.OP_UPDATE, 'SELECT Name FROM Case WHERE Owner.Name = \'Steve Cox\'', new AccountNameUpdater(), null);
If several scheduled cleanup tasks are needed in your org, you can create a custom setting and use a simple function like scheduleAllJobs (below) to load them all up at once. Here's the complete code listing. Enjoy!
public class SF_Batch implements Database.Batchable<SObject>, Schedulable { //-------------------------------------------------------------------------- // Constants public enum OP { OP_UPDATE, OP_DELETE, OP_UNDELETE } private final static String ALL_ROWS = ' ALL ROWS '; // {0} = process name, {1} = status private final static String NOTIFY_SUBJECT = 'Salesforce Batch Process: {0} - {1}'; // {0} = total batches processed, {1} = number of failures private final static String NOTIFY_BODY = '{0} batch(es) processed, with {1} failure(s).'; //-------------------------------------------------------------------------- // Properties private String name; private String query; private OP operation; private Handler handler; private String[] notify; //-------------------------------------------------------------------------- // Constructor /** * Create a batch process * @param name optional name of the process. This will be reported in the * notification email. * @param operation the operation to perform * @param query the query used to select records * @param handler an optional handler. If specified, h.handle() will be called * and passed the array of objects before the operation is performed. * @param notify optional email addresses for finish or error notifications */ public SF_Batch(String name, OP operation, String query, Handler handler, String[] notify) { SF.preCondition(null != operation, 'SF_Batch.SF_Batch() - missing operation'); SF.preCondition(!SF.isEmpty(query), 'SF_Batch.SF_Batch() - missing query'); this.name = name; this.operation = operation; this.handler = handler; this.notify = notify; if ((OP.OP_UNDELETE == operation) && !query.contains(ALL_ROWS)) { this.query = query + ALL_ROWS; } else { this.query = query; } // validate that the query is valid SObject[] o = Database.query(this.query); } public interface Handler { void handle(SObject[] scope); } /** Database.Batchable method */ public Database.QueryLocator start(Database.BatchableContext context) { return Database.getQueryLocator(query); } /** Database.Batchable method */ public void execute(Database.BatchableContext context, SObject[] scope) { if (null != handler) { handler.handle(scope); } if (OP.OP_UPDATE == operation) { update scope; } else if (OP.OP_DELETE == operation) { delete scope; } else if (OP.OP_UNDELETE == operation) { undelete scope; } } /** Database.Batchable method */ public void finish(Database.BatchableContext context) { if (null != notify) { AsyncApexJob a = [SELECT Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Name FROM AsyncApexJob WHERE Id = :context.getJobId()]; final String subject = String.format(NOTIFY_SUBJECT, new String[]{ String.valueOf(name), String.valueOf(a.Status)}); final String body = String.format(NOTIFY_BODY, new String[]{ String.valueOf(a.TotalJobItems), String.valueOf(a.NumberOfErrors)}); new SF.Email(notify, null, null, subject, body).send(); } } /** Schedulable method */ public void execute(SchedulableContext SC) { Database.executeBatch(new SF_Batch(name, operation, query, handler, notify)); } //-------------------------------------------------------------------------- // Schedule/abort processes from custom settings /** * Schedule all active jobs specified in the SF Job custom setting. */ public static void scheduleAllJobs() { final Map<String, Batch.OP> opMap = new Map<String, Batch.OP> { 'update' => SF_Batch.OP.OP_UPDATE, 'delete' => SF_Batch.OP.OP_DELETE, 'undelete' => SF_Batch.OP.OP_UNDELETE }; SF_Job__c[] jobs = new SF_Job__c[]{}; for (SF_Job__c j : [SELECT Name, Schedule__c, Operation__c, Query__c, Email_Recipients__c FROM SF_Job__c WHERE Active__c = true]) { final SF_Batch b = new SF_Batch(j.Name, opMap.get(j.Operation__c.toLowerCase()), j.Query__c, null, (null != j.Email_Recipients__c)? j.Email_Recipients__c.split(',') : null); final Id cronId = System.schedule(j.Name, j.Schedule__c, b); jobs.add(new SF_Job__c(Id = j.Id, Job_Id__c = cronId)); } update jobs; } /** * Abort all active jobs launched with scheduleAllJobs */ public static void abortAllJobs() { SF_Job__c[] jobs = new SF_Job__c[]{}; for (SF_Job__c j : [SELECT Job_Id__c FROM SF_Job__c WHERE Job_Id__c != null]) { System.abortJob(j.Job_Id__c); jobs.add(new SF_Job__c(Id = j.Id, Job_Id__c = null)); } update jobs; } }
No comments:
Post a Comment