classDiagram direction LR class CollectJob { -List~SnapshotSource~ sources -CallBudget budget -SnapshotRepository snapshots -Clock clock +collectAll() void } class SnapshotSource { <> +id() String +costPerCall() int +collect(String routeId, Instant now) Snapshot } class GbisLocationSource { -RestClient client -String serviceKey +id() String +costPerCall() int +collect(String routeId, Instant now) Snapshot } class CallBudget { -Map usedBySource -LocalDate windowDate -int dailyLimit +tryConsume(String sourceId, int cost) boolean } class Snapshot { -Long id -String sourceId -String routeId -Instant observedAt -Instant collectedAt -int normalizationVersion -List~BusObservation~ buses +from(String sourceId, String routeId, Instant observedAt, List raw) Snapshot } class BusObservation { -Long id -String vehicleId -int stationSeq -Integer remainingSeats -Integer crowded } class SnapshotRepository { <> +save(Snapshot s) Snapshot } CollectJob --> SnapshotSource CollectJob --> CallBudget CollectJob --> SnapshotRepository SnapshotSource <|.. GbisLocationSource SnapshotSource ..> Snapshot Snapshot o-- BusObservation SnapshotRepository ..> Snapshot