# ジョブの管理

ジョブとは、1台または複数のデバイスに対して非同期に実行される操作のことです。Fleetsは、対象デバイスごとに実行状況を独立して追跡し、キューに入った初期状態から成功、失敗、タイムアウトまで管理します。

## ジョブを使うタイミング

以下の場合は、コマンドの代わりにジョブを使用してください：
- 複数のデバイスを一度に対象にしたい場合（例：グループに対してファームウェアアップデートをプッシュする）
- デバイスが断続的にオフラインになる可能性がある場合（ジョブはキューに入り、再接続時に配信される）
- 操作を完了したデバイスと完了していないデバイスを永続的に記録したい場合

## コンソールからジョブを作成する

1. Fleetsのデプロイメントで、**Commands & Jobs** > **Jobs** タブに移動します。
2. **+ Create Job** をクリックします。
3. 以下の項目を入力します：
   - **Name**：（任意）ジョブの人間が読める名前。省略するとジョブはIDで識別されます。
   - **Job Type**：**SNAPSHOT**（現在の対象に対して一度だけ実行）または **CONTINUOUS**（時間経過で新たに対象に加わるデバイスにも適用）を選択します。
   - **Description**：（任意）ジョブの目的の説明。
   - **Target Things**：1台以上の個別デバイスを選択。
   - **Group**：Thing Groupを選択し、その現在のメンバー全員を対象にします。
   - **Document**：（必須）操作内容を定義するJSONオブジェクト。デバイスはこれをジョブドキュメントとして受け取ります。
4. **Create Job** をクリックします。

![create_job](./_assets/create_job.png)

## APIでジョブを作成する

```text
POST /api/v1/jobs
```

リクエストボディ例：
```json
{
  "description": "Firmware update to v2.1.5",
  "targets": {
    "thingGroupNames": ["com.example.thermostat (default)"]
  },
  "document": {
    "action": "updateFirmware",
    "params": {
      "version": "2.1.5",
      "url": "https://firmware.example.com/thermostat-v2.1.5.bin"
    }
  }
}
```

`targets` フィールドは以下を受け付けます：
- `thingNames`：個別のThing名のリスト
- `thingGroupNames`：Thing Group名のリスト（現在の全メンバーが対象）

レスポンスには `jobId`（UUID）が含まれます。

## ジョブと実行状況の確認

1. **Commands & Jobs** > **Jobs** タブに移動します。
2. **Status** と **Job Type** のフィルターでリストを絞り込みます。
3. リストには各ジョブの **Name**、**Job Type**、**Status**、**Targets**（Thing数とグループ名）、**Created At** タイムスタンプが表示されます。
4. ジョブ名をクリックすると詳細画面が開き、デバイスごとの実行状況の内訳が確認できます。

### ジョブのステータス

| ステータス | 意味 |
|---|---|
| `IN_PROGRESS` | 少なくとも1台のデバイスの実行が進行中 |
| `COMPLETED` | 全てのデバイス実行が終了状態に到達 |
| `CANCELED` | ジョブがキャンセルされた |
| `DELETION_IN_PROGRESS` | ジョブが削除中 |

### デバイスごとの実行ステータス

| ステータス | 意味 |
|---|---|
| `QUEUED` | デバイスがジョブを取得するのを待機中 |
| `IN_PROGRESS` | デバイスが実行を開始 |
| `SUCCEEDED` | デバイスが成功を報告 |
| `FAILED` | デバイスが失敗を報告 |
| `REJECTED` | デバイスがジョブを拒否 |
| `TIMED_OUT` | タイムアウト期間内に更新なし |
| `CANCELED` | このデバイスの実行がキャンセルされた |
| `REMOVED` | 実行記録が削除された |

## ジョブをキャンセルする

残りのデバイスへのジョブ配信を停止するには：

1. ジョブ詳細画面を開きます。
2. **Cancel Job** をクリックします。
3. 操作を確認します。

API経由の場合：
```text
POST /api/v1/jobs/{jobId}/cancel
```

リクエストボディ（全フィールド任意）：
```json
{
  "reasonCode": "USER_CANCEL",
  "comment": "Pausing rollout for investigation"
}
```

ジョブのキャンセルは、すでに `IN_PROGRESS` 状態の実行を停止しません。アクティブな実行を強制キャンセルするには、`"force": true` パラメータを使用してください。

## 特定デバイスの実行をキャンセルする

他のデバイスに影響を与えず、特定のデバイスのジョブ実行のみキャンセルするには：

```text
POST /api/v1/jobs/{jobId}/executions/{thingName}/cancel
```

## ジョブを削除する

終了状態（`COMPLETED`、`CANCELED`）のジョブは削除可能です：

```text
DELETE /api/v1/jobs/{jobId}
```

アクティブなジョブを削除する場合：
```text
DELETE /api/v1/jobs/{jobId}?force=true
```

::: warning 重要なお知らせ

ジョブを削除すると、そのジョブに関する全ての実行記録が削除されます。この操作は元に戻せません。

:::

## ジョブのデバイス側プロトコル

デバイス側では、ジョブはプルベースのプロトコルに従います。新しいジョブがデバイスにキューイングされると、Fleetsは以下のトピックに通知をパブリッシュします：

```text
$emqx/things/{thingName}/jobs/notify
```

デバイスはジョブドキュメントをプルし、実行し、状態を報告します。詳細なデバイス側プロトコルは [Device Integration: Jobs](../device_integration/mqtt_integration.md#jobs) をご参照ください。

## 次のステップ

- [Commands and Jobs Overview](./commands_and_jobs_overview.md)
- [Send Commands](./send_commands.md)
- [Device Integration: Jobs](../device_integration/mqtt_integration.md#jobs)
