Refactor shuttle update method into clear sub-procedures

This commit is contained in:
2025-09-26 14:45:11 -07:00
parent 9a2b2f65b9
commit 74a55b3f57
2 changed files with 61 additions and 41 deletions

View File

@@ -132,11 +132,37 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
} }
public async updateShuttleDataForSystem() { public async updateShuttleDataForSystem() {
const systemId = this.passioSystemId; try {
const json = await this.fetchShuttleDataJson();
const shuttles = this.constructShuttlesFromJson(json);
if (shuttles !== null) {
await this.updateShuttleDataInRepository(shuttles);
} else {
console.warn(`Shuttle update failed for the following JSON: ${JSON.stringify(json)}`)
}
} catch(e: any) {
throw new ApiResponseError(e.message);
}
}
private async updateShuttleDataInRepository(shuttles: IShuttle[]) {
const shuttleIdsToPrune = await this.constructExistingEntityIdSet(async () => { const shuttleIdsToPrune = await this.constructExistingEntityIdSet(async () => {
return await this.repository.getShuttles(); return await this.repository.getShuttles();
}); });
await Promise.all(shuttles.map(async (shuttle) => {
await this.repository.addOrUpdateShuttle(shuttle);
shuttleIdsToPrune.delete(shuttle.id);
}));
await Promise.all(Array.from(shuttleIdsToPrune).map(async (shuttleId) => {
await this.repository.removeShuttleIfExists(shuttleId);
}));
}
private async fetchShuttleDataJson() {
const systemId = this.passioSystemId;
const params = { const params = {
getBuses: "2" getBuses: "2"
}; };
@@ -151,44 +177,37 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
const query = new URLSearchParams(params).toString(); const query = new URLSearchParams(params).toString();
try { const response = await fetch(`${this.baseUrl}?${query}`, {
const response = await fetch(`${this.baseUrl}?${query}`, { method: "POST",
method: "POST", body: formData,
body: formData, });
return await response.json();
}
private constructShuttlesFromJson(json: any): IShuttle[] | null {
if (json.buses && json.buses["-1"] === undefined) {
const jsonBuses = Object.values(json.buses).map((busesArr: any) => {
return busesArr[0];
}); });
const json = await response.json();
if (json.buses && json.buses["-1"] === undefined) { return jsonBuses.map((jsonBus: any) => {
const jsonBuses = Object.values(json.buses).map((busesArr: any) => { const constructedShuttle: IShuttle = {
return busesArr[0]; name: jsonBus.bus,
}); coordinates: {
latitude: parseFloat(jsonBus.latitude),
await Promise.all(jsonBuses.map(async (jsonBus: any) => { longitude: parseFloat(jsonBus.longitude),
const constructedShuttle: IShuttle = { },
name: jsonBus.bus, routeId: jsonBus.routeId,
coordinates: { systemId: this.systemIdForConstructedData,
latitude: parseFloat(jsonBus.latitude), id: `${jsonBus.busId}`,
longitude: parseFloat(jsonBus.longitude), orientationInDegrees: parseFloat(jsonBus.calculatedCourse),
}, updatedTime: new Date(),
routeId: jsonBus.routeId, }
systemId: this.systemIdForConstructedData, return constructedShuttle;
id: `${jsonBus.busId}`, });
orientationInDegrees: parseFloat(jsonBus.calculatedCourse),
updatedTime: new Date(),
}
await this.repository.addOrUpdateShuttle(constructedShuttle);
shuttleIdsToPrune.delete(constructedShuttle.id);
}));
}
await Promise.all(Array.from(shuttleIdsToPrune).map(async (shuttleId) => {
await this.repository.removeShuttleIfExists(shuttleId);
}));
} catch(e: any) {
throw new ApiResponseError(e.message);
} }
return null;
} }
public async updateEtaDataForExistingStopsForSystem() { public async updateEtaDataForExistingStopsForSystem() {
@@ -331,4 +350,5 @@ export class ApiBasedShuttleRepositoryLoader implements ShuttleRepositoryLoader
})) }))
} }
} }
} }

View File

@@ -34,10 +34,10 @@ describe("ApiBasedShuttleRepositoryLoader", () => {
describe("fetchAndUpdateAll", () => { describe("fetchAndUpdateAll", () => {
it("calls all the correct methods", async () => { it("calls all the correct methods", async () => {
const spies = { const spies = {
fetchAndUpdateRouteDataForSystem: jest.spyOn(loader, "fetchAndUpdateRouteDataForSystem"), updateRouteDataForSystem: jest.spyOn(loader, "updateRouteDataForSystem"),
fetchAndUpdateStopAndPolylineDataForRoutesInSystem: jest.spyOn(loader, "fetchAndUpdateStopAndPolylineDataForRoutesInSystem"), updateStopAndPolylineDataForRoutesInSystem: jest.spyOn(loader, "updateStopAndPolylineDataForRoutesInSystem"),
fetchAndUpdateShuttleDataForSystem: jest.spyOn(loader, "fetchAndUpdateShuttleDataForSystem"), updateShuttleDataForSystem: jest.spyOn(loader, "updateShuttleDataForSystem"),
fetchAndUpdateEtaDataForExistingStopsForSystem: jest.spyOn(loader, "fetchAndUpdateEtaDataForExistingStopsForSystem"), updateEtaDataForExistingStopsForSystem: jest.spyOn(loader, "updateEtaDataForExistingStopsForSystem"),
}; };
Object.values(spies).forEach((spy: any) => { Object.values(spies).forEach((spy: any) => {
@@ -153,7 +153,7 @@ describe("ApiBasedShuttleRepositoryLoader", () => {
describe("fetchAndUpdateEtaDataForExistingStopsForSystem", () => { describe("fetchAndUpdateEtaDataForExistingStopsForSystem", () => {
it("calls fetchAndUpdateEtaDataForStopId for every stop in repository", async () => { it("calls fetchAndUpdateEtaDataForStopId for every stop in repository", async () => {
const spy = jest.spyOn(loader, "fetchAndUpdateEtaDataForStopId"); const spy = jest.spyOn(loader, "updateEtaDataForStopId");
const stops = generateMockStops(); const stops = generateMockStops();
stops.forEach((stop) => { stops.forEach((stop) => {