- Add `currentTrainMetadata.ts` to manage carrying forward official position metadata between train snapshots. - Introduce `lineDisplayName.ts` for mapping line IDs to display names. - Create `officialPositionCache.ts` for parsing and serializing official position data with cache validation. - Enhance `officialPositionService.ts` to support persistent caching of official positions and improve resolver functionality. - Update `requestCoordinator.ts` to allow cancellation of polling requests without disposing of the coordinator. - Modify `trainTimeFiltering.ts` to incorporate line ID context when checking for duplicate train data. - Refactor `useCurrentTrain.tsx` to support polling for current train data with official position enrichment. - Add tests for new features, including persistent cache behavior and handling of ambiguous train data.
7.1 KiB
JR四国データモデル契約(素案)
Status: Phase 1.5 contract only
この文書は、既存APIレスポンスや画面処理を一括移行するものではない。駅DBとアプリの責任分界を先に固定し、将来のRepository/API整理でidentityを再び混同しないための境界である。
Physical Station
Physical Stationは、現実の一つの駅施設・旅客駅を表す概念である。物理駅ID(PhysicalStationId)はBackendの駅情報DBまたは合意済みdomain masterが発行する値を使う。
アプリは駅番号から物理駅IDを算出・発明しない。Backendから対応付けが届かない間は、contract上のphysicalStationIdをnullとして扱う。
Station Stop
Station Stop(StationStopId)は、路線・方向・運行上の文脈を持つline-specificな停車点である。同じPhysical Stationに複数のStation Stopが存在し得る。
Y00とT28が同じ高松の別路線文脈を表す場合、番号を一つの物理駅IDとして扱わず、物理駅、停車点、番号、路線を別フィールドで保持する。
Station Number
Station Numberは、路線またはデータソースが付与した表示・検索用のlegacy referenceである。M12のように複数の路線・駅で再利用される可能性があるため、単独でlong-lived canonical IDにしない。
adaptLegacyStationNumber()は、legacy numberをStationIdentityの境界へ載せるだけで、physicalStationIdを埋めない。lookupLegacyStations()は曖昧な候補を全件返し、呼び出し側が路線・Backend mappingを確認する。
実データの全駅変換、既存のStationNumber検索、WebView注入処理はこのフェーズでは変更しない。
Train Identity
列車番号はidentityの一部であり、単独のcanonical keyではない。最低限、次の値を組み合わせる。
trainNumberserviceDatelineId(不明な場合はnullだが、省略しない)source(API・namespace)
必要に応じてoperatorCodeやserviceVariantを追加する。trainIdentityKey()はこれらを複合化するため、同じ列車番号でも日付、路線、sourceが違えば別keyになる。
Calendar Date
Calendar Dateは通常の暦日(YYYY-MM-DD)である。タイムゾーンを暗黙にしたJavaScript Dateをidentityの代わりに保存しない。
Service Date
Service Dateは鉄道の営業日・運行日である。アプリの表示上の暦日と一致しない場合がある。契約ヘルパーの既定境界は04:00で、00:00〜03:59のwall clockは前日のService Date、04:00以降は当日のService Dateとする。この境界はBackendとの最終合意で変更可能なpolicyであり、各処理が独自に判定してはいけない。
Wall Clock Time
Wall Clock Timeは日常の00:00〜23:59である。24時台表記をこの型へ混ぜない。parseWallClockTime()は24:00を受け付けない。
Service Minute
Service Minuteは、extended railway timeを整数分で表すpure valueである。JavaScript Dateへ直接変換しない。
00:00 = 0
23:59 = 1439
24:00 = 1440
24:30 = 1470
25:15 = 1515
parseServiceMinute()は上記のextended表記を扱う。一方、通常のwall clockを現在のService Day軸へ写像するserviceMinuteFromWallClock()では、既定04:00境界の00:30は1470になる。つまり「文字列として00:30を読む」ことと「営業日軸へ写像する」ことを分離する。
Legacy dataとの関係
既存のY00、T28、M12などの処理は直ちに変更しない。新しいAPI層やRepositoryは、legacy referenceを境界で受け取り、Backendが返すPhysicalStationId・StationStopIdとの対応をadapterで明示する。対応がないデータを推測で結合しない。
既存の運行情報・列車位置データは、今回追加した型へ一括変換せず、fixtureと境界関数から段階的に移行する。
Backendとの責任分界
Backend/domain masterが責任を持つもの:
- Physical Stationのcanonical ID発行と同一物理駅の統合
- Station Stop、路線、駅番号、営業日ルールの正式な対応表
- 列車番号・Service Date・路線・sourceを含むidentity情報
- schema version、
fetchedAt、sourceの仕様
アプリが責任を持つもの:
- contractに沿った型境界とlegacy adapter
- 欠損・曖昧なidentityを推測でcanonical化しないこと
- Service Minuteを
Dateへ押し込まずに表示・比較すること - Backend contract変更時のfixture、parser、release compatibility確認
Backendがcanonical mappingを提供するまでは、アプリのphysicalStationId: nullは未解決状態として保持する。
Official Position
OfficialPositionは、JR公式走行位置の完全一致tupleと、Backendが発行したUUIDを持つcanonical Position metadataである。アプリ側のlookup identityは、pos、line、pos_numの3値をこの順で保持する。pos_numは文字列であり、109、0279、ABCを数値化しない。
Backend responseは次のNative型へ変換する。
- positionId / pos / line / posNum
- positionType / platform / track / note
- enrichmentStatus / firstSeenAt / lastSeenAt / revision
Position metadataの解決はCurrentPositionの取得・更新とは別の処理として扱う。起動時は検証済みのOfficialPosition metadataをAsyncStorageの永続ウォームキャッシュから先に返し、次回pollでAPIを再取得する。session memory cacheとin-flight dedupeを併用し、一覧表示などの多数tupleではbounded concurrencyを使う。404はunresolvedとしてmetadataだけを欠落させ、走行位置・遅延・列車番号などを失敗させない。ネットワーク障害時も同様にCurrentPositionの表示を維持する。
Resolverのアプリ向け入口は一括解決に絞り、tupleの重複除去はResolverが所有する。未使用の管理用APIを追加せず、通信のobservabilityと上記の失敗時の表示契約を維持する。
CurrentTrainのsnapshotは、同じ列車番号でもLineを持つ在線観測を行単位で保持する。路線コンテキストがある画面では駅番号・路線の対応を選択条件にし、一般ユーザー向け表示は候補を一件に絞る。管理者向け表示だけは候補を全件表示し、行ごとのOfficialPosition metadata(platform / trackを含む)を使う。路線コンテキストがないfallbackでは、複数行のどれかへ推測で結び付けず、直前のline-specificな候補を保持する。
すべてのNative環境でOfficialPosition Backend resolverをcanonical sourceとして使う。production release / production betaはproduction Backend、experimentalはbeta Backendへ環境configで切り替える。自動fallbackは行わず、旧n8n Position masterのadapter・書き込み経路はNativeから削除する。管理権限がありUUIDとuserIDが揃った場合のみ、環境対応Frontendのcanonical編集URLをgeneralWebViewで開く。