Published on

オープンソースのバグで開発が止まりかけたので、コミットを積んで直してみた話

Authors

去年、eKYCを利用した本人確認機能を開発していたのですが、導入しようとしたオープンソースにバグがあり、そのままでは開発が進められない事態となりました。 この状況を打破すべく、オープンソースにコミットを積んで運良く直すことができたので、背景や解決までに至ったプロセスなどを紹介します。

背景

ユーザーが本人確認申請時に個人情報をeKYCへ送信した後、正しくレスポンスが返ってきた場合はユーザーをeKYCの本人確認手続き画面へ誘導する必要がありました。また、本人確認機能の提供後にユーザーが集中してタイムアウトなどのエラーが懸念されるため、eKYCへのリクエストは非同期処理にしなければなりませんでした。

ただし、eKYCへの同時リクエスト数が5までであっためSidekiqで制御する必要がありました。

Sidekiq単体で制御を行う場合、有料版のSidekiq Enterpriseへ切り替えなければなりませんでした。しかし、利用料金が高額なことと開発期限が約1ヶ月後に迫っていたため、予算申請から導入までの時間も考えると開発負荷を上げてしまう懸念がありました。

そこで、オープンソースのsidekiq-limit_fetchというサードパーティを使うことで、同時リクエスト数を制限しようとしました。しかし、ここでも問題がありsidekiq-limit_fetchを実際に導入してみるとバグが存在していたためそのまま使用することが困難でした。

対応方針

sidekiq-limit_fetchで同時リクエスト数制限を実現させるためにできそうなことは、2つありました。

  • Sidekiqをダウングレードする
  • sidekiq-limit_fetchのバグを修正する

sidekiq-limit_fetchの導入時、開発環境に入っていたSidekiqのバージョンはv7でした。v7は半年以内にリリースされたばかりだったこともあり、sidekiq-limit_fetchがまだv7に完全に対応できていない状況でした。Sidekiqをv6にダウングレードするとエラーが出ずに動作することを確認できましたが、メジャーバージョンを下げることは影響範囲のことを考慮すると懸命でないと判断し、sidekiq-limit_fetchのバグ修正を優先させました。

発生していたバグ

問題となるsidekiq-limit_fetchのバグは2つありました。

  • キューの設定が読み込めない
  • Sidekiq::BasicFetchの引数に渡す値が間違えていた

キューの設定が読み込めない

原因

sidekiq.ymlに設定されているキューの名前を取得しto_sもしくはto_symで型を変換する処理があったのですが、コード1のように、重みづけも設定されていると配列が取得されるため型の変換でエラーが起きていました。

コード1

:queues:
  - ['high_priority', 2]
  - ['low_priority', 1]

発生していたエラー

undefined method `to_sym' for ["active_storage_analysis", 4]:Array
queue.process_limit = @process_limits[queue_name.to_s] || @process_limits[queue_name.to_sym]
                                                                                        ^^^^^^^
Did you mean?  to_s
               to_set
/Users/me/.rvm/gems/ruby-3.1.2@project/gems/sidekiq-limit_fetch-4.4.0/lib/sidekiq/limit_fetch/queues.rb:121:in `apply_process_limit_to_queue'

解決方法

キューを受け取った時に、文字列か配列かを判定して必ずキューの名前だけを取得する処理を入れました。

実装した修正コミット

@queues = config[:queues].map do |queue|
  if queue.is_a? Array
    queue.first
  else
    queue
  end
end.uniq

GitHubのコミット

https://github.com/deanpcmad/sidekiq-limit_fetch/pull/155/commits/97084a6352bd4f51b6dd55232ffe557c71e98475

Sidekiq::BasicFetchの引数に渡す値が間違えていた

原因

sidekiq-limit_fetchの処理でSidekiq::BasicFetchにSidekiqのconfigを渡す処理があります。Sidekiq v6ではSidekiqモジュール内にconfigが含まれており、sidekiq-limit_fetchの実装もSidekiqモジュールからconfigを取得する実装になっていました。しかし、Sidekiq v7からconfigは別モジュールに切り出されてconfigの取得方法が変わったため、sidekiq-limit_fetchもSidekiqの変更に合わせて実装を変える必要がありました。

解決方法

Sidekiqのバージョンが7であるときは、Configモジュール経由でconfigを取得するようにしました。

実装した修正コミット

Sidekiq::BasicFetch.new(post_7? ? Sidekiq.default_configuration.default_capsule : config).bulk_requeue(*args)

GitHubのコミット

https://github.com/deanpcmad/sidekiq-limit_fetch/pull/155/commits/b222c01b8aa1d921850121725fcc18b83afbac7c

修正してマージされたPR

https://github.com/deanpcmad/sidekiq-limit_fetch/pull/155