' P '

whatever I will forget

スケジュール済み Apex

スケジュール済み Apexとは

  • Apex スケジューラーを使用すると、Apex クラスの実行を遅らせて、指定した日時に実行できる
  • スケジューラーは、Apex 一括処理を使用した日次または週次のメンテナンス作業に最適
  • スケジュール済み Apex ジョブは一度に 100 件しか設定できず、スケジュール済み Apex の 24 時間あたりの最大実行数も制限されている
  • 同期 Web サービスコールアウトは、スケジュールされた Apex からは実行できない
  • コールアウトを実行するには、@future(callout=true) のアノテーションを付加したメソッドにコールアウトを配置し、このメソッドをスケジュールされた Apex からコールすることで非同期コールアウトを実行する
  • スケジュールされた Apex で一括処理ジョブを実行する場合、一括処理クラスからコールアウトを実行できる

構文

  • クラスにSchedulableインターフェースを実装する
  • System.scheduleメソッドを使用して特定の時間に実行されるようにクラスのインスタンスをスケジュールする
  • メソッドのパラメータは SchedulableContext オブジェクト
  • クラスがスケジュールされると、スケジュール済みジョブを表す CronTrigger オブジェクトが作成される
    • CronTriggerオブジェクトには、CronTrigger API オブジェクトの ID を返す getTriggerId メソッドが存在する
global class SomeClass implements Schedulable {
    global void execute(SchedulableContext ctx) {
        // awesome code here
    }
}

サンプルコード

  • Apex スケジューラー UI またはプログラムからcallが可能
global class RemindOpptyOwners implements Schedulable {
    global void execute(SchedulableContext ctx) {
        List<Opportunity> opptys = [SELECT Id, Name, OwnerId, CloseDate
            FROM Opportunity
            WHERE IsClosed = False AND
            CloseDate < TODAY];
        // Create a task for each opportunity in the list
        TaskUtils.remindOwners(opptys);
    }
}

System.Schedule メソッドの使用

  • ユーザーにクラスの実行権限があるかどうかにかかわらず、すべてのクラスが実行される
RemindOpptyOwners reminder = new RemindOpptyOwners();
// Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
String sch = '20 30 8 10 2 ?';
String jobID = System.schedule('Remind Opp Owners', sch, reminder);

UI からのジョブのスケジュール

  • UIを使用してクラスをスケジュールすることも可能
    • [設定] →[Apex クラス]
    • [Apex をスケジュール] をクリック
    • ジョブ名に「Daily Oppty Reminder」などと入力
    • Apex クラスの横にあるルックアップボタンをクリックし、検索語に「*」と入力して、スケジュール可能なすべてのクラスのリストを取得
    • 検索結果で、スケジュール済みクラスの名前をクリック
    • [毎週] または [毎月] の頻度を選択して、必要な頻度を設定
    • 開始日と終了日、適切な開始時刻を選択
    • [保存] をクリック

サンプルテストクラス

  • System.schedule メソッドの前後に startTeststopTest を再度使用して、テストを続行する前に処理が終了するようにする
@isTest
private class RemindOppyOwnersTest {
    // Dummy CRON expression: midnight on March 15.
    // Because this is a test, job executes
    // immediately after Test.stopTest().
    public static String CRON_EXP = '0 0 0 15 3 ? 2022';
    static testmethod void testScheduledJob() {
        // Create some out of date Opportunity records
        List<Opportunity> opptys = new List<Opportunity>();
        Date closeDate = Date.today().addDays(-7);
        for (Integer i=0; i<10; i++) {
            Opportunity o = new Opportunity(
                Name = 'Opportunity ' + i,
                CloseDate = closeDate,
                StageName = 'Prospecting'
            );
            opptys.add(o);
        }
        insert opptys;
        // Get the IDs of the opportunities we just inserted
        Map<Id, Opportunity> opptyMap = new Map<Id, Opportunity>(opptys);
        List<Id> opptyIds = new List<Id>(opptyMap.keySet());
        Test.startTest();
        // Schedule the test job
        String jobId = System.schedule('ScheduledApexTest',
            CRON_EXP,
            new RemindOpptyOwners());
        // Verify the scheduled job has not run yet.
        List<Task> lt = [SELECT Id
            FROM Task
            WHERE WhatId IN :opptyIds];
        System.assertEquals(0, lt.size(), 'Tasks exist before job has run');
        // Stopping the test will run the job synchronously
        Test.stopTest();
        // Now that the scheduled job has executed,
        // check that our tasks were created
        lt = [SELECT Id
            FROM Task
            WHERE WhatId IN :opptyIds];
        System.assertEquals(opptyIds.size(),
            lt.size(),
            'Tasks were not created');
    }
}