diff --git a/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts b/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts index 322c11a..c0384d9 100644 --- a/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts +++ b/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts @@ -77,31 +77,20 @@ export class RedisSelfUpdatingETARepository extends BaseRedisETARepository imple this.shuttleRepository.removeListener(ShuttleRepositoryEvent.SHUTTLE_WILL_ARRIVE_AT_STOP, this.handleShuttleWillArriveAtStop); } - private handleShuttleUpdate(shuttle: IShuttle) { - // TODO: handle shuttle update - } + private async handleShuttleUpdate(shuttle: IShuttle) { + const lastStop = await this.shuttleRepository.getShuttleLastStopArrival(shuttle.id); + if (!lastStop) return; - private async handleShuttleWillArriveAtStop( - shuttleArrival: ShuttleStopArrival, - - ) { - const lastStop = await this.shuttleRepository.getShuttleLastStopArrival(shuttleArrival.shuttleId); - if (lastStop == undefined) return; - - const shuttle = await this.shuttleRepository.getShuttleById(shuttleArrival.shuttleId); - if (shuttle == null) return; + const lastOrderedStop = await this.shuttleRepository.getOrderedStopByRouteAndStopId(shuttle.routeId, lastStop.stopId); + const nextStop = lastOrderedStop?.nextStop; + if (!nextStop) return; let referenceCurrentTime = new Date(); if (this.referenceTime != null) { referenceCurrentTime = this.referenceTime; } - const oneWeekAgo = new Date(referenceCurrentTime.getTime() - (60 * 60 * 24 * 7 * 1000)); - const lastOrderedStop = await this.shuttleRepository.getOrderedStopByRouteAndStopId(shuttle.routeId, lastStop.stopId); - const nextStop = lastOrderedStop?.nextStop; - if (nextStop == null) return; - const travelTimeSeconds = await this.getAverageTravelTimeSeconds({ routeId: shuttle.routeId, fromStopId: lastStop.stopId, @@ -115,6 +104,7 @@ export class RedisSelfUpdatingETARepository extends BaseRedisETARepository imple const elapsedTimeMs = referenceCurrentTime.getTime() - lastStop.timestamp.getTime(); const predictedTimeSeconds = travelTimeSeconds - (elapsedTimeMs / 1000); + // TODO: update multiple ETAs await this.addOrUpdateEta({ secondsRemaining: predictedTimeSeconds, shuttleId: shuttle.id, @@ -123,4 +113,94 @@ export class RedisSelfUpdatingETARepository extends BaseRedisETARepository imple updatedTime: new Date(), }); } + + private async handleShuttleWillArriveAtStop( + shuttleArrival: ShuttleStopArrival, + ) { + const lastStopTimestamp = await this.shuttleRepository.getShuttleLastStopArrival(shuttleArrival.shuttleId); + if (lastStopTimestamp) { + const shuttle = await this.shuttleRepository.getShuttleById(lastStopTimestamp.shuttleId); + if (!shuttle) return; + + const routeId = shuttle.routeId; + const fromStopId = lastStopTimestamp.stopId; + const toStopId = shuttleArrival.stopId; + + const travelTimeSeconds = (shuttleArrival.timestamp.getTime() - lastStopTimestamp.timestamp.getTime()) / 1000; + await this.addTravelTimeDataPoint({ routeId, fromStopId, toStopId, }, travelTimeSeconds, shuttleArrival.timestamp.getTime()); + } + } + + public async addTravelTimeDataPoint( + { routeId, fromStopId, toStopId }: ShuttleTravelTimeDataIdentifier, + travelTimeSeconds: number, + timestamp = Date.now(), + ): Promise { + const historicalEtaTimeSeriesKey = this.createHistoricalEtaTimeSeriesKey(routeId, fromStopId, toStopId); + + try { + await this.redisClient.sendCommand([ + 'TS.ADD', + historicalEtaTimeSeriesKey, + timestamp.toString(), + travelTimeSeconds.toString(), + 'LABELS', + 'routeId', + routeId, + 'fromStopId', + fromStopId, + 'toStopId', + toStopId + ]); + } catch (error) { + await this.createHistoricalEtaTimeSeriesAndAddDataPoint( + historicalEtaTimeSeriesKey, + timestamp, + travelTimeSeconds, + routeId, + fromStopId, + toStopId + ); + } + } + + + private async createHistoricalEtaTimeSeriesAndAddDataPoint( + timeSeriesKey: string, + timestamp: number, + travelTimeSeconds: number, + routeId: string, + fromStopId: string, + toStopId: string, + ): Promise { + try { + await this.redisClient.sendCommand([ + 'TS.CREATE', + timeSeriesKey, + 'RETENTION', + '2678400000', // one month in milliseconds + 'LABELS', + 'routeId', + routeId, + 'fromStopId', + fromStopId, + 'toStopId', + toStopId + ]); + await this.redisClient.sendCommand([ + 'TS.ADD', + timeSeriesKey, + timestamp.toString(), + travelTimeSeconds.toString() + ]); + } catch (createError) { + await this.redisClient.sendCommand([ + 'TS.ADD', + timeSeriesKey, + timestamp.toString(), + travelTimeSeconds.toString() + ]); + } + } + }