お仕事中に遭遇したRubyの不具合のお話です。
Problem
2025年2月28日、お仕事で運用しているRedmineで次のような問題が発生しました:
- チケットの変更履歴に記録される変更前のチケットの「開始日」(
start_date
)や「期日」(due_date
)に「2025年2月29日」の何時何分(例:2025-02-29 18:00:00 +0900
)という不正な日時が記録され、チケットページ表示時にエラーとなる - チケットの変更履歴の作成日(
created_on
)に、2月28日現在にもかかわらず、「2025年3月1日」の何時何分(例:2025-03-01 16:44:36
)という不正な日時が記録され、変更履歴の表示内容と表示順序が狂う
この不具合は Ruby v3.1.4 で発生します。
2025年2月27日までは問題発生はなく、28日になり発生、3月1日を迎えて収束しました。
試みに、サーバーのシステム時刻を28日に戻すと事象再現しました。
おそらく26年以降も同じ問題が起こるのでは?と想像しています。
28日に事象発生した当時、同じ画面オペでも不具合が発現するときとしない時があり。後日再現実験した折も厳密にどういう条件であれば発現をするのかが掴みきれませんでした。
システム時刻は28日9時より前なのか後なのか、28日0時や28日9時を迎える前にhttpdのプロセスが起動しているかどうか、などなど
なお、少なくとも1つ目の事象は、私がお仕事で運用しているRedmineが「開始日や期日に、日付ではなく日時を入力できるよう、カスタマイズされている」という背景もあって発現している可能性が高いです。
Solution
本件はRuby v3.1.4の実装に潜む、閏年の処理の不具合に起因するようです。
この事象はうるう日の午前0時から9時までに起動したプロセスでのみ再現するサーバー障害で報告されているものと同じ原因のように見受けられます。
この記事で報告されている事象は閏年であった2024年2月29日に発生したものですが、閏年でない2025年にも別のかたちで問題が発生しました。
対策として考えられるものをいくつか列挙します:
- プランA: Ruby 3.2系にアップグレード
- プランB: Webサーバーを再起動
- プランC: 2月28日が終わる(3月1日0時)のを待つ
今回は事象そのものの性質が掴みきれておらず、journals
表のcreated_on
列やjournal_details
表のold_value
列をデータメンテしつつのプランC。
今後についてはプランAを有望視しつつ、Redmine側のビジネスロジックのカスタマイズも選択肢として考えています(前述の通り、私が運用しているRedmineはすでにカスタマイズが入ってしまっているので・・・)。