通知は接続から二十分後に現れました。その下のカウンターは前の朝から、あるいはアカウントが最後に認証した時点から動いており、警告のどこにもどちらなのか書かれていませんでした。これが症状です。目の前の接続ではなく、別の何かに結びついたリマインダーです。

直し方は、より良い警告ではありません。要件がどの時計を指しているのかを決め、その時計の中に存在する対象にタイマーを結びつけることです。

何が発火し、何を数えていたのか

三つのもっともらしい発生源が同じメッセージを生みます。カレンダーの規則は決まった現地時刻に動き、トンネルのことを何も知りません。クライアントのカウンターは接続が上がっている間だけ積み上がり、再接続を越えて残ります。ゲートウェイのポリシーはサーバー側でセッションを失効させ、その前に警告を送ります。

セッションについて語るのは最後の二つだけで、しかもその二つも一致しません。クライアントのカウンターはローカルのプロセスが観測したものを測り、ゲートウェイは認証して計上したものを測ります。スリープ、ネットワークの切り替え、監視プロセスの再起動は両者を何時間も引き離すことがあり、だから警告と強制失効がずれます。

ひとつの要件の背後にある三つの時計

まず、本当に欲しい文を書き出してください。ゲートウェイがこの接続を終える前に警告することは、接続時間が一日たってから思い出させることと同じ要件ではありません。このセッションが23時間続いていると報告することとも違います。どの版も別の出来事を名指ししており、別のコンポーネントがそれに答える必要があります。

次に、データが存在するか確認します。ローカルの開始タイムスタンプはサーバーに依存せずセッションの経過時間を与えます。ゲートウェイのポリシーは残りの寿命を与えますが、ゲートウェイがそれを公開している場合に限ります。利用レポートは事後に期間を与えるもので、事前の通知を動かすことはできません。

タイマーはアカウントではなくセッションに結びつける

まず対象を選びます。アカウントは複数の端末と複数の同時セッションを持てるので、ユーザー名をキーにしたリマインダーでは、どの接続がその時間に達したのか分かりません。プロファイルとそのアクティベーションをキーにし、アクティベーションが終わったら保留中の通知を取り消します。

Evidence you can readWhat it establishesWhere it misleads
Connection state changes to activeA session started nowDoes not carry the gateway's own session identifier
Duration reported at disconnectTotal service time for that sessionArrives too late for any advance notice
Interim usage updateTime accounted up to that updateStaleness equals the update interval
Local timestamp taken at activationAge of your observationResets whenever the observer restarts

この表は自分の通知器のための契約であり、どのクライアントのコールバックAPIの説明でもありません。導入した製品が接続状態について文書化しているものが、結びつけるべき情報源です。認証イベントしか公開していない場合は、そう明言し、セッションを推測するのではなく粗い挙動を受け入れてください。

短いしきい値で試す

一日がかりのタイマーを一日がかりの待ち時間でデバッグしてはいけません。設定可能なしきい値を追加し、三十秒に設定して、四つの遷移を順に実行します。接続、待機、切断、再接続です。各遷移はちょうど一つの状態変化を生むべきで、再接続は古い期限を引き継ぐのではなく新しい期限を設定すべきです。

# current connection state and profile identity
nmcli -f GENERAL.STATE,GENERAL.CONNECTION connection show work

# the notifier unit you wrote: does it restart the deadline or resume it?
journalctl --user -u vpn-timer.service --since "-5 min" -o cat

文言ではなくタイムスタンプを見てください。前のセッションの開始時刻を伴って届く通知は間違った対象に結びついており、一つの期限に対して二度届く通知は、送信済みフラグが一度も保存されなかったことを意味します。

スリープ、再接続、そして届かなかった配信

スリープは両方の素朴な設計を壊します。単調なカウントダウンはマシンが眠っている間止まり、壁時計の期限は動き続け、スリープ中に発火したタイマーは遅れて、あるいはまったく届きません。要件がどちらの挙動を必要とするかを決め、しきい値をまたいでマシンをスリープさせて確認してください。

配信にも同じ注意が必要です。通知を表示できない場合はキューに入れ、最終的に表示する前に対象のセッションがまだ存在するか再確認してください。そうしなければ、すでに終わった接続について利用者に警告することになります。強制切断と資格情報の更新はこの経路の外に置きます。接続の運命を静かに変えるリマインダーは、通知の衣装を着たポリシー判断だからです。

関連記事