Upload
salesforce-developers
View
1.047
Download
8
Embed Size (px)
Citation preview
Advanced Apex – Asynchronous ProcessesMarch 29th 2016
#forcewebinar
Statement under the Private Securities Litigation Reform Act of 1995:
This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-looking statements we make. All statements other than statements of historical fact could be deemed forward-looking, including any projections of product or service availability, subscriber growth, earnings, revenues, or other financial items and any statements regarding strategies or plans of management for future operations, statements of belief, any statements concerning new, planned, or upgraded services or technology developments and customer contracts or use of our services.
The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality for our service, new products and services, our new business model, our past operating losses, possible fluctuations in our operating results and rate of growth, interruptions or delays in our Web hosting, breach of our security measures, the outcome of any litigation, risks associated with completed and any possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our ability to expand, retain, and motivate our employees and manage our growth, new releases of our service and successful customer deployment, our limited history reselling non-salesforce.com products, and utilization and selling to larger enterprise customers. Further information on potential factors that could affect the financial results of salesforce.com, inc. is included in our annual report on Form 10-K for the most recent fiscal year and in our quarterly report on Form 10-Q for the most recent fiscal quarter. These documents and others containing important disclosures are available on the SEC Filings section of the Investor Information section of our Web site.
Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently available and may not be delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently available. Salesforce.com, inc. assumes no obligation and does not intend to update these forward-looking statements.
Forward-Looking Statement
#forcewebinar
Speakers
MJ KahnVice President,OpFocus, Inc.
Kartik ViswanadhaDirector, OpFocusSalesforce MVP
@logontokartik
#forcewebinar
Go Social!
@salesforcedevs / #forcewebinar
Salesforce Developers
Salesforce Developers
Salesforce Developers
This webinar is being recorded! The video will be posted to YouTube and thewebinar recap page (same URL as registration).
#forcewebinar
Agenda• What is Asynchronous Process?• Why we need it?• Types of Asynchronous Processes in Salesforce• Usage and Examples• Comparison of various Asynchronous Processes• Appendix• Recap
#forcewebinar
Pre-requisites• Good understanding of Apex Programming on Salesforce• Passion to learn the platform
The WHAT
#forcewebinar
Asynchronous Process - Definition
• In computer programs, asynchronous operation means that a process operates independently of other processes
#forcewebinar
Asynchronous vs Synchronous
Synchronous
• Quick and Immediate Actions
• Transactions are immediate and serial
• Normal governor limits
Asynchronous
• Actions that will not
block the
transaction pr
process
• Duration is not a
Priority
• Higher governor
limits
#forcewebinar
Asynchronous Process – Force.com • Ensure fairness of
processing• Ensure
transactional capabilities
#forcewebinar
Queue Based Framework
#forcewebinar
Concepts
#forcewebinar
Multi tenant Fair Share Handling - Delay
#forcewebinar
Multi tenant Fair Share Handling - Delay
#forcewebinar
Multi tenant Fair Share Handling – Extended Delay
All the rquests from Org 1 are moved back with an Extended Delay
#forcewebinar
The WHY
#forcewebinar
Benefits
• User Efficiency
• Resource Efficiency
• Scalability
#forcewebinar
Why Asynchronous Processes in Salesforce
• Avoid Governor Limits
• Mixed DML Operations
• Long Running User Operations
#forcewebinar
Use Cases
• Send Data to an External System on a Insert or Update
• Complex Calculations or Analysis based on Data in Salesforce
• Report Runs
• Callouts to External Systems
#forcewebinar
Use Case – Large Data Processing
#forcewebinar
Use Case – Logic on Millions of Rows
• Supports complex logic on very large datasets
• Scalable, robust, asynchronous execution platform
• Scheduled or programmatically executed
• Eliminate ‘data processing’ integrations
• Data cleansing, augmentation • Automated batch process
#forcewebinar
The HOW
#forcewebinar
Types of Asynchronous Processes in Apex
• @future
• Queueable
• Batch Apex
• Schedulable
• Continuation
#forcewebinar
Scenario
• Goal: Populate Account’s Billing Longitude/Latitude based on Billing Address
• Assume we have a method that calls out to a web service and returns the lon/lat for a given Account, in the Geocoding Utils class
public static LonLat geocodeAccount(Account acct) { … }
LonLat is a class with 2 Double properties.
• Solution: Write a trigger that calls this method.
• Problem: You can’t call out to a web service from a trigger.
#forcewebinar
@future
• A public static method, decorated with @future• Arguments:
• Primitives (Integer, String, etc.) • Collections of primitives (List, Map, Set)• NOT Sobjects or Apex objects• You can use JSON.serialize() and pass in a String
• Returns void
@future
public class GeocodingUtils {
@future (callout=true) public static void geocodeAccountFuture(Id accountId) {
Account acct = [select Id, BillingStreet, BillingCity, BillingState, BillingPostalCode, BillingCountry from Account where Id = :accountId];
LonLat coordinates = geocodeAccount(acct);
if (coordinates != null) {acct.BillingLongitude = coordinates.lon;acct.BillingLatitude = coordinates.lat;update acct;
}}
}
@future – Account trigger
trigger Account on Account (before insert, before update) {
if (Trigger.isBefore && (Trigger.isInsert || Trigger.isUpdate)) {// For each new Account or each existing Account whose Address has changed, geocode it
for (Account acct : Trigger.new) {if (Trigger.isInsert || (Trigger.isUpdate && GeocodingUtils.addressChanged(acct, Trigger.oldMap.get(acct.Id)))) {
// Geocode the Account's address
GeocodingUtils.geocodeAccountFuture(acct.Id);}
} }
}
#forcewebinar
Queueable Class
• A public class that implements the Queueable interface• Includes an execute method that accepts only a QueueableContext
parameter• The execute method can access instance properties for the
class• Returns void• Launch by calling System.enqueueJob(cls) with an instance of the
class.• Returns an AsyncApexJob Id
Queueable Apex
public class GeocodingQueueable implements Queueable, Database.AllowsCallouts {public Account[] lstAccounts = new Account[]{};
public void execute(QueueableContext ctx) {// Process as many Accounts as we canAccount[] lstProcessed = new Account[]{};Integer numProcessed;for (numProcessed=0;
numProcessed < Limits.getLimitCallouts() && numProcessed<lstAccounts.size(); numProcessed++) {Account acctGeo = lstAccounts[numProcessed];
GeocodingUtils.LonLat coordinates = GeocodingUtils.geocodeAccount(acctGeo);if (coordinates != null) {
acctGeo.BillingLongitude = coordinates.lon;acctGeo.BillingLatitude = coordinates.lat;lstProcessed.add(acctGeo);
}}
Queueable Apex
…update lstProcessed;
// Remove the ones we just processed from the list.for (Integer i=0; i<numProcessed; i++) {
lstAccounts.remove(0);}
// If there are any remaining Accounts, chain a new Async job to process them.// NOTE: As of Spring 16, a chained Queueable job cannot do a callout, so the next// run of this execute() method will fail!if (!lstAccounts.isEmpty()) {
Id jobID = System.enqueueJob(this);}
}}
Queueable Apex– Account trigger
trigger Account on Account (before insert, before update) {if (Trigger.isBefore && (Trigger.isInsert || Trigger.isUpdate)) {
Account[] lstAccounts = new Account[]{};for (Account acct : Trigger.new) {
if (Trigger.isInsert || (Trigger.isUpdate && GeocodingUtils.addressChanged(acct, Trigger.oldMap.get(acct.Id)))) { Account acctGeo = new Account(Id=acct.Id); acctGeo.BillingStreet = acct.BillingStreet; acctGeo.BillingCity = acct.BillingCity;
acctGeo.BillingState = acct.BillingState; acctGeo.BillingPostalCode = acct.BillingPostalCode; acctGeo.BillingCountry = acct.BillingCountry; lstAccounts.add(acctGeo);}
}
if (!lstAccounts.isEmpty()) { // Geocode the Account's addressGeocodingQueueable cls = new GeocodingQueueable();cls.lstAccounts = lstAccounts;Id jobID = System.enqueueJob(cls);}
}}
#forcewebinar
Batchable Class
• A global class that implements the Database.Batchable interface• Includes:
• Start method – identifies the scope (list of data to be processed)• Execute method – processes a subset of the scoped records• Finish method – does any post-job wrap-up
• Additional interfaces:• Database.Stateful • Database.AllowCallouts
#forcewebinar
Batchable Class
• Launch by callling Database.executeBatch(cls) with an instance of the class and an optional scope size• Default scope size is 200• Returns an AsyncApexJobId
Batch Apex
global class GeocodingBatch implements Database.Batchable<SObject>, Database.AllowsCallouts, Database.Stateful {
global Integer numberOfAccountsUpdated = 0;
// Start method gets all Accounts that need to be geocodedglobal Database.QueryLocator start(Database.BatchableContext bc) {
String query = 'select id from Account where Need_to_Geocode__c = true';return Database.getQueryLocator(query);
}
Batch Apex
global void execute(Database.BatchableContext bc, List<SObject> lstSObjects) {// Get the AccountsAccount[] lstAccounts = [select Id, BillingStreet, BillingCity, BillingState, BillingPostalCode, BillingCountry from Account where Id in :lstSObjects];
for (Account acct : lstAccounts) {// Geocode the Account and save the resultsGeocodingUtils.LonLat coordinates = GeocodingUtils.geocodeAccount(acct);if (coordinates != null) {
acct.BillingLongitude = coordinates.lon;acct.BillingLatitude = coordinates.lat;
}acct.Need_to_Geocode__c = false;
}
update lstAccounts;numberOfAccountsUpdated += lstAccounts.size();
}
Batch Apex
global void finish(Database.BatchableContext bc) {// Send an email to let someone know how many Accounts we updatedSystem.debug('Number of Accounts updated: ' + numberOfAccountsUpdated);
}
} // End of class
Batchble Apex– Account trigger
trigger Account on Account (before insert, before update) {
if (Trigger.isBefore && (Trigger.isInsert || Trigger.isUpdate)) {// For each new Account or each existing Account whose Address has changed, // flag it to be geocoded laterfor (Account acct : Trigger.new) {
if (Trigger.isInsert || (Trigger.isUpdate && GeocodingUtils.addressChanged(acct, Trigger.oldMap.get(acct.Id)))) { acct.Need_to_Geocode__c = true;}
} }
}
#forcewebinar
Schedulable Class
• A global class that implements the Schedulable interface• Includes an execute method
Schedulable Apex
global class GeocodingSchedulable {
global void execute(SchedulableContext ctx) {
GeocodingBatch cls = new GeocodingBatch();
Integer batchSize = (Limits.getLimitCallouts() < 200) ? Limits.getLimitCallouts() : 200;
Id jobId = Database.executeBatch(cls, batchSize);}
}
#forcewebinar
Schedulable Class
• Schedule by calling System.Schedule(‘job name’, cron expression, cls)
• Job Name is found in AsyncApexJob object• Cron expression can be complex
• Returns an AsyncApexJob Id
#forcewebinar
Schedulable Class
• Cron expression string
seconds minutes hours day_of_month month day_of_week optional_year
• Run at 30 minutes past midnight on Jan 1 every yearGeocodingSchedulable cls = new GeocodingSchedulable();
System.Schedule('Geocode on Jan 1', '0 30 0 1 1 ? *', cls);
• Run every hourGeocodingSchedulable cls = new GeocodingSchedulable();
System.Schedule('Geocode on Jan 1', '0 0 * * * ? *', cls);
• Check the Apex Language Reference for details
#forcewebinar
Summary of Techniques
• @future – static method, simple arguments, no monitoring, no chaining
• Queueable – class with instance variables, can monitor, can chain (within limits)
• Batch Apex – class with instance variables, great for large numbers of records, can monitor
• Schedulable – class with instance variables, runs one or at specified times, can monitor
#forcewebinar
Monitoring Async Apex
• For Queueable and Batchable• When you launch the job, you get an AsyncApexJob Id• Setup | Monitoring | Apex Jobs• See doc for description of Status values
• For Schedulable• When you schedule the job, you get a CronTrigger Id• When it runs, it’s added to AsyncApexJobs• Setup | Monitoring | Scheduled Jobs
• Add a list view filter for Type = Scheduled Apex
#forcewebinar
Testing Async Apex
• Before launching the job, do Test.startTest()• After launching the job, do Test.stopTest()• One instance of the job will run before Test.stopTest() returns
#forcewebinar
Recap
• Asynchronous Processes • Salesforce Async Model & Framework• Advantages of using Async processes• Use Cases• Types of Async Processes• Comparison & Monitoring
#forcewebinar
Resources
• https://developer.salesforce.com/page/Loading_Large_Data_Sets_with_the_Force.com_Bulk_API
• https://developer.salesforce.com/page/Asynchronous_Processing_in_Force_com
• https://developer.salesforce.com/blogs/engineering/2014/05/flex-batch-apex-muscles-flexqueue.html
#forcewebinar
#forcewebinar
Deploying Your Code
#forcewebinar
Deploying Your Code
#forcewebinar
Deploying Your Code
Got Questions?developer.salesforce.com/forums/
Q&AYour feedback is crucial to the successof our webinar programs. Thank you!
Thank YouTry Trailhead: trailhead.salesforce.comJoin the conversation: @salesforcedevs