

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 设备和任务
<a name="jobs-devices"></a>

设备可以使用 MQTT、HTTP 签名版本 4 或 HTTP TLS 与AWS IoT任务通信。要确定您的设备与 AWS IoT Jobs 通信时要使用的终端节点，请运行**DescribeEndpoint**命令。例如，如果您运行此命令：

```
aws iot describe-endpoint --endpoint-type iot:Data-ATS
```

您会获得与以下内容相似的结果：

```
{
    "endpointAddress": "a1b2c3d4e5f6g7-ats.iot.us-west-2.amazonaws.com"
}
```

## 使用 MQTT 协议
<a name="jobs-using-mqtt"></a>

设备可以使用 MQTT 协议与AWS IoT任务通信。设备订阅 MQTT 主题是为了收到有关新任务的通知并接收来自AWS IoT任务服务的响应。设备在 MQTT 主题上发布以查询或更新任务启动的状态。每台设备都有自己的一般 MQTT 主题。有关发布和订阅 MQTT 主题的更多信息，请参阅 [设备通信协议](protocols.md)。

通过这种通信方式，您的设备使用其设备专用证书和私钥向 Jobs 进行AWS IoT身份验证。

您的设备可以订阅以下主题。`thing-name` 是与设备关联的事物名称。
+ 

**`$aws/things/thing-name/jobs/notify`**  
订阅此主题，以便在待处理任务启动列表中添加或删除任务启动时接收通知。
+ 

**`$aws/things/thing-name/jobs/notify-next`**  
订阅此主题，以在下一个待处理任务执行发生更改时通知您。
+ 

**`$aws/things/thing-name/jobs/request-name/accepted`**  
AWS IoT作业服务发布有关 MQTT 主题的成功和失败消息。通过将 `accepted` 或 `rejected` 追加到用于发出请求的主题来构成该主题。这里，`request-name`是请求的名称，例如`Get`，主题可以是：`$aws/things/myThing/jobs/get`。 AWS IoT然后，Jobs 会发布有关该`$aws/things/myThing/jobs/get/accepted`主题的成功消息。
+ 

**`$aws/things/thing-name/jobs/request-name/rejected`**  
此处，`request-name` 是请求的名称，例如 `Get`。如果请求失败，AWS IoTJobs 将发布有关该`$aws/things/myThing/jobs/get/rejected`主题的失败消息。

您还可以使用以下 HTTPS API 操作：
+ 通过调用 [https://docs.aws.amazon.com/iot/latest/apireference/API_iot-jobs-data_UpdateJobExecution.html](https://docs.aws.amazon.com/iot/latest/apireference/API_iot-jobs-data_UpdateJobExecution.html) API 来更新任务执行的状态。
+ 通过调用 [https://docs.aws.amazon.com/iot/latest/apireference/API_iot-jobs-data_DescribeJobExecution.html](https://docs.aws.amazon.com/iot/latest/apireference/API_iot-jobs-data_DescribeJobExecution.html) API 来查询任务执行的状态。
+ 通过调用 [https://docs.aws.amazon.com/iot/latest/apireference/API_iot-jobs-data_GetPendingJobExecutions.html](https://docs.aws.amazon.com/iot/latest/apireference/API_iot-jobs-data_GetPendingJobExecutions.html) API 来检索待处理任务执行的列表。
+ 通过使用 `jobId` 作为 `$next` 调用 [https://docs.aws.amazon.com/iot/latest/apireference/API_iot-jobs-data_DescribeJobExecution.html](https://docs.aws.amazon.com/iot/latest/apireference/API_iot-jobs-data_DescribeJobExecution.html) API 来检索下一个待定任务执行。
+ 通过调用 [https://docs.aws.amazon.com/iot/latest/apireference/API_iot-jobs-data_StartNextPendingJobExecution.html](https://docs.aws.amazon.com/iot/latest/apireference/API_iot-jobs-data_StartNextPendingJobExecution.html) API 来获取和开启下一个待处理任务执行。

## 使用 HTTP Signature 版本 4
<a name="jobs-using-http-v4"></a>

设备可以在端口 443 上使用 HTTP 签名版本 4 与 AWS IoT Job 通信。这是AWSSDKs 和 CLI 使用的方法。有关这些工具的更多信息，请参阅[AWS CLI命令参考： iot-jobs-data](https://docs.aws.amazon.com/cli/latest/reference/iot-jobs-data/index.html)或[AWSSDKs 和工具](https://aws.amazon.com/tools/#sdk)，并参考您的首选语言 IotJobsDataPlane 部分。

通过这种通信方式，您的设备使用 IAM 凭证通过 AWS IoT Jobs 进行身份验证。

可以使用此方法执行以下命令：
+ **DescribeJobExecution**

  `aws iot-jobs-data describe-job-execution ...` 
+ **GetPendingJobExecutions**

  `aws iot-jobs-data get-pending-job-executions ...` 
+ **StartNextPendingJobExecution**

  `aws iot-jobs-data start-next-pending-job-execution ...` 
+ **UpdateJobExecution**

  `aws iot-jobs-data update-job-execution ...` 

## 使用 HTTP TLS
<a name="jobs-using-http-tls"></a>

设备可以使用支持该协议的第三方软件客户端，在端口 8443 上使用 HTTP TLS 与 AWS IoT Jobs 通信。

利用此方法，您的设备可使用基于 X.509 证书的身份验证（例如，其特定于设备的证书和私有密钥）。

可以使用此方法执行以下命令：
+ **DescribeJobExecution**
+ **GetPendingJobExecutions**
+ **StartNextPendingJobExecution**
+ **UpdateJobExecution**

## 对设备进行编程以使用任务
<a name="programming-devices"></a>

本部分中的示例使用 MQTT 来演示设备如何使用 AWS IoT Jobs 服务。或者，您也可以使用相应的 API 或 CLI 命令。对于这些示例，我们假定名为 `MyThing` 的设备订阅以下 MQTT 主题：
+ `$aws/things/MyThing/jobs/notify` – 、 或 `$aws/things/MyThing/jobs/notify-next`
+ `$aws/things/MyThing/jobs/get/accepted`
+ `$aws/things/MyThing/jobs/get/rejected`
+ `$aws/things/MyThing/jobs/jobId/get/accepted`
+ `$aws/things/MyThing/jobs/jobId/get/rejected`

 如果您使用代码签名AWS IoT，则您的设备代码必须验证代码文件的签名。该签名在任务文档中的 `codesign` 属性内。有关验证代码文件签名的更多信息，请参阅[设备代理示例](https://github.com/aws/aws-iot-device-sdk-js#jobsAgent)。

**Topics**
+ [对设备进行编程以使用任务](#programming-devices)
+ [设备工作流程](jobs-workflow-device-online.md)
+ [任务流](jobs-workflow-jobs-online.md)
+ [任务通知](jobs-comm-notifications.md)

# 设备工作流程
<a name="jobs-workflow-device-online"></a>

设备可以使用以下任一方式处理它运行的任务。
+ 

**获取下一个任务**

  1. 当设备首次联机时，它应订阅设备的 `notify-next` 主题。

  1. 使用 jobId `$next` 调用 [DescribeJobExecution](jobs-mqtt-api.md#mqtt-describejobexecution) MQTT API 以获取下一个任务、其任务文档和其他详细信息，包括保存在 `statusDetails` 中的任何状态。如果任务文档具有代码文件签名，则您必须验证签名，然后才能继续处理任务请求。

  1. 调用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) MQTT API 以更新任务状态。或者，要在一个调用中将此步骤与上一步骤合并，设备可调用 [StartNextPendingJobExecution](jobs-mqtt-api.md#mqtt-startnextpendingjobexecution)。

  1. （可选）您可在调用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) 或 [StartNextPendingJobExecution](jobs-mqtt-api.md#mqtt-startnextpendingjobexecution) 时为 `stepTimeoutInMinutes` 设置值来添加步骤计时器。

  1. 使用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) MQTT API 执行任务文档所指定的操作以报告任务的进度。

  1. 通过使用此 jobId 调用 [DescribeJobExecution](jobs-mqtt-api.md#mqtt-describejobexecution) MQTT API 来继续监控任务执行。如果删除了任务执行，[DescribeJobExecution](jobs-mqtt-api.md#mqtt-describejobexecution) 将返回 `ResourceNotFoundException`。

     如果在设备运行任务时取消或删除了任务执行，则设备应能够恢复到有效状态。

  1. 在任务完成后调用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) MQTT API 以更新任务状态并报告成功或失败。

  1. 由于此任务的执行状态已更改为最终状态，因此，可用于执行的下一个任务（如果有）将发生更改。设备将收到下一个待处理任务执行已更改的通知。此时，设备将按照步骤 2 中所述继续操作。

  如果设备保持联机状态，则将继续收到下一个待处理任务执行的通知。这包括它在完成任务或添加新的待处理任务执行时的任务执行数据。在发生此情况时，设备将按照步骤 2 中所述继续操作。
+ 

**从可用任务中选择**

  1. 当设备首次联机时，它应订阅事物的 `notify` 主题。

  1. 调用 [GetPendingJobExecutions](jobs-mqtt-api.md#mqtt-getpendingjobexecutions) MQTT API 以获取待处理任务执行的列表。

  1. 如果列表中包含一个或多个任务执行，请选择一个任务执行。

  1. 调用 [DescribeJobExecution](jobs-mqtt-api.md#mqtt-describejobexecution) MQTT API 以获取任务文档和其它详细信息，包括保存在 `statusDetails` 中的任何状态。

  1. 调用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) MQTT API 以更新任务状态。如果在此命令中将 `includeJobDocument` 字段设置为 `true`，则设备可跳过上一个步骤并在此时检索任务文档。

  1. （可选）您可在调用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) 时为 `stepTimeoutInMinutes` 设置值来添加步骤计时器。

  1. 使用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) MQTT API 执行任务文档所指定的操作以报告任务的进度。

  1. 通过使用此 jobId 调用 [DescribeJobExecution](jobs-mqtt-api.md#mqtt-describejobexecution) MQTT API 来继续监控任务执行。如果在设备运行任务时取消或删除了任务执行，则设备应能够恢复到有效状态。

  1. 在任务完成后调用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) MQTT API 以更新任务状态并报告成功或失败。

  如果设备保持联机状态，则在一个新的待处理任务执行变为可用时，它将收到所有待处理任务执行的通知。在发生此情况时，设备可按照步骤 2 中所述继续操作。

如果设备无法执行任务，它应调用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) MQTT API 来将任务状态更新为 `REJECTED`。

# 任务流
<a name="jobs-workflow-jobs-online"></a>

下面显示了任务工作流程中的不同步骤，从启动新任务到报告任务执行的完成状态。

## 开始新任务
<a name="jobs-respond-new-job"></a>

创建新任务后，J AWS IoT obs 会为每台目标设备发布一条有关该`$aws/things/thing-name/jobs/notify`主题的消息。

消息包含以下信息：

```
{
    "timestamp":1476214217017,
    "jobs":{
        "QUEUED":[{
            "jobId":"0001",
            "queuedAt":1476214216981,
            "lastUpdatedAt":1476214216981,
            "versionNumber" : 1
        }]
    }
}
```

在对任务执行进行排队时，设备将在 `'$aws/things/thingName/jobs/notify'` 主题上收到此消息。

**注意**  
对于具有可选 `SchedulingConfig` 的任务，该任务将保持初始状态 `SCHEDULED`。当任务达到所选的 `startTime` 时，将发生以下情况：  
任务状态将更新为 `IN_PROGRESS`。
任务将开始向目标组中的所有设备推出任务文档。

## 获取任务信息
<a name="jobs-respond-get-job"></a>

要获取有关任务执行的更多信息，请调用 [DescribeJobExecution](jobs-mqtt-api.md#mqtt-describejobexecution) MQTT API 并将 `includeJobDocument` 字段设置为 `true`（默认值）。

如果请求成功，AWS IoT作业服务将发布一条有关该`$aws/things/MyThing/jobs/0023/get/accepted`主题的消息：

```
{
    "clientToken" : "client-001",
    "timestamp" : 1489097434407,
    "execution" : {
        "approximateSecondsBeforeTimedOut": number,
        "jobId" : "023",
        "status" : "QUEUED",
        "queuedAt" : 1489097374841,
        "lastUpdatedAt" : 1489097374841,
        "versionNumber" : 1,
        "jobDocument" : {
            < contents of job document >
        }
    }
}
```

如果请求失败，AWS IoT作业服务将发布一条有关该`$aws/things/MyThing/jobs/0023/get/rejected`主题的消息。

设备现在已有任务文档，它可使用该文档执行任务的远程操作。如果任务文档包含一个 Amazon S3 预签名 URL，则设备可使用该 URL 下载任务的任何所需文件。

## 报告任务执行状态
<a name="jobs-job-processing"></a>

当设备执行任务时，它可调用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) MQTT API 来更新任务执行的状态。

例如，设备可通过在 `IN_PROGRESS` 主题上发布以下消息来将任务执行状态更新为 `$aws/things/MyThing/jobs/0023/update`：

```
{
    "status":"IN_PROGRESS",
    "statusDetails": {
        "progress":"50%"
    },
    "expectedVersion":"1",
    "clientToken":"client001"
}
```

Jobs 通过将消息发布到 `$aws/things/MyThing/jobs/0023/update/accepted` 或 `$aws/things/MyThing/jobs/0023/update/rejected` 主题来进行响应：

```
{
    "clientToken":"client001",
    "timestamp":1476289222841
}
```

设备可通过调用 [StartNextPendingJobExecution](jobs-mqtt-api.md#mqtt-startnextpendingjobexecution) 来合并两个以前的请求。这将获取并开始下一个待处理任务执行，并允许设备更新任务执行状态。此请求还在有待处理任务执行时返回任务文档。

如果作业包含 [TimeoutConfig](https://docs.aws.amazon.com//iot/latest/apireference/API_TimeoutConfig.html)，则正在进行的计时器开始运行。您还可以通过设置调用时的值来为任务执行设置步进计`stepTimeoutInMinutes`时器[UpdateJobExecution](https://docs.aws.amazon.com//iot/latest/apireference/API_iot-jobs-data_UpdateJobExecution.html)。步骤计时器仅应用于您更新的任务执行。您每次更新任务执行时，可以为此计时器设置新值。您也可以在呼叫时创建计步器[StartNextPendingJobExecution](https://docs.aws.amazon.com//iot/latest/apireference/API_iot-jobs-data_StartNextPendingJobExecution.html)。如果任务执行保持在 `IN_PROGRESS` 状态的时间长度超过了此步骤计时器间隔，它将失败，并切换为最终 `TIMED_OUT` 状态。步骤计时器对您在创建任务时设置的进行中计时器没有任何影响。

`status` 字段可设置为 `IN_PROGRESS`、`SUCCEEDED` 或 `FAILED`。您无法更新已处于最终状态的任务执行的状态。

## 报告执行已完成
<a name="jobs-job-completed"></a>

在设备执行完任务后，它将调用 [UpdateJobExecution](jobs-mqtt-api.md#mqtt-updatejobexecution) MQTT API。如果任务已成功，则将 `status` 设置为 `SUCCEEDED`，并在消息有效载荷的 `statusDetails` 中，将有关任务的其它信息作为名称-值对添加。任务执行完成时，进行中计时器和步骤计时器结束。

例如：

```
{
    "status":"SUCCEEDED",
    "statusDetails": {
        "progress":"100%"
    },
    "expectedVersion":"2",
    "clientToken":"client-001"
}
```

如果任务未成功，则将 `status` 设置为 `FAILED`，并在 `statusDetails` 中，添加有关出现的错误的信息：

```
{
    "status":"FAILED",
    "statusDetails": {
        "errorCode":"101",
        "errorMsg":"Unable to install update"
    },
    "expectedVersion":"2",
    "clientToken":"client-001"
}
```

**注意**  
`statusDetails` 属性可包含任意数量的名称-值对。

当 AWS IoT Jobs 服务收到此更新时，它会发布一条有关该`$aws/things/MyThing/jobs/notify`主题的消息，表示任务执行已完成：

```
{
    "timestamp":1476290692776,
    "jobs":{}
}
```

## 其它任务
<a name="jobs-additional-job"></a>

如果设备有其它待处理的任务执行，这些任务执行将包含在发布到 `$aws/things/MyThing/jobs/notify` 的消息中。

例如：

```
{
    "timestamp":1476290692776,
    "jobs":{
        "QUEUED":[{
            "jobId":"0002",
            "queuedAt":1476290646230,
            "lastUpdatedAt":1476290646230
        }],
        "IN_PROGRESS":[{
            "jobId":"0003",
            "queuedAt":1476290646230,
            "lastUpdatedAt":1476290646230
        }]
    }
}
```

# 任务通知
<a name="jobs-comm-notifications"></a>

当任务处于待处理状态或列表中的第一个任务执行发生变化时，AWS IoT作业服务会向保留主题发布 MQTT 消息。设备可通过订阅这些主题来跟踪待处理任务。

## 任务通知类型。
<a name="jobs-comm-notifications-types"></a>

任务通知将作为 JSON 有效载荷发布到 MQTT 主题。通知有两种：

**ListNotification**

`ListNotification` 包含一个列表，其中待处理的任务执行不超过 15 个。它们依次按照状态（`IN_PROGRESS` 任务执行在 `QUEUED` 任务执行之前）和排队的时间进行排序。

如果满足以下条件之一，则发布 `ListNotification`。
+ 新的任务执行已排队或更改为非最终状态（`IN_PROGRESS` 或 `QUEUED`）。
+ 旧的任务执行更改为最终状态（`FAILED`、`SUCCEEDED`、`CANCELED`、`TIMED_OUT`、`REJECTED` 或 `REMOVED`）。

有关使用和不使用调度配置时的限制的更多信息，请参阅 [任务执行限制](job-limits.md#job-execution-limits)。

**NextNotification**
+ `NextNotification` 包含有关队列中下一个任务执行的摘要信息。

  每当列表中第一个任务执行更改时，则会发布 `NextNotification`。
  + 新的任务执行作为 `QUEUED` 添加到列表，并且在列表中排在第一位。
  + 不是列表中第一位的现有任务执行的状态从 `QUEUED` 更改为 `IN_PROGRESS`，然后成为列表中的第一个。（当列表中没有其它 `IN_PROGRESS` 任务执行时，或者当状态从 `QUEUED` 更改为 `IN_PROGRESS` 的任务执行排队的时间早于列表中其他所有 `IN_PROGRESS` 任务执行时，会出现这种情况。） 
  + 列表第一的任务执行状态更改为最终状态，并且从列表中删除。

有关发布和订阅 MQTT 主题的更多信息，请参阅 [设备通信协议](protocols.md)。

**注意**  
当您使用 HTTP Signature Version 4 或 HTTP TLS 与 Jobs 通信时，通知不可用。

## 任务待处理
<a name="jobs-comm-pending"></a>

在某事物的待处理任务执行列表中添加或从中删除任务或列表中的第一个任务执行发生变化时，AWS IoT作业服务会在 MQTT 主题上发布一条消息：
+ `$aws/things/thingName/jobs/notify`
+ `$aws/things/thingName/jobs/notify-next`

消息包含以下示例有效载荷：

`$aws/things/thingName/jobs/notify`:

```
{
  "timestamp" : 10011,
  "jobs" : {
    "IN_PROGRESS" : [ {
      "jobId" : "other-job",
      "queuedAt" : 10003,
      "lastUpdatedAt" : 10009,
      "executionNumber" : 1,
      "versionNumber" : 1
    } ],
    "QUEUED" : [ {
      "jobId" : "this-job",
      "queuedAt" : 10011,
      "lastUpdatedAt" : 10011,
      "executionNumber" : 1,
      "versionNumber" : 0
    } ]
  }
}
```

如果名为 `this-job` 的任务执行源自某个选定了可选计划配置且任务文档推出计划在维护时段内进行的任务，则该任务只会在定期维护时段内出现。在维护时段之外，名为 `this-job` 的任务将从待处理的任务执行列表中排除，如以下示例所示。

```
{
  "timestamp" : 10011,
  "jobs" : {
    "IN_PROGRESS" : [ {
      "jobId" : "other-job",
      "queuedAt" : 10003,
      "lastUpdatedAt" : 10009,
      "executionNumber" : 1,
      "versionNumber" : 1
    } ],
    "QUEUED" : []
  }
}
```

`$aws/things/thingName/jobs/notify-next`:

```
{
  "timestamp" : 10011,
  "execution" : {
    "jobId" : "other-job",
    "status" : "IN_PROGRESS",
    "queuedAt" : 10009,
    "lastUpdatedAt" : 10009,
    "versionNumber" : 1,
    "executionNumber" : 1,
    "jobDocument" : {"c":"d"}
  }
}
```

如果名为 `other-job` 的任务执行源自某个选定了可选计划配置且任务文档推出计划在维护时段内进行的任务，则该任务只会在定期维护时段内出现。在维护时段之外，名为 `other-job` 的任务不会列为下一个任务执行，如以下示例所示。

```
{} //No other pending jobs
```

```
{
  "timestamp" : 10011,
  "execution" : {
      "jobId" : "this-job",
      "queuedAt" : 10011,
      "lastUpdatedAt" : 10011,
      "executionNumber" : 1,
      "versionNumber" : 0,
      "jobDocument" : {"a":"b"}
  }
} // "this-job" is pending next to "other-job"
```

可能的任务执行状态值为 `QUEUED`、`IN_PROGRESS`、`FAILED`、`SUCCEEDED`、`CANCELED`、`TIMED_OUT`、`REJECTED` 和 `REMOVED`。

以下一系列示例显示了在创建任务执行以及任务执行从一种状态更改为另一种状态时向每个主题发布的通知。

首先，创建了一个名为 `job1` 的任务。此通知发布到 `jobs/notify` 主题：

```
{
  "timestamp": 1517016948,
  "jobs": {
    "QUEUED": [
      {
        "jobId": "job1",
        "queuedAt": 1517016947,
        "lastUpdatedAt": 1517016947,
        "executionNumber": 1,
        "versionNumber": 1
      }
    ]
  }
}
```

此通知发布到 `jobs/notify-next` 主题：

```
{
  "timestamp": 1517016948,
  "execution": {
    "jobId": "job1",
    "status": "QUEUED",
    "queuedAt": 1517016947,
    "lastUpdatedAt": 1517016947,
    "versionNumber": 1,
    "executionNumber": 1,
    "jobDocument": {
      "operation": "test"
    }
  }
}
```

当创建另一个任务 (`job2`) 时，此通知将发布到 `jobs/notify` 主题：

```
{
  "timestamp": 1517017192,
  "jobs": {
    "QUEUED": [
      {
        "jobId": "job1",
        "queuedAt": 1517016947,
        "lastUpdatedAt": 1517016947,
        "executionNumber": 1,
        "versionNumber": 1
      },
      {
        "jobId": "job2",
        "queuedAt": 1517017191,
        "lastUpdatedAt": 1517017191,
        "executionNumber": 1,
        "versionNumber": 1
      }
    ]
  }
}
```

通知未发布到 `jobs/notify-next` 主题，因为队列中的下一个任务 (`job1`) 尚未更改。当 `job1` 开始执行时，其状态更改为 `IN_PROGRESS`。没有发布任何通知，因为任务列表和队列中的下一个任务尚未更改。

当添加第三个任务 (`job3`) 时，此通知将发布到 `jobs/notify` 主题：

```
{
  "timestamp": 1517017906,
  "jobs": {
    "IN_PROGRESS": [
      {
        "jobId": "job1",
        "queuedAt": 1517016947,
        "lastUpdatedAt": 1517017472,
        "startedAt": 1517017472,
        "executionNumber": 1,
        "versionNumber": 2
      }
    ],
    "QUEUED": [
      {
        "jobId": "job2",
        "queuedAt": 1517017191,
        "lastUpdatedAt": 1517017191,
        "executionNumber": 1,
        "versionNumber": 1
      },
      {
        "jobId": "job3",
        "queuedAt": 1517017905,
        "lastUpdatedAt": 1517017905,
        "executionNumber": 1,
        "versionNumber": 1
      }
    ]
  }
}
```

通知未发布到 `jobs/notify-next` 主题，因为队列中的下一个任务仍为 `job1`。

当 `job1` 完成后，其状态更改为 `SUCCEEDED`，此通知将发布到 `jobs/notify` 主题：

```
{
  "timestamp": 1517186269,
  "jobs": {
    "QUEUED": [
      {
        "jobId": "job2",
        "queuedAt": 1517017191,
        "lastUpdatedAt": 1517017191,
        "executionNumber": 1,
        "versionNumber": 1
      },
      {
        "jobId": "job3",
        "queuedAt": 1517017905,
        "lastUpdatedAt": 1517017905,
        "executionNumber": 1,
        "versionNumber": 1
      }
    ]
  }
}
```

此时，已从队列中删除 `job1`，要执行的下一个任务是 `job2`。此通知发布到 `jobs/notify-next` 主题：

```
{
  "timestamp": 1517186269,
  "execution": {
    "jobId": "job2",
    "status": "QUEUED",
    "queuedAt": 1517017191,
    "lastUpdatedAt": 1517017191,
    "versionNumber": 1,
    "executionNumber": 1,
    "jobDocument": {
      "operation": "test"
    }
  }
}
```

如果 `job3` 必须在 `job2` 之前开始执行（不推荐），`job3` 的状态可以更改为 `IN_PROGRESS`。更改后，`job2` 则不再是队列中的下一个任务，此通知将发布到 `jobs/notify-next` 主题：

```
{
  "timestamp": 1517186779,
  "execution": {
    "jobId": "job3",
    "status": "IN_PROGRESS",
    "queuedAt": 1517017905,
    "startedAt": 1517186779,
    "lastUpdatedAt": 1517186779,
    "versionNumber": 2,
    "executionNumber": 1,
    "jobDocument": {
      "operation": "test"
    }
  }
}
```

没有向 `jobs/notify` 主题发布任何通知，因为没有添加或删除任何任务。

如果设备拒绝 `job2`，并且将其状态更新为 `REJECTED`，则此通知将发布到 `jobs/notify` 主题：

```
{
  "timestamp": 1517189392,
  "jobs": {
    "IN_PROGRESS": [
      {
        "jobId": "job3",
        "queuedAt": 1517017905,
        "lastUpdatedAt": 1517186779,
        "startedAt": 1517186779,
        "executionNumber": 1,
        "versionNumber": 2
      }
    ]
  }
}
```

如果 `job3`（仍在进行）被强制删除，则此通知将发布到 `jobs/notify` 主题：

```
{
  "timestamp": 1517189551,
  "jobs": {}
}
```

此时队列为空。此通知发布到 `jobs/notify-next` 主题：

```
{
  "timestamp": 1517189551
}
```