Apex-异步

Apex 异步(5)schedule

学习目标

完成这个单位后,你会知道:

  • 何时使用预定的Apex。
  • 如何监控计划的工作。
  • 计划的Apex语法。
  • 计划的方法最佳实践。

计划的Apex

Apex Scheduler让您延迟执行,以便您可以在指定的时间运行Apex类。对于使用Batch Apex的每日或每周维护任务来说,这是理想之选。要利用调度程序,编写一个实现Schedulable接口的Apex类,然后按照特定的调度安排它执行。

计划的Apex 语法

为了调用Apex类在特定时间运行,首先实现类的Schedulable接口。然后,使用System.schedule方法安排类的实例在特定时间运行。

global class SomeClass implements Schedulable {
    global void execute(SchedulableContext ctx) {
        // 真棒代码在这里
    }
}

该类实现了Schedulable接口,并且必须实现此接口包含的唯一方法,即execute方法。

这个方法的参数是一个SchedulableContext对象。在课程安排好之后,将创建一个CronTrigger对象来表示计划的作业。它提供了一个getTriggerId方法,该方法返回一个CronTrigger API对象的ID。

示例代码

这个类查询当前应该关闭的开放机会,并创建一个任务来提醒所有者更新机会。

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];
        // 为列表中的每个机会创建一个任务
        TaskUtils.remindOwners(opptys);
    }
    
}
您可以安排您的课程以编程方式或从Apex调度程序用户界面运行。

使用System.Schedule方法

在使用Schedulable接口实现类之后,使用System.Schedule方法执行它。 System.Schedule方法使用用户的时区作为所有调度的基础,但是以系统模式运行 – 所有类都被执行,无论用户是否有执行类的权限。

注意

如果您计划通过触发器安排课程,请特别小心。您必须能够保证触发器不会添加比限制更多的计划作业分类。特别是,考虑API批量更新,导入向导,通过用户界面进行的大容量记录更改以及一次可以更新多个记录的所有情况。

System.Schedule方法有三个参数:作业的名称,用于表示作业计划运行的时间和日期的CRON表达式以及类的名称。

RemindOpptyOwners reminder = new RemindOpptyOwners();
// 秒分钟小时数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);
有关用于计划的CRON表达式的更多信息,请参阅Apex Scheduler中的“使用System.Schedule方法”部分。


从UI调度作业

您也可以使用用户界面安排课程。

  1. 从安装程序中,在快速查找框中输入Apex,然后选择 Apex Classes.
  2. 点击 Schedule Apex.
  3. 对于工作名称,请输入类似Daily Oppty Reminder的内容。
  4. 单击Apex类旁边的查找按钮,然后为搜索项输入*以获取所有可以调度的类的列表。在搜索结果中,单击您的计划课程的名称。
  5. 为频率选择每周或每月,并设置所需的频率。
  6. 选择开始和结束日期,以及首选开始时间。
  7. 点击 Save.

测试计划的 Apex

就像我们到目前为止所介绍的其他异步方法一样,对于Scheduled Apex,您还必须确保计划的作业在测试结果之前完成。为此,请在System.schedule方法周围再次使用startTest和stopTest,以确保在继续测试之前完成处理。

@isTest
private class RemindOppyOwnersTest {

    // CRON表情:3月15日午夜。
    // 因为这是一个测试,所以在Test.stopTest()之后立即执行作业。
    public static String CRON_EXP = '0 0 0 15 3 ? 2022';

    static testmethod void testScheduledJob() {

        // 创建一些过时的机会记录
        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;
        
        // 获取我们刚刚插入的机会的ID
        Map<Id, Opportunity> opptyMap = new Map<Id, Opportunity>(opptys);
        List<Id> opptyIds = new List<Id>(opptyMap.keySet());

        Test.startTest();
        // 安排测试工作
        String jobId = System.schedule('ScheduledApexTest',
            CRON_EXP, 
            new RemindOpptyOwners());         
        // 验证计划作业尚未运行。
        List<Task> lt = [SELECT Id 
            FROM Task 
            WHERE WhatId IN :opptyIds];
        System.assertEquals(0, lt.size(), 'Tasks exist before job has run');
        // 停止测试将同步运行作业
        Test.stopTest();
        
        // 现在计划的作业已经执行,
        // 检查我们的任务是否被创建
        lt = [SELECT Id 
            FROM Task 
            WHERE WhatId IN :opptyIds];
        System.assertEquals(opptyIds.size(), 
            lt.size(), 
            'Tasks were not created');

    }
}

要记住的事情

计划的Apex包含许多需要注意的项目(有关详细信息,请参阅参考资料部分中的Apex Scheduler),但一般情况下:
  • 一次只能有100个预定的Apex作业,每24小时有最多的预定Apex执行次数。有关详细信息,请参阅参考资料部分中的执行调控器和限制。
  • 如果您计划通过触发器安排课程,请特别小心。您必须能够保证触发器不会添加比限制更多的计划作业。
  • 计划的Apex不支持同步Web服务标注。为了能够进行标注,通过将标注放在用@future(callout = true)注释的方法中进行异步标注,并从预定的Apex中调用此方法。但是,如果预定的Apex执行批处理作业,则批处理类将支持标注。

你可能也会喜欢...