1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

時計が巻き戻っても、過去の画面に戻さないスケジューラ

1
Posted at

時計が巻き戻っても、過去の画面に戻さないスケジューラ

時計どおりに動かすだけでは足りない

店頭のサイネージを、10時に「営業中」、18時に「本日は終了しました」へ切り替えるとします。

単純に現在時刻だけから表示内容を決めると、時計が18時から15時へ戻ったとき、画面も「営業中」に戻ってしまいます。NTPの補正やRTCの異常を考えると、これは机上の話ではありません。

Glyphaでは、次の方針にしました。

時刻は戻ってもよい。ただし、システムの履歴は戻さない。

「最後に消化した時刻」を保存する

Glyphaのスケジューラは、現在時刻だけでなく、どこまで切り替えを消化したかを示すカーソルを持ちます。

たとえば、日次スケジュールが次の内容だとします。

10:00 → open
13:00 → afternoon
18:00 → closed

14時に問い合わせが来たら、10時の画面を経由せず、13時の afternoon を直接選びます。カーソルも13時まで進めます。

その後、時計が11時へ戻っても、カーソルより前の切り替えはすでに消化済みです。open は再生せず、afternoon を表示し続けます。

Goの実装では、半開区間 (cursor, now] にある最新の切り替えだけを返します。

func (d *Daily) LatestBetween(cursor, now int64) (Occurrence, bool, error) {
	if now <= cursor {
		return Occurrence{}, false, nil
	}

	o, err := d.ApplicableAt(now)
	if err != nil {
		return Occurrence{}, false, err
	}
	if o.Second <= cursor {
		return Occurrence{}, false, nil
	}
	return o, true, nil
}

ポイントは、now <= cursor なら何もしないことです。時計が戻っても、消化済みの履歴は巻き戻りません。

また、現在時刻に適用される場面を直接計算するため、通信が途切れて何時間経過しても、中間の画面を順番に再生する必要はありません。

再起動しても履歴を失わない

カーソルがメモリにしかなければ、再起動時に過去の画面が復活します。

そこでGlyphaは、カーソルと現在の表示対象をSQLiteへ同じトランザクションで保存し、コミットに成功してから応答します。

カーソルと表示対象を保存
        ↓
コミット成功
        ↓
画面へ応答

保存に失敗した場合は、曖昧な状態で処理を続けず、サーバーを失敗状態にします。画面側は、その間も最後に正常表示できた内容を出し続けます。

代わりに失うものもある

この方式にも弱点があります。

時計が誤って翌年へ飛び、そこでカーソルを進めてから正しい日時へ戻ると、現在時刻がカーソルへ追いつくまで切り替わりません。Glyphaでは、新しいコンテンツを公開してカーソルを初期化する運用で復旧します。

「過去を再生しないこと」と「大きな時計異常から自動復旧すること」は、単純には両立しません。Glyphaはサイネージの用途を考え、前者を選びました。

まとめ

時計に従って表示を切り替えるシステムでも、判断材料を現在時刻だけにすると、時計の巻き戻しで過去を再生してしまいます。

Glyphaでは、次の3点でこれを防いでいます。

  • 切り替え時刻との完全一致ではなく、未消化のうち最新の場面を選ぶ
  • 消化済み範囲をカーソルで表し、一方向にだけ進める
  • カーソルと表示対象を永続化してから応答する

時刻は信用できなくても、履歴を単調に進めることはできます。

スケジューラを設計するときは、「何時なら何を出すか」だけでなく、時計が戻ったときに過去を再生するのかを先に決めておくと、実装の方針が明確になります。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?