Experiment record
運転停止とクラウド料金確定が非同期になるとき:リンナイ乾太くんで検証した遅延料金の安全な確定ロジック
物理的な運転停止とクラウド料金更新が非同期になる機器で、停止後のrunを保持し、最初の帰属可能な料金変化で確定する状態機械をfield validationした。修正後4件の料金遅延をすべて自動確定した。
概要
クラウド接続機器では、機器が「停止」した時点で関連する料金情報まで確定しているとは限りません。
AIEL-2026-0008は、リンナイRDT-93乾太くんの運転が終了した後も、クラウド料金が未確定のまま残った実例から始まりました。最初の課題は料金を推定することではなく、後で現れるAPI値を安全に帰属できるまで、停止済みrunをどう保持するかでした。
collectorは、停止と料金確定を別の状態遷移として扱うよう再設計しました。
- 機器の停止イベントを保持する。
- 料金が変わらない間はrunを未確定のまま残す。
- 最初の帰属可能な停止後料金変化を観測した時点で即時確定する。
- 2時間変化がなければlate状態へ移し、その後もbounded reconciliationを続ける。
- 帰属が曖昧な後続値を推測で別runへ割り当てない。
修正後のfield validationでは、2時間を超えて料金変化が現れずlate pathへ入った独立ケースを4件確認しました。4件すべてが、その後の最初の帰属可能な料金変化で手動補正なしに自動確定しました。停止から確定までの丸めた遅延は159〜540分で、review時点に未解決のlate caseは残っていません。
これにより通常のdelayed-settlement pathはproductionでfield validationできました。一方、料金変化が次run開始境界で初めて現れる場合の別branchはcode上保守的に実装されていますが、今回の4件はいずれも次run開始前に確定しており、このboundary branchは未実行のedge conditionとして残します。
実験の背景
telemetry systemでは、物理的な処理完了とクラウド側の集計完了を同じイベントとして扱いがちです。しかし、異なるAPI fieldやbackend processが別タイミングで更新される場合、この仮定は安全ではありません。
今回のcollectorでは、乾太くんの状態がOFFになった後も、料金APIが運転中と同じ値を返し続けるケースがありました。また旧settlement設計では、最初の有効な料金変化を観測した後も、同じ値を複数回確認してから確定する構造でした。
この設計では、すでに帰属可能な変化を観測できていても後続pollに依存します。後続観測が欠ければ、不要な確定遅延や未確定runを生む可能性があります。
第三者へ再利用できる問いは次のようになります。
機器状態では運転終了が確認できているが、クラウドで計算される料金・集計値が後から確定する場合、collectorはどの時点でrunを閉じるべきか。
安全な設計には、即時確定や推測補完ではなく、Evidenceを保持したpending stateが必要です。
実験方法
保持された非公開の運転ログ・診断ログと、現行production collector sourceを確認しました。
現行collectorは、状態APIと料金APIの両方を毎分取得します。無変化時のdiagnostic heartbeat行だけを5分間隔へ間引いています。したがって、diagnostic rowが5分間隔だからといって、API polling自体が5分周期という意味ではありません。
settlementでは、active中に取得した最後の完全な料金値をbaselineとして保持します。OFF後は次のルールで処理します。
- 不完全な料金payloadではrunを確定しない。
- 料金がactive baselineと同じ間はrunを未確定のまま保持する。
- baselineと異なる完全な料金値を最初に観測し、帰属が明確ならその時点で確定する。
- 120分変化がなければlate reconciliationへ移行する。
- late reconciliationはさらに24時間のbounded windowで継続する。
- unresolvedな旧runを保持したまま新runを観測した場合、明示的な帰属条件を満たすときだけ旧runを確定し、条件を満たさなければ推測料金を割り当てず未確定として残す。
修正後のfield reviewでは、実際にlate pathへ入ったrunを抽出し、手動補正なしで正しく自動確定されたかを確認しました。
公開するのはsanitizedした集約結果だけです。個別家庭の運転時刻、料金値、run ID、installation固有情報、production sourceは公開しません。
実験ログ
最初に確認したfailure mode
少なくとも1件で、乾太くんが停止した後も料金が確定していませんでした。
この時点で、運転停止と料金確定は別イベントであることが分かりました。
安全な補正原則として、後から現れた料金値は、保持された観測から対象runへ帰属できる場合だけ利用します。運転が終わったという理由だけで料金や使用量を推測しません。
状態機械の再設計
旧settlement設計では、最初の有効な料金変化を観測した後にも追加の同値sampleを要求していました。
修正版では、中心となる遷移を次のようにしました。
OFF + 料金変化なし → unresolved
unresolved + 最初の帰属可能な料金変化 → finalized
2時間変化がなければ、
unresolved → pending late reconciliation
へ移し、runを捨てずにbounded observationを続けます。
修正後の実運用検証
再設計後、実際にlate pathへ入った独立運転を4件確認しました。
4件すべてが、その後にsettled_late_api_first_cost_change相当の経路で自動確定しました。停止から確定までの丸めた遅延は、
159, 273, 343, 540分
でした。
4件とも手動補正は不要で、review時点に未解決のlate caseは残っていません。
重要なのは、ある特定の遅延時間が標準だと分かったことではありません。4ケースしかないため遅延分布を一般化できません。今回確認できたのは、設計対象だったfailure modeがproductionで再発し、修正版状態機械が繰り返し自動回収できたことです。
残っているboundary condition
今回の遅延4ケースは、いずれも次の乾太くんrunが始まる前に確定しました。
現行collectorには、旧runがlateのまま次run開始を観測した場合の別branchもあります。旧runのbaseline、最後のpost-OFF値、new-run boundaryで初めて現れた変化が明示条件を満たす場合だけ旧runへ帰属し、それ以外は未確定として残します。
このbranchはcode上では確認済みですが、今回の4件では実行されていません。そのためfield-validatedとは表現しません。
結論
このcollectorでは、機器停止とクラウド料金確定を別イベントとして扱う必要があります。
実運用で検証できたpatternは次のとおりです。
- 停止したrunを保持する。
- active中の最後の料金をattribution baselineとして残す。
- 不完全なpayloadや変化のない料金では確定しない。
- 最初の帰属可能な停止後料金変化で確定する。
- 未解決runはbounded late-reconciliation stateへ残す。
- 曖昧なcross-run attributionでは、推測値より明示的な未確定を優先する。
修正後の独立した料金遅延4件でこの設計がproduction実行され、4件すべてが手動補正なしに自動確定しました。これにより本Experimentの主要Objectiveは完了したと判断します。
一方で、すべての料金遅延が同じupstream原因で起きること、159〜540分が一般的な遅延分布であること、競合する次run境界でのlate attribution branchがfield validation済みであることまでは結論しません。
証拠区分のまとめ
このExperimentで得られた情報のEvidence Stateは次のとおりです。
各Evidence Stateの意味はEvidence State(証拠状態)を参照してください。
| 記録内容 | Evidence State | 根拠 |
|---|---|---|
| 乾太くん停止と料金確定は異なる時刻に観測され得る | OBSERVED | 保持運転ログ・診断ログ |
| 現行collectorは状態・料金APIを毎分取得し、無変化diagnostic heartbeatだけ5分に間引く | VERIFIED | 現行production source |
| first attributable post-stop cost changeで確定し、bounded late reconciliationを保持する | VERIFIED | 現行production source |
| 修正後の料金遅延4件はlate pathへ入り、4件すべて自動確定した | VERIFIED | 保持production運転ログ・診断ログ |
| 観測された4件の停止→確定遅延は159〜540分 | OBSERVED | sanitized field-validation summary |
| 実装済みnew-run-boundary branchが将来の競合run late-cost caseを安全に処理できる | HYPOTHESIS | source review済みだが今回4件では未実行 |
運用上の示唆
第三者に再利用できる中心知見は、physical completionとderived cloud settlementを別の状態遷移として表現することです。
collectorは物理イベントのidentityを保持したまま、遅延fieldが安全に帰属できるまで待つ方が安全です。OFF時点でrunを完全に閉じ、その後に現れた「次の値」を無条件で貼り付ける設計は、別runへの誤帰属を招きます。
このpatternは、遅延料金だけでなく、cloud-computed summary、billing event、post-processing result、energy estimateなど、物理イベントより後に集計値が確定するtelemetryにも応用できます。
ただし本質は「一定時間待てば次の値を信用する」ことではありません。必要なのは、その値をどのeventへ帰属できるかというEvidenceです。
post-fix validationのsanitized集約はpost-fix-validation-summary.jsonで公開します。
実験データについて
Raw運転ログ、診断ログ、production sourceはaudit用に非公開で保持します。公開記事には、個別家庭の運転時刻、個別料金、run identifier、installation identifierなど第三者理解に不要なtelemetryは含めません。
料金と設定単価から換算したガス使用量は推定値であり、ガスメーターによる直接実測値とは扱いません。
機械可読な実験記録
このExperimentの機械可読な正本記録をJSONとして公開しています。
AIEL-2026-0008 experiment.json
関連実験
AIEL-2026-0005は同じRinnai収集系を対象にしていますが、認証障害を扱う別Objectiveです。AIEL-2026-0008は停止後の非同期料金確定とreconciliationを対象とします。