こちらの記事に触発されて terraform planでEventBridgeのcron式を検証するterraform providerを書いた。
以下のようにデータソースを定義すると
data "cronplan_expr" "every_weekday" { expr = "cron(5 0 ? * ? *)" }
terraform planの時にエラーが表示される。
検証するようにした。rate()
とat()
については今のところ無視しているが、そのうち検証するようにしたい。
EventBridgeのday-of-weekの奇妙な動作について
EventBridgeのcron式にはいくつかコーナーケースがあって、例えば
0 0 31 * ? *
: 31日がない月はどうなるか?0 0 ? * FRI#5 *
: 5週目の金曜日がない月はどうなるか?0 0 1W 10 ? *
: 10/1が土日の場合はどうなるか?
…等々。
一応、EventBridgeのコンソールの出力を正としてそれに合わせるようにしているが、何日、何ヶ月もかけて検証はできないので完全に合っているかはわからない。
そのようなコーナーケースの動作としてday-of-weekのL
の動作がある。*1
通常、cron(0 0 ? * 6L *)
と書くと*2、毎月の最終の金曜日がスケジュールされる。
# cron(0 0 ? * 6L *) Fri, 27 Oct 2023 00:00:00 Fri, 24 Nov 2023 00:00:00 Fri, 29 Dec 2023 00:00:00 Fri, 26 Jan 2024 00:00:00 Fri, 23 Feb 2024 00:00:00
しかしL
の前に数字や曜日を書かないと、SAT
と書いたのと同じ動作になる。
# cron(0 0 ? * L *) = cron(0 0 ? * SAT *) Sat, 07 Oct 2023 00:00:00 Sat, 14 Oct 2023 00:00:00 Sat, 21 Oct 2023 00:00:00 Sat, 28 Oct 2023 00:00:00 Sat, 04 Nov 2023 00:00:00
とても奇妙な仕様なのでL
単独で使うのは避けた方がいいと思う。
ちなみに、ウェブを調べていたらJavaのQuartz Job Schedulerが同じ仕様だった。
L (“last”) - ... If used in the day-of-week field by itself, it simply means “7” or “SAT”. ... When using the ‘L’ option, it is important not to specify lists, or ranges of values, as you’ll get confusing/unexpected results.
L ( "last" ) - ... 曜日フィールドで単独で使用される場合は、単に「7」または「SAT」を意味します。... 'L' オプションを使用する場合は、混乱したり予期しない結果が得られるため、リストまたは値の範囲を指定しないことが重要です。
なので、EventBridgeのcron式のパースには秒を無視したQuartzが使われているのではないかと疑っている。
さらに追記
cron式のSUN=0をSUN=1に書き換えた犯人がQuartzではないかと考えているが、ログは見つけられていない…
追記2
なんだとぉ
— Genki Sugawara (@sgwr_dts) 2023年10月1日
> The 'L' and 'W' characters can also be combined in the day-of-month field to yield 'LW', which translates to *"last weekday of the month"*.https://t.co/dWJ195Bk9A
げ、マジだ… pic.twitter.com/tWQ6bxYVJx
— Genki Sugawara (@sgwr_dts) 2023年10月1日
※対応しました https://github.com/winebarrel/cronplan/pull/45/files?w=1
*1:https://github.com/winebarrel/cronplan#about-the-behavior-of-l-in-day-of-week
*2:できれば6L→FRILと書いた方がよいと思う