# ジョブ: イベントトピック付き

**想定読者:** MQTT経由でジョブの進行や結果を連携先の購読者が受け取る必要があり、`KeeperLogger` 向けの構造化ログとは別の経路で扱う必要がある統合担当者。

多くのジョブタスクは出力に `KeeperLogger` だけで足ります。本例は、タスクがリアルタイムで公開するイベントに別コンポーネントが反応する必要がある場合 (ダッシュボード、アラート連携ブリッジ、オーケストレーター、ログ集約を待てない購読者など) 向けです。`eventTopic` フィールドで専用のMQTTトピックを宣言し、`mqttTopics.allowedPublications` に明示的に列挙しないとパブリッシュは拒否されます。

本例はWindowsのパスを使います。LinuxおよびmacOSでは、[ジョブ: 最小構成 (Linux)](/keeperpam/jp/endpoint-privilege-manager/integrations/examples/job-minimal-linux.md) および[ジョブ: 最小構成 (macOS)](/keeperpam/jp/endpoint-privilege-manager/integrations/examples/job-minimal-macos.md) の例に示すとおり、パスと `osFilter` を置き換えてください。

## ジョブのJSON <a href="#the-job-json" id="the-job-json"></a>

```json
{
  "id": "my-tool",
  "name": "My Tool",
  "description": "Runs MyTool on an interval and publishes progress events to a dedicated MQTT topic.",
  "enabled": true,

  "schedule": {
    "intervalMinutes": 60
  },

  "eventTopic": "Jobs/my-tool/events",

  "osFilter": {
    "windows": true,
    "linux": false,
    "macOS": false
  },

  "mqttTopics": {
    "allowedPublications": [
      "KeeperLogger",
      "Jobs/my-tool/events"
    ],
    "allowedSubscriptions": []
  },

  "parameters": [],

  "tasks": [
    {
      "id": "run-tool",
      "name": "Run tool",
      "ExecutionType": "Service",
      "command": "MyTool",
      "executablePath": "C:\\Program Files\\KeeperPrivilegeManager\\Jobs\\bin\\MyTool\\MyTool.exe",
      "arguments": "--keeper-api-base={KeeperApiBaseUrl}",
      "timeoutSeconds": 3600,
      "continueOnFailure": false,
      "scriptType": "Auto"
    }
  ]
}
```

## 変更する箇所 <a href="#what-to-change" id="what-to-change"></a>

| フィールド                            | 内容                                                                                                    |
| -------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `id`                             | 本ジョブを一意に識別する文字列。ハイフンを使い、アンダースコアは使いません。ファイル名は `id` と一致させます (例: `"id": "my-tool"` のときは `my-tool.json`)。 |
| `name`                           | ログや管理画面に表示する名称                                                                                        |
| `eventTopic`                     | タスクがイベントをパブリッシュするMQTTトピック。`mqttTopics.allowedPublications` の文字列と完全一致させる                               |
| `mqttTopics.allowedPublications` | `KeeperLogger` (ログを出す場合) と `eventTopic` の文字列の両方を含める必要があります。パブリッシュするトピックはすべてここに列挙します。                  |
| `tasks[0].command`               | バイナリ名。パスや拡張子は含めません。                                                                                   |
| `tasks[0].executablePath`        | エンドポイント上のバイナリのフルパス                                                                                    |
| `tasks[0].arguments`             | バイナリが受け付けるフラグ。`{KeeperApiBaseUrl}` は残します。                                                             |

## 動作の要点 <a href="#how-this-works" id="how-this-works"></a>

`eventTopic` は、エージェントが本ジョブの実行イベントに関連付けるMQTTトピックを宣言します。省略した場合のデフォルトは `Jobs/{jobId}/events` で、`"id": "my-tool"` のジョブでは `Jobs/my-tool/events` です。ここで明示すると JSON 上でトピックが見え、デフォルトパターンが将来変わっても意図しない結果を避けやすくなります。

重要なのは、`eventTopic` と `mqttTopics.allowedPublications` を常に同期させることです。ブローカーはパブリッシュ時点で許可リストを強制します。タスクが `Jobs/my-tool/events` にパブリッシュしても、その文字列が `allowedPublications` にない場合、MQTT接続自体は成功してもパブリッシュはエラー表示なく拒否されます。イベントトピックまわりで最も多い設定ミスです。`eventTopic` を変えたら、`allowedPublications` も同じ文字列に合わせて更新してください。

タスクのバイナリは、 `KeeperLogger` と同様に、プラグイン設定から読んだブローカー設定でMQTT接続を開いたあと、イベントトピックへパブリッシュします。イベントトピックは、ブローカーが追加で許可するトピックにすぎません。ペイロード形式は任意で、 `KeeperLogger` の `RequestMessage` 構造に合わせる必要はありません。

購読者は、タスクがパブリッシュするタイミングでリアルタイムにイベントを受け取ります。設計に組み込む前に管理者に確認を取り、購読コンポーネントが当該イベントトピックを購読する権限を持つようにしてください。

## デプロイ前に <a href="#before-you-deploy" id="before-you-deploy"></a>

1. `eventTopic` と `mqttTopics.allowedPublications` の対応エントリが同一の文字列であることを確認する。不一致はバリデーションエラーにならず、実行して初めてパブリッシュの成否が分かります。
2. 連携先の購読者がイベントトピックをMQTTで購読できる権限を持つことを確認する。
3. ジョブを登録する前に、バイナリを `executablePath` にデプロイする。
4. ファイル名は `id` と一致させる。

## デプロイ <a href="#deploy" id="deploy"></a>

保存前に検証します。

```powershell
Invoke-RestMethod -Method Post `
  -Uri "https://127.0.0.1:6889/api/Jobs/validate" `
  -ContentType "application/json" `
  -Certificate $adminClientCert `
  -Body (Get-Content -Raw .\my-tool.json)
```

ジョブを作成します。

```powershell
Invoke-RestMethod -Method Post `
  -Uri "https://127.0.0.1:6889/api/Jobs" `
  -ContentType "application/json" `
  -Certificate $adminClientCert `
  -Body (Get-Content -Raw .\my-tool.json)
```

手動実行をトリガーし、想定トピックにイベントが出ることを確認します。

```powershell
Invoke-RestMethod -Method Post `
  -Uri "https://127.0.0.1:6889/api/Jobs/my-tool/trigger" `
  -ContentType "application/json" `
  -Certificate $adminClientCert `
  -Body "{}"
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/jp/endpoint-privilege-manager/integrations/examples/job-with-event-topic.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
