環境変数によるスーパーバイザーモード指定が機能しない問題を修正
Solid Queueのドキュメントには SOLID_QUEUE_SUPERVISOR_MODE 環境変数でスーパーバイザーモードを制御できると記載されていましたが、実際には環境変数が無視される不具合がありました。#709 は、CLIオプションのデフォルト値設定を削除することでこの問題を解決しています。
背景
Solid Queueのスーパーバイザーモードには、ワーカーとディスパッチャーを別プロセスで起動する fork モードと、スーパーバイザーと同じプロセス内で実行する async モードの2種類があります。READMEには環境変数でモードを切り替えられると記載されていましたが、SOLID_QUEUE_SUPERVISOR_MODE=async bin/jobs を実行してもforkモードで起動されるという問題が報告されました。
この不具合の原因は、CLIクラスとConfigurationクラスの間でのデフォルト値の優先順位にありました。Cli クラスが --mode オプションに "fork" をデフォルト値として設定していたため、環境変数が参照される前にオプション値が確定してしまっていました。
技術的な変更
lib/solid_queue/cli.rb の class_option :mode からデフォルト値の指定が削除されました。
変更前:
class_option :mode, type: :string, default: "fork", enum: %w[ fork async ],
desc: "Whether to fork processes for workers and dispatchers (fork) or to run these in the same process as the supervisor (async) (default: fork).",
banner: "SOLID_QUEUE_SUPERVISOR_MODE"
変更後:
class_option :mode, type: :string, enum: %w[ fork async ],
desc: "Whether to fork processes for workers and dispatchers (fork) or to run these in the same process as the supervisor (async) (default: fork).",
banner: "SOLID_QUEUE_SUPERVISOR_MODE"
これにより、Configuration クラスの初期化時に options に mode キーが含まれなくなり、default_options メソッドで環境変数 SOLID_QUEUE_SUPERVISOR_MODE が参照されるようになりました。Configuration クラスでは以下のようにオプションとデフォルト値がマージされています:
def initialize(**options)
@mode = SupervisorMode.new(options.fetch(:mode, default_options[:mode]))
end
private
def default_options
{
mode: ENV.fetch("SOLID_QUEUE_SUPERVISOR_MODE", "fork")
}
end
新たに追加された test/unit/cli_test.rb では、4つのシナリオがテストされています:
- 環境変数もオプションも指定しない場合はforkモードになること
-
SOLID_QUEUE_SUPERVISOR_MODE=asyncでasyncモードになること - オプション指定が環境変数より優先されること
- 環境変数なしでもオプション指定が機能すること
テストは with_env ヘルパーで環境変数を制御し、Cli クラスから Configuration を生成して期待されるモードになることを検証しています。
設計判断
CLIクラスからデフォルト値を削除する方式 が採用されました。
デフォルト値の設定箇所を Cli から Configuration に一本化することで、環境変数・CLIオプション・コードレベルのデフォルト値という3層の優先順位が明確になりました。Thorライブラリの class_option で default を指定すると、オプションが未指定でも必ず値が設定されてしまうため、fetch の第2引数によるデフォルト値適用が機能しなくなります。
この修正により、「CLIオプション > 環境変数 > ハードコードされたデフォルト値」という直感的な優先順位が実現されています。descriptionには依然として "(default: fork)" の記載が残されており、デフォルト動作は変更されていません。
まとめ
本PRは、CLIクラスのデフォルト値設定を削除することで、環境変数によるスーパーバイザーモード制御を機能させる修正です。Thorの class_option の仕様を考慮し、デフォルト値の設定箇所を Configuration クラスに集約することで、ドキュメントに記載された動作を実現しています。