ããã«ã¡ã¯ããªããã¾ã§ãã
ãã®ããã°ã¯Salesforce Platform Advent Calendar 2017ã®15æ¥ç®ã®æ稿ã«ãªãã¾ãã
Â
æè¿ååããâããªã¬ããå¼ã³åºããfutureã¡ã½ãããã¨ã©ã¼(UNABLE_TO_LOCK_ROW)ã«ãªãã®ã§ãQueueableã使ã£ã¦ã¿ãã¨ããã¨ã©ã¼ã解æ¶ãããã®ã ããæããã¦ãã®ä½¿ãæ¹ã§è¯ãã®ãï¼ï¼âã¨ããç¸è«ãåãã¾ãããç§èªèº«Queueableãå©ç¨ãããã¨ããªãã£ãã®ã§ãæ´çãã¦ã¿ããã¨æãã¾ãã
â»futureãQueueableã¯éåæå¦çã®ãã¨ã§ãã
Â
ã¡ãªã¿ã«Salesforceã«ã¯Trailheadã¨ãããªã³ã©ã¤ã³ã§å©ç¨ã§ããå¦ç¿ææãããã¾ããTrailheadããåç¥ã®æ¹ã§ãããããã¡ãã®ã¢ã¸ã¥ã¼ã«ã«ãã£ã¬ã³ã¸ããã¨ããç解ã§ããã¨æãã¾ãã
åè) ãªãã¡ã¬ã³ã¹:éåæApex
Â
ã¯ããã«
Salesforceã§éçºããã«ã¯åºæ¥ãã ãå¦çã«è² è·ãããããªãã³ã¼ããæ¸ãå¿ è¦ãããã¾ããã©ã®ç¨åº¦ã¾ã§OKãªã®ãã¯ãWebãµã¤ãã«ã¾ã¨ã¾ã£ã¦ããã®ã§éçºè ã¯å¸¸ã«æèãã¾ããããã¡ãªã¿ã«å¦çä¸ã«ã¬ãããè¶ããã¨ã¨ã©ã¼ãçºçãã¦å¦çãä¸æãã¦ãã¾ãã¾ããæãã§ãããè² è·ããããªãããã«ãéåæã§å®è¡ã§ããæ§ã ãªæ¹æ³ãããã¾ããï¼ã¤ãã¤ã¿ã¦ããã¾ãããã
åè)Apex ã¬ããå¶é
Â
Salesforceã§å©ç¨ã§ããéåææ©è½
ç¾æç¹ã§ã¯ã以ä¸ã®ï¼ã¤ã®æ©è½ãæä¾ããã¦ãã¾ãã
- @futureã¡ã½ãã
- Queuable (Winter'15ã)
- Apex Batch
- Scheduled
Â
@futureã¡ã½ãã
ã¨ããå¦çãéåæã§å¼ã¶æã«å©ç¨ãã¾ããä»ã¾ã§Salesforceéçºããã¦ãã¾ããããå©ç¨æ©ä¼ã¯ããã¾ã§å¤ãããã¾ãããæ¨æºã®ãã©ã³ã¶ã¯ã·ã§ã³ã§ã©ããã¦ãå¦çãã§ããªãå ´åã«å©ç¨ãã¾ãã
global class FutureMethodRecordProcessing {
ãã// ï¼ï¼ã¡ã½ããã«ã¢ããã¼ã·ã§ã³@futureãã¤ãããæ»ãå¤ã¯void @future
ãã// ï¼ï¼å¼æ°ã¯ããªããã£ããªå¤æ°ã®ã¿ public static void processRecords(List<ID> recordIds) { // Get those records based on the IDs List<Account> accts = [SELECT Name FROM Account WHERE Id IN :recordIds]; // Process records } }
Â
ï¼ã±ã¼ã¹ï¼ï¼DMLæä½ã§åæã«å¦çã§ããªããªãã¸ã§ã¯ãã®æ´æ°ï¼
Salesforceã§ã¯DMLå¦çã§åä¸ã«å¦çã§ããªããªãã¸ã§ã¯ããããã¾ããä¾ãã°ãåå¼å 責任è (Contact)ã¨ã¦ã¼ã¶(User)ãåæã«ä½æãããã¨ããã¨ã¨ã©ã¼ãçºçãã¾ãããã®å ´åã«åå¼å 責任è (Contact)ã¯ç¾ç¶ã®ãã©ã³ã¶ã¯ã·ã§ã³ã§å¦çãããæåããã@futureã¡ã½ããå ã§å¦çããããã«ãã¾ãã
åè)DML æä½ã§åæã«ä½¿ç¨ã§ããªã sObjectÂ
â»éåæå¦çã«ãã¦ãã¾ãã¨ãå¼ã°ããå ã§ã¨ã©ã¼ã«ãªã£ãå ´åã®ãã³ããªã³ã°ãé¢åã«ãªãã®ã§ããã®è¾ºãããã£ããè¨è¨ããä¸ã§å®è£ ãã¾ããããã
Â
ï¼ã±ã¼ã¹ï¼ï¼ããªã¬ãå¼ã°ããå ´åã«ã³ã¼ã«ã¢ã¦ãï¼
ãªãã¸ã§ã¯ãã®ããªã¬ããã¼ã«ã³ã¼ã«ã¢ã¦ãããããã±ã¼ã¹ã®å ´åãããããã¾ããSalesforceã®ä¸ã§ã¯ããªã¬å¦çå ã§ã³ã¼ã«ã¢ã¦ããããã¨ã¨ã©ã¼ãçºçãã¾ããããªã¬å ã§å¤é¨ã³ã¼ã«ã¢ã¦ããããããã«ã¯ãã³ã¼ã«ã¢ã¦ãOKãªéåæã¡ã½ãããå¼ã³åºãå¿ è¦ãããã¾ãã
@future(callout=true)
Â
ã¡ãªã¿ã«ãã³ã¼ã«ã¢ã¦ãã®é »åº¦ãå°ãªãå ´åï¼éç¨ä¸ããã¾ã§å¤§éã¬ã³ã¼ãã®æ´æ°ããªãããããå¤æ´ãããå ´åã®ã¿ï¼ã¯ãã¢ã¦ããã¦ã³ãã¡ãã»ã¼ã¸ã¨ããä»çµã¿ãããã¾ãããã¡ã㯠UIä¸ã§è¨å®ãã§ããããã«ãªã£ã¦ã¾ããããªã¬ã¨éã£ã¦éä¿¡ããå¤ã®å å·¥ãã§ããªãã®ã§ããããã¼ã¿åãåãæå´ã§é å¼µããã®ã§ããã°ããã¡ãã®æ¹æ³ã使ãã¾ããã
âã¯ã¼ã¯ããã¼ã使ç¨ããã³ã¼ã«ã¢ã¦ãã®ããããåèã«
åè)ãªãã¡ã¬ã³ã¹:ã¢ã¦ããã¦ã³ãã¡ãã»ã¼ã¸ã«ã¤ãã¦
Â
ï¼ã±ã¼ã¹ï¼ï¼ã¬ããã®å£ãè¶ ãã¦ãã¾ã£ãï¼
 ããã¤ãã®é ç®ã¯éåæã¨ãã¦å¼ã¶ãã¨ã§ãã¬ãããç·©åããã¾ãã
- çºè¡ããã SOQL ã¯ã¨ãªã®åè¨æ°ã100â200
- ãã¼ãã®åè¨ãµã¤ãºã6 MBâ12 MB
- Salesforce ãµã¼ãã®æ大 CPU æéã10,000 ããªç§â60,000 ããªç§
ã¬ãããç·©åãããã®ã¯å¬ããã®ã§ãããä¿å®ãç¶ãã¦ãããã¡ã«ã¾ãã¬ããã®å£ãè¶ãããã¨ãããã¾ãããããã§æ¢åã®futureã¡ã½ããå¦çãåå²ãã¦ãfutureã¡ã½ãããå¼ã³ç¶ããã¨ãã¾ãããæ°ããã¾ããããåããã¦ã¿ãã¨ã¨ã©ã¼ã«ãªã£ã¦ãã¾ãã¾ããfutureã¡ã½ããããfutureã¡ã½ãããå¼ã¶ãã¨ã¯ã§ããªãã®ã§ãããã©ãããæ°ããã¾ããããã®è¾ºãã次ã«ç´¹ä»ããQueuableã§è§£æ¶ããã¾ãã
Â
ï¼futureã®å¶éï¼
ã»ï¼ãã©ã³ã¶ã¯ã·ã§ã³ã§å¼ã¹ãã®ã¯ï¼ï¼åã¾ã§ï¼ããªã¬å ã§ï¼ã¬ã³ã¼ãã«ã¤ãï¼ã³ã¼ã«ããã¨ã¬ããã¨ã©ã¼ã«ãªãããã¾ã¨ãã¦ï¼ã³ã¼ã«ã§æ¸ãããã«å®è£ ãã¾ãããï¼
ã»futureããfutureã®å¼ã³åºãNG
ã»ç·©åãããã¬ãããããã
ã»ã¡ã½ããã®å¼æ°ã¯ããªããã£ããªå¤æ°ã®ã¿ï¼sObjectã渡ããã¨ã¯ã§ããªãããã§ãããªãã§ãéåæå¦çã®ãããå¦çãããéã«ãªãã¸ã§ã¯ãã®æ å ±ãå¤ãã£ã¦ãã¾ããã¨ãæ³å®ãã¦ããããã§ããã¸ã¼ãï¼
ã»è¤æ°ã®futureã¡ã½ãããåæã«å®è¡ãããå¯è½æ§ãããï¼ã¬ã³ã¼ãã®ããã¯ã«æ³¨æï¼
ã»æ»ãå¤ã¯void
ã»ããªã¬ã§ã¯æ£å¸¸çµäºããªãã¨futureã¡ã½ãããå¼ã°ããªã
åè) help:ããªã¬å ãã@futureã¡ã½ãããå®è¡ããéã®åä½ã«ã¤ãã¦
Â
Queuable
ã¨ããéåæå¦çãå¼ã¶ãã¨ãã§ãã¾ããã¸ã§ãIDãè¿å´ãããã®ã§ç»é¢ä¸ã§ç£è¦ãã§ãã¾ããããã«QueuableããQueuableãå¼ã¶ãã¨ãã§ãã¾ããfutureãããéããå¦çãå¶éã®ããå¦çãä½ãããå ´åã«ä½¿ãã¾ãã
public class AsyncExecutionExample implements Queueable {
// ï¼ï¼âQueueableã¤ã³ã¿ã¼ãã§ã¼ã¹
ãã// ï¼ï¼voidåã
public void execute(QueueableContext context) { Account a = new Account(Name='Acme',Phone='(415) 555-1212'); insert a; } }
// å¼ã³åºãæ¹ï¼å¼æ°ãããå ´åã¯ãã¯ã©ã¹çææã«ãã©ã¡ã¼ã¿ã¨ãã¦æ¸¡ãããããï¼
ID jobID = System.enqueueJob(new AsyncExecutionExample());
Â
ï¼ã±ã¼ã¹ï¼ï¼éåæå¦çãçµãã£ãããå¥ã®éåæå¦çãå¼ã¶ï¼
futureã¡ã½ããã§ã¯å®ç¾ã§ããªãã£ããéåæå¦çããéåæå¦çãå¼ã¶ãã¨ãã§ãã¾ãããã©ã³ã¶ã¯ã·ã§ã³ã¯åããããã®ã®ãå¦çãéããã®ãå¤é¨ã³ã¼ã«ã¢ã¦ããããããå¦çæéãããããããªãã®ããå¦çåå²ãã¦ããé ã«èµ·åãããã¨ãã§ãã¾ãã
Â
ï¼ã±ã¼ã¹ï¼ï¼sObjectã®æ å ±ãQueuableã«æ¸¡ãã¦å¦çããï¼
futureã¡ã½ããã®å ´åã¯ããªããã£ããªå¤æ°ã®ã¿ã§ããããQueuableã§ã¯éããªããã£ãå¤æ°ã®åã渡ããå¯è½ã§ããè¨ç®éä¸ã®ãªãã¸ã§ã¯ãã次ã®éåæå¦çã«å¼ã渡ããã¨ãã¨ãã§ãããã§ããã
Â
ï¼Queuableã®å¶éï¼Â
ã»ï¼ãã©ã³ã¶ã¯ã·ã§ã³ã§å¼ã¹ãã®ã¯ï¼ï¼åã¾ã§ï¼futureã¨åãï¼
ã»Queuableã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®è£ ããÂ
åè)ãªãã¡ã¬ã³ã¹:Queueable ApexÂ
Â
Apex Batch
ã¿ããªå¤§å¥½ãApex Batchã§ããSalesforceã®ä¸ã§å¤§éãã¼ã¿ã®å¦çãããå ´åã¯ãééããªãå©ç¨ãã¾ãã対象ã¨ãªããªãã¸ã§ã¯ãã®ã¯ã¨ãªãå®ç¾©ãããã®ã¯ã¨ãªã200è¡ãã¤executeã®ã¡ã½ããã¨ãã¦å¼ã°ããæå¾ã¯finishã¡ã½ãããå¼ã°ãã¦å¦çãçµããã¾ãã
ãããã¯ç»é¢ãããã¿ã³ãæ¼ããã¿ã¤ãã³ã°ã§èµ·åããããå¤éãããã¨ãã¦ã¹ã±ã¸ã¥ã¼ã«ã¯ã©ã¹ããèµ·åããããã¾ããÂ
global class SearchAndReplace implements Database.Batchable<sObject>{ // ï¼ï¼ãããç¨ã¤ã³ã¿ã¼ãã§ã¼ã¹ã global final String Query; global final String Entity; global final String Field; global final String Value; global SearchAndReplace(String q, String e, String f, String v){ Query=q; Entity=e; Field=f;Value=v; } ã // ï¼ï¼ãããéå§æã«å¼ã°ããã¡ã½ããï¼å¤æ°æ´çãããï¼ global Database.QueryLocator start(Database.BatchableContext BC){ return Database.getQueryLocator(query); } ã // ï¼ï¼ããããµã¤ãºåä½ã§ã³ã¼ã«ããããstartã¡ã½ããã®æ»ãå¤ãã«å¼æ°ã«ãã¾ã global void execute(Database.BatchableContext BC, List<sObject> scope){ for(sobject s : scope){ s.put(Field,Value); } update scope; } ã // ï¼ï¼ãããçµäºæã«ã³ã¼ã«ãããããã°ãæ¸ãè¾¼ãã ãã¡ã¼ã«éä¿¡ããããã global void finish(Database.BatchableContext BC){ } } // ãããç»é²ã第ï¼å¼æ°ã«ã¯ããããµã¤ãºãæå®ã§ãã¾ã ID batchprocessid = Database.executeBatch(SearchAndReplace,200);
Â
Â
ï¼ã±ã¼ã¹ï¼ï¼å¤§éãã¼ã¿ã®ã¢ãããã¼ãï¼
ï¼åã®ãã©ã³ã¶ã¯ã·ã§ã³ã§ã¯ã¬ããå¶éã«ãªããããªä»¶æ°ãéãå¦çãApex Batchã¨ãã¦åå²ãã¦å¦çã§ãã¾ãããããå¦çã«ãã£ã¦ã¯å¦ççµäºæã«å®äºã¡ã¼ã«ãéä¿¡ããããã¨ã©ã¼æ å ±ãã«ã¹ã¿ã ãªãã¸ã§ã¯ãã«æ¸ãè¾¼ãã ããã¾ãã
Â
ï¼Apex Batchã®å¶éï¼
ã»å¯¾è±¡ã¨ãªãã®ã¯500ä¸ã¬ã³ã¼ã
ã»startãexecuteãfinishã§ï¼ï¼åãã¤ã³ã¼ã«ã¢ã¦ãã§ãã
ã»ããããµã¤ãºï¼ããã©ã«ã200ï¼ã¯
Â
åè) help: Batch Apex (Apex ã®ä¸æ¬å¦ç) ã®å¶é
åè) Apex BatchãApex Batchã®ä¸æ¬å¦çã®ä½¿ç¨
Â
Scheduled
ç¹å®ã®æéã«èµ·åããå¦çãæ¸ããã¨ã§ãã¾ããã ããããApex Batchãå¼ã³åºãå¦çã«ä½¿ããã¾ãããããå¦çãå¿ è¦ãªãå ´åã¯ãã¹ã±ã¸ã¥ã¼ã«ã¯ã©ã¹ã«å¦çãã¸ãã¯ãæ¸ããã¨ãããã¾ãã
ã¹ã±ã¸ã¥ã¼ã«ã®ç»é²ã¯ç»é¢ä¸ãããã§ãã¾ãããååä½ã®è¨å®ãã§ãã¾ãããç´°ããè¨å®ãããå ´åã¯ãéçºè ã³ã³ã½ã¼ã«ããã¹ã±ã¸ã¥ã¼ã«ç»é²å¦çãå¼ã¶ãã¨ã§ååä½ã®æå®ãã§ããããã«ãªãã¾ãããã ããç»é²ãããã¹ã±ã¸ã¥ã¼ã«ã¯ã©ã¹ãæééãã«å®è¡ãããã¨ã¯éãããè² è·ã®ããã£ãç¶æ ã ã¨å°ãé ãã¦å®è¡ããããã¨ãããã¾ããã
Â
global class scheduledMerge implements Schedulable {
// ï¼ï¼ã¹ã±ã¸ã¥ã¼ã«ã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®è£ â global void execute(SchedulableContext SC) {
mergeNumbers M = new mergeNumbers(); } }
åè) Apex Scheduled
Â
ã¾ã¨ãÂ
ä»æ¥ã¯è²ã ãªéåæå¦çã調ã¹ã¦ã¿ã¾ãããQueuableã«ã¤ãã¦ã¯ãéåæå¦çããéåæå¦çãå¼ã¶ã±ã¼ã¹ã®å ´åã«ä½¿ã£ã¦ã¿ããã¨æãã¾ããéåæå¦çãä½ãå ´åã¯ä¾å¤ãçºçããã±ã¼ã¹ãæ³å®ãã¦ãªã«ããªã§ããããã«ãã¦ããã¾ããããã
future | ã¡ãã£ã¨ããéåæç¨ |
---|---|
Quauable | éåæå¦çããéåæå¦çãå¼ã¶ã±ã¼ã¹ |
Apex Batch | 大éã¬ã³ã¼ãã®å¦ç |
Schedule | ã¹ã±ã¸ã¥ã¼ã«ããæ¥æã§èµ·åããã |
â»ååãã質åãåããå 容ã ã¨ãQueuableã§ããã¯ã¨ã©ã¼ãçºçããªãã®ã¯å¶ç¶ãªæ°ããã¦ãã¾ãããæå ã«ç°å¢ããªãã®ã§ãªãã¨ãã§ããã
Â
ä»åã¯ç´¹ä»ãã¾ããã§ãããããã©ãããã©ã¼ã ã¤ãã³ãã¨ããã¤ãã³ãé§åãªãä»çµã¿ãããã®ã§æ°ã«ãªãæ¹ã¯ãã¡ããè¦ã¦ããã ããã¨è¯ãããã
Â
Â
ããã§ã¯ãã¿ãªãã¾ç´ æµãªSalesforceã©ã¤ããï¼