# ホットアップグレード（Relup）

このプラグインは、実行中のEMQXノードに対して`.relup`形式のコード変更指示を適用し、オペレーターがVMを再起動せずにパッチリリースを展開できるようにします。

オペレーターは各ノードで`emqx ctl relup ...` CLIを使用して操作します。クラスター全体への展開はオペレーターの責任であり（オーケストレーション機能は組み込まれていません）。

## 使用タイミング

ホットアップグレードは以下の場合に適しています：

- 適用したいホップが`emqx ctl relup list-supported-paths`でリストされている（宣言された`{from, target}`ホップのみサポート）。
- 次のノードに進む前にターゲットノードを検証できる。
- `data/`のバックアップがある。適用済みホップに対するインプレースのロールバックはありません（[ロールバック](#rollback)参照）。

これらを満たせない場合は、通常のローリング再起動によるアップグレードを行ってください。

## オペレーターの作業手順

### 1. プラグインのインストール

以下の[ダウンロード](#download)セクションからEMQXバージョンに合ったtarballを取得し、ダッシュボード（またはREST API / CLI）から他のプラグインと同様にインストールします。

### 2. アップグレードパスのサポート確認

```bash
emqx ctl relup list-supported-paths
```

出力はこのプラグインバージョンの`priv/relup/`にバンドルされた`{from, target}`ホップを示します。ホップがない場合、そのパスのホットアップグレードは利用できません。通常の再起動ベースのアップグレードに戻ってください。

### 3. 各ノードにターゲットリリースを配置

各ノードで、EMQXプロセスが読み取れるパスに以下の2ファイルをコピーします：

- `emqx-enterprise-<TargetVsn>-<os>-<arch>.tar.gz`：EMQXターゲットリリースのtarball
- `<tarball>.sha256`：sha256ダイジェスト。標準の`sha256sum`形式（`<digest>  <filename>`）が受け入れられます。

### 4. アップグレードの実行

各ノードで：

```bash
emqx ctl relup upgrade <TarballPath> [--force]
```

ハンドラーは以下を行います：

- `<TarballPath>.sha256`と実際のダイジェストを照合し、不一致の場合は展開を拒否。
- `data/patches/`に`*.beam`ファイルがある場合は続行を拒否。このディレクトリは`vm.args -pa`でコードパスの先頭に追加されるため、アップグレードターゲットのモジュールより優先されます。ターゲットリリースにホットパッチ済みの修正が含まれていても、古いbeamファイルが読み込まれる可能性があります。パッチファイルを先に削除するか、ターゲットリリース上に適用し続ける意図がある場合のみ`--force`を指定してください。
- tarballを展開し、`releases/emqx_vars`から`REL_VSN`を読み込みます。
- `priv/relup/*.relup`で一致する`{from, target}`ホップを検索し、宣言されたコード変更指示とポストアップグレードコールバックを実行します。

### 5. ノードの検証

次の信号を確認してから次に進みます：

- `emqx ctl status`がノードが稼働中であることを報告する。
- `<RootDir>/relup/current`がターゲットバージョンと一致し、`<RootDir>/relup/<TargetVsn>/`に`bin/`、`erts-*/`、`lib/`、`releases/`が含まれている。

次回の`emqx start`または`restart`時に、`bin/emqx`ラッパーは`relup/current`を検出し、展開済みツリー（新しいERTS、新しいbinスクリプト、新しいlib）にexecします。元の`<RootDir>`は`data/`、`etc/`、`log/`、`plugins/`の管理を継続します。

### 6. 成功後のクリーンアップ

クラスター全体がターゲットバージョンに移行したら、配置したtarballと`.sha256`サイドカーを手動で削除してください。プラグインはソースパスを追跡しないため、プラグイン側での状態クリアは不要です。

## アップグレード履歴

各ノードは`emqx_relup_log`テーブル（ディスクバック、ローカル内容）に独自の監査ログを保持します。履歴はプラグインアンインストール後も残り、再インストールで再接続されます。

CLIで確認またはクリア可能です：

```bash
emqx ctl relup logs           # 最近のアップグレード試行を表示
emqx ctl relup logs-clear     # このノードのログ行をすべて削除
```

## ロールバック

適用済みホップに対するインプレースのロールバックはありません。ホットアップグレードはライブVM上で`code_changes`を実行し、`post_upgrade_callbacks`がディスク上のデータを変更している可能性があるため、これを元に戻すことはプラグインでサポートされていません。

実用的なフォールバック方法：

- **次回の再起動前に**、アップグレードは成功したが新コードに問題があり、ディスク上のデータが旧リリースと互換性がある場合：

  ```bash
  rm <RootDir>/relup/current
  # 必要に応じて：rm -rf <RootDir>/relup/<TargetVsn>/
  emqx restart
  ```

  ラッパーは元の`<RootDir>/bin/emqx`ツリーにフォールバックします。これは起動パスのみを回復し、アップグレード時のVM内部のライブ状態は失われています。

- **それ以外の場合**、アップグレード前にバックアップした`data/`（mnesia、設定など）から復元し、旧EMQXリリースを再インストールしてください。アップグレードの計画時にこれを考慮してください。

## ホップの作成（開発者向けメモ）

新しいホップを追加するには、必要な各リリースに対して：

1. `priv/relup/<from>-to-<to>.relup`を追加し、ホップの`code_changes`と`post_upgrade_callbacks`を宣言します。プラグインソースの`priv/relup/README.md`にスキーマ、サポートされる命令、ポストアップグレードコールバックの契約が記載されています。特に、新しいEMQXの`emqx_post_upgrade`に`pr_NNNNN_*`コールバックを追加する場合、relupホップはコールバック呼び出し前にそのモジュールをリロードするか、このプラグインに`emqx_post_upgrade_<TargetVsn>.erl`としてコールバックを同梱する必要があります。
2. このプラグインの`VERSION`を更新して再公開します。

プラグインは起動時にすべての`priv/relup/*.relup`を検証し、不正なエントリがあれば警告ログを出します。悪いファイルはスキップされ、致命的にはなりません。

<!-- PLUGIN-DOWNLOADS:BEGIN (auto-generated, do not edit) -->

## ダウンロード

各EMQXリリースのtarball：

| EMQXバージョン | プラグインバージョン | パッケージ |
|---|---|---|
| 5.10.4 | 1.0.0 | [emqx_relup-1.0.0.tar.gz](https://packages.emqx.io/emqx-plugins/e5.10.4/emqx_relup-1.0.0.tar.gz) |

<!-- PLUGIN-DOWNLOADS:END -->
