From b7a25a6115a8ea40011ee9e837b3b3a8e0ec2ce6 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 16 Jan 2025 21:07:44 -0800 Subject: [PATCH 1/5] add repository methods to clear all data --- src/repositories/GetterSetterRepository.ts | 7 ++++++ .../UnoptimizedInMemoryRepository.ts | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/repositories/GetterSetterRepository.ts b/src/repositories/GetterSetterRepository.ts index ce50567..ddcf68b 100644 --- a/src/repositories/GetterSetterRepository.ts +++ b/src/repositories/GetterSetterRepository.ts @@ -18,4 +18,11 @@ export interface GetterSetterRepository extends GetterRepository { addOrUpdateStop(stop: IStop): Promise; addOrUpdateOrderedStop(orderedStop: IOrderedStop): Promise; addOrUpdateEta(eta: IEta): Promise; + + clearSystemData(): Promise; + clearRouteData(): Promise; + clearShuttleData(): Promise; + clearStopData(): Promise; + clearOrderedStopData(): Promise; + clearEtaData(): Promise; } diff --git a/src/repositories/UnoptimizedInMemoryRepository.ts b/src/repositories/UnoptimizedInMemoryRepository.ts index e992531..c24a3c5 100644 --- a/src/repositories/UnoptimizedInMemoryRepository.ts +++ b/src/repositories/UnoptimizedInMemoryRepository.ts @@ -147,4 +147,28 @@ export class UnoptimizedInMemoryRepository implements GetterSetterRepository { this.etas.push(eta); } } + + public async clearSystemData() { + this.systems = []; + } + + public async clearShuttleData(): Promise { + this.shuttles = []; + } + + public async clearEtaData(): Promise { + this.etas = []; + } + + public async clearOrderedStopData(): Promise { + this.orderedStops = []; + } + + public async clearRouteData(): Promise { + this.routes = []; + } + + public async clearStopData(): Promise { + this.stops = []; + } } \ No newline at end of file From 6176dd9f5a49046f2b604f4b21715c552db8bfce Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 16 Jan 2025 21:07:49 -0800 Subject: [PATCH 2/5] call methods to clear data --- src/loaders/RepositoryDataLoader.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/loaders/RepositoryDataLoader.ts b/src/loaders/RepositoryDataLoader.ts index c4996f1..efe4298 100644 --- a/src/loaders/RepositoryDataLoader.ts +++ b/src/loaders/RepositoryDataLoader.ts @@ -48,6 +48,7 @@ export class RepositoryDataLoader { if (!this.shouldBeRunning) return; try { + await this.clearAllData(); await this.fetchAndUpdateSystemData(); await this.fetchAndUpdateRouteDataForExistingSystems(); await this.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems(); @@ -60,6 +61,15 @@ export class RepositoryDataLoader { this.timer = setTimeout(this.startFetchDataAndUpdate, timeout); } + private async clearAllData() { + await this.repository.clearRouteData(); + await this.repository.clearSystemData(); + await this.repository.clearEtaData(); + await this.repository.clearStopData(); + await this.repository.clearOrderedStopData(); + await this.repository.clearShuttleData(); + } + private async fetchAndUpdateSystemData() { const params = { getSystems: "2", From e4b08be1e4c2b0277fc5c833b142b25e6b92f316 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 16 Jan 2025 21:29:51 -0800 Subject: [PATCH 3/5] clear data individually instead of all at once --- src/loaders/RepositoryDataLoader.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/loaders/RepositoryDataLoader.ts b/src/loaders/RepositoryDataLoader.ts index efe4298..04e2c21 100644 --- a/src/loaders/RepositoryDataLoader.ts +++ b/src/loaders/RepositoryDataLoader.ts @@ -48,11 +48,15 @@ export class RepositoryDataLoader { if (!this.shouldBeRunning) return; try { - await this.clearAllData(); + await this.repository.clearSystemData(); await this.fetchAndUpdateSystemData(); + await this.repository.clearRouteData(); await this.fetchAndUpdateRouteDataForExistingSystems(); + await this.repository.clearStopData(); await this.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems(); + await this.repository.clearShuttleData(); await this.fetchAndUpdateShuttleDataForExistingSystems(); + await this.repository.clearEtaData(); await this.fetchAndUpdateEtaDataForExistingOrderedStops(); } catch (e) { console.error(e); @@ -61,15 +65,6 @@ export class RepositoryDataLoader { this.timer = setTimeout(this.startFetchDataAndUpdate, timeout); } - private async clearAllData() { - await this.repository.clearRouteData(); - await this.repository.clearSystemData(); - await this.repository.clearEtaData(); - await this.repository.clearStopData(); - await this.repository.clearOrderedStopData(); - await this.repository.clearShuttleData(); - } - private async fetchAndUpdateSystemData() { const params = { getSystems: "2", From 33c1a512d2f7fd754caeb44c922c6817d92fb63e Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Fri, 17 Jan 2025 14:39:05 -0800 Subject: [PATCH 4/5] experiment with using RepositoryDataLoader for ETA data --- src/loaders/RepositoryDataLoader.ts | 56 +++++++++++++++++------------ src/resolvers.ts | 8 ++--- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/loaders/RepositoryDataLoader.ts b/src/loaders/RepositoryDataLoader.ts index 04e2c21..b9ec37b 100644 --- a/src/loaders/RepositoryDataLoader.ts +++ b/src/loaders/RepositoryDataLoader.ts @@ -1,5 +1,5 @@ import { GetterSetterRepository } from "../repositories/GetterSetterRepository"; -import { IRoute, IShuttle, IStop, ISystem } from "../entities/entities"; +import { IEta, IRoute, IShuttle, IStop, ISystem } from "../entities/entities"; const timeout = 10000; const systemIdsToSupport = ["263"]; @@ -201,27 +201,39 @@ export class RepositoryDataLoader { private async fetchAndUpdateEtaDataForExistingOrderedStops() { // TODO implement once I figure out how to associate ETA data with shuttles - // const systems = await this.repository.getSystems(); - // await Promise.all(systems.map(async (system: ISystem) => { - // const stops = await this.repository.getStopsBySystemId(system.id); - // - // await Promise.all(stops.map(async (stop: IStop) => { - // const orderedStops = await this.repository.getOrderedStopsByStopId(stop.id); - // - // await Promise.all(orderedStops.map(async (orderedStop) => { - // const params = { - // eta: "3", - // stopIds: stop.id, - // routeId: orderedStop.routeId, - // position: orderedStop.position, - // }; - // - // // How to get shuttle ID????????? - // // API doesn't provide it - // // I might be cooked - // })); - // })); - // })); + const systems = await this.repository.getSystems() + await Promise.all(systems.map(async (system: ISystem) => { + const stops = await this.repository.getStopsBySystemId(system.id); + await Promise.all(stops.map(async (stop) => { + const params = { + eta: "3", + stopIds: stop.id, + }; + + const query = new URLSearchParams(params).toString(); + const response = await fetch(`${baseUrl}?${query}`, { + method: "GET", + }); + const json = await response.json(); + + if (json.ETAs && json.ETAs[stop.id]) { + // Continue with the parsing + json.ETAs[stop.id].forEach((jsonEta: any) => { + // Update cache + const shuttleId: string = jsonEta.busId; + + const eta: IEta = { + secondsRemaining: jsonEta.secondsSpent, + shuttleId: `${shuttleId}`, + stopId: stop.id, + millisecondsSinceEpoch: Date.now(), + }; + + this.repository.addOrUpdateEta(eta); + }); + } + })); + })) } private async updateStopDataForSystemAndApiResponse(system: ISystem, json: any) { diff --git a/src/resolvers.ts b/src/resolvers.ts index e6dc137..29cf156 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -132,10 +132,10 @@ export const resolvers: Resolvers = { Shuttle: { eta: async (parent, args, contextValue, info) => { if (!args.forStopId) return null; - const etaForStopId = await contextValue.apiBasedRepository.getEtaForShuttleAndStopId(parent.id, args.forStopId); + const etaForStopId = await contextValue.repository.getEtaForShuttleAndStopId(parent.id, args.forStopId); if (etaForStopId === null) return null; - const stop = await contextValue.apiBasedRepository.getStopById(etaForStopId.stopId); + const stop = await contextValue.repository.getStopById(etaForStopId.stopId); if (stop === null) return null; return { @@ -149,14 +149,14 @@ export const resolvers: Resolvers = { }; }, etas: async (parent, args, contextValue, info) => { - const etasForShuttle = await contextValue.apiBasedRepository.getEtasForShuttleId(parent.id); + const etasForShuttle = await contextValue.repository.getEtasForShuttleId(parent.id); if (!etasForShuttle) return null; const computedEtas = await Promise.all(etasForShuttle.map(async ({ secondsRemaining, stopId, }): Promise => { - const stop = await contextValue.apiBasedRepository.getStopById(stopId); + const stop = await contextValue.repository.getStopById(stopId); if (stop === null) return null; return { From 80faf8114bb6bc4fd1ece172fd8957b16c1bbb57 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Fri, 17 Jan 2025 14:46:35 -0800 Subject: [PATCH 5/5] remove redundant todo --- src/loaders/RepositoryDataLoader.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/loaders/RepositoryDataLoader.ts b/src/loaders/RepositoryDataLoader.ts index b9ec37b..edcc831 100644 --- a/src/loaders/RepositoryDataLoader.ts +++ b/src/loaders/RepositoryDataLoader.ts @@ -9,7 +9,6 @@ const baseUrl = "https://passiogo.com/mapGetData.php"; // Have one repository data loader running for each supported system // Each data loader independently updates data based on frequency of usage -// TODO implement reloading of data // Notes on this: we only need to reload ETA data frequently // Other data can be reloaded periodically // Detailed list: