Skip to content

バックグラウンドサーバースクリプトに cron 式を直接指定する ​

第1版作成 最終更新 (日本時間)
確認バージョン1.5.1.01.5.8.1

1.5.8.1 のバックグラウンドサーバースクリプトのスケジュールは、毎時・毎日・毎週・毎月・一回のみの 5 種類から選び、時刻や曜日を入力する方式です。このページは、cron 式を直接入力できるようにし、入力中に「どう動くか」(説明文と次回実行日時)を表示する本体改修の設計メモで、本体の標準機能ではありません。調査は 1.5.1.0 を対象に行い、前提にした現行実装は 1.5.8.1 のソースで確かめています。

前提にした現行実装 ​

詳しくは バックグラウンドサーバースクリプトの仕組み の「スケジュールと cron 式」にあります。要点は次のとおりです。

  • スケジュール(BackgroundSchedule)は種別ごとに別のプロパティ(ScheduleHourlyTime・ScheduleDailyTime・ScheduleWeeklyWeek・ScheduleWeeklyTime・ScheduleMonthlyMonth・ScheduleMonthlyDay・ScheduleMonthlyTime・ScheduleOnlyOnceTime)を持ちます。使わない種別のプロパティも JSON に残ります(BackgroundSchedule.cs#L7-L21)。
  • GetTrigger() がこれを Quartz の 7 フィールドの cron 式に組み立て、WithCronSchedule() に渡しています(BackgroundServerScriptUtilities.cs#L112-L179)。内部はすでに cron 式なので、入力を cron 式にしても後段は変わりません。
  • 画面はテナント管理のスケジュールのダイアログで、種別のドロップダウンに応じて ServerScriptScheduleHourlyField などのフィールドセットを出し分けます(TenantUtilities.cs#L2438-L2563)。
  • サーバー側の検証は時刻の HH:mm の正規表現だけです(BackgroundScheduleValidators.cs#L22-L39)。

現行の方式でできないこと:

制約内容
分の自由度が低い毎時は 5 分刻みのドロップダウンだけ
複合条件が書けない平日だけ、第 N 曜日、9〜17 時の間だけ、など
間隔が書けない15 分ごと、3 時間ごと、など
種別が固定新しいパターンにはコードの改修が要る

Quartz の cron 式 ​

Quartz.NET の cron 式は、Unix の cron(5 フィールド)と違い 7 フィールドです。

位置フィールド値特殊文字
1秒0-59, - * /
2分0-59, - * /
3時0-23, - * /
4日1-31, - * / ? L W
5月1-12 または JAN-DEC, - * /
6曜日1-7(1 が日曜)または SUN-SAT, - * / ? L #
7年空 または 1970-2099, - * /(省略可)

日と曜日はどちらか一方を ? にします。直接入力なら、次のような指定ができるようになります。

cron 式意味
0 */15 9-17 ? * MON-FRI *平日 9:00〜17:59 に 15 分ごと
0 0 9 ? * 3#2 *毎月第 2 火曜日の 9:00
0 0 0 L * ? *毎月末日の 0:00
0 0 */3 * * ? *3 時間ごと
0 30 8,12,18 * * ? *毎日 8:30・12:30・18:30

Quartz.NET の CronExpression クラスで検証と次回実行日時の計算ができます。

csharp
bool isValid = CronExpression.IsValidExpression("0 */15 9-17 ? * MON-FRI *");
var cron = new CronExpression("0 */15 9-17 ? * MON-FRI *");
cron.TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Asia/Tokyo");
DateTimeOffset? next = cron.GetNextValidTimeAfter(DateTimeOffset.UtcNow);

画面の設計 ​

既存の簡易設定を残すかで 3 案を比べ、B を採用します。

案長所短所
A:cron 式だけデータが単純になるcron に慣れない人には難しい
B:簡易設定と cron 式を切り替え既存の操作と設定データをそのまま使える画面が少し複雑になる
C:簡易設定を cron 式に変換して表示学習になるcron 式から簡易設定への逆変換が難しい

図を読み込み中…

簡易設定から cron 式に切り替えたとき、今の設定を cron 式にして表示すると学習にもなります。

データと処理の変更 ​

  • BackgroundSchedule に CronExpression(文字列)を追加し、ScheduleType に "cron" を足します。既存の種別とプロパティは変えません。
  • GetTrigger() に case "cron": を足し、CronExpression.IsValidExpression() が通ればその文字列をそのまま使います。現行は未知の種別で ArgumentException を投げるので(BackgroundServerScriptUtilities.cs#L165-L166)、分岐の追加は必須です。タイムゾーンの決め方は既存のままです。

プレビュー ​

方式応答実装コストサーバー負荷
A:クライアント側の JavaScript ライブラリ即時低なし
B:サーバーの API(Ajax)遅れあり中あり
C:Svelte のコンポーネント+ライブラリ即時中なし

説明文はクライアント側(方式 A)で作り、次回実行日時は Quartz の独自拡張(L・W・#)とタイムゾーンを正しく扱えるサーバー側で計算します。

ライブラリ機能サイズ日本語Quartz の 7 フィールド
cronstruecron 式 → 説明文約 10 KB対応対応
cron-parser次回実行日時約 15 KB-5 フィールドだけ

cronstrue は ?・L・W・#・年・秒を正しく説明文にします。dayOfWeekStartIndexZero: false を必ず指定します。 既定値のままだと曜日の数字を Unix 式(0 が日曜)で解釈し、Quartz(1 が日曜)と 1 日ずれます(MON などの名前は影響を受けません)。

javascript
function describeCron(cronExpression) {
    try {
        return cronstrue.toString(cronExpression, {
            locale: 'ja',
            dayOfWeekStartIndexZero: false, // 必須:Quartz は 1 が日曜
            use24HourTimeFormat: true,
        });
    } catch (e) {
        return null;
    }
}
cron 式cronstrue の出力(日本語)
0 */15 9-17 ? * MON-FRI *15 分ごと, 09:00 と 17:59 の間、月曜日 から 金曜日 まで
0 0 9 ? * 2#2 *09:00、月のうち 2 番目 月曜日
0 0 0 L * ? *00:00、最終日に
0 0 12 15W * ? *12:00、月の 15 日の直近の平日 に
0 0 12 ? * 6L *12:00、月の最後の 金曜日 に
0 0 9 15 3 ? 202609:00、月の 15 日目、3月 でのみ、2026 でのみ
*/30 * * * * ? *30 秒ごと

図を読み込み中…

プレビュー用には TenantsController に、CronExpression と TimeZoneId を受け取り、IsValidExpression() の結果と次回実行日時 5 件を返すエンドポイントを足します(任意)。

検証 ​

層タイミング内容
クライアント入力中フィールド数が 6〜7 か、cronstrue で解釈できるか
サーバーの APIプレビュー時CronExpression.IsValidExpression() と次回実行日時の計算
サーバーの保存時追加・変更空でないこと、IsValidExpression()、次回実行日時があること(過去しか指さない式を拒否)

保存時の検証は BackgroundScheduleValidators に足し、エラーの種類として InvalidCronExpression を新設します。

改修箇所 ​

ファイル内容
Libraries/Settings/BackgroundSchedule.csCronExpression を追加
Libraries/Settings/BackgroundServerScriptUtilities.csGetTrigger() に case "cron"
Libraries/Settings/BackgroundScheduleValidators.cscron 式の検証
Models/Tenants/TenantUtilities.cs種別に "cron" を足し、入力欄とプレビュー領域を追加
Controllers/TenantsController.csプレビュー用のエンドポイント(任意)
Libraries/General/Error.csエラーの種類 InvalidCronExpression とメッセージ
Implem.DefinitionAccessor の表示文字列cron 関連の文言
Implem.PleasanterFrontend/wwwroot/src/scripts/generals/tenants.js入力イベントでの説明文表示とプレビューの要求
Implem.Pleasanter/wwwroot/Extensions/cronstrue の minify 版を配置(既存の mermaid-11.9.0.min.js などと同じ置き方)

関連ページ ​

変更履歴

第1版バックグラウンドサーバースクリプトの仕組みと、サーバースクリプトの他言語対応・DLL 実行・cron スケジュールの改修・設計メモを追加