From 4523badea993c386c871215849453aa07db938a5 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Fri, 14 Nov 2025 10:17:33 -0800 Subject: [PATCH 1/4] Test that clearShuttleData also clears last stop data --- .../ShuttleRepositorySharedTests.test.ts | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/repositories/shuttle/__tests__/ShuttleRepositorySharedTests.test.ts b/src/repositories/shuttle/__tests__/ShuttleRepositorySharedTests.test.ts index b45f2a3..038ea56 100644 --- a/src/repositories/shuttle/__tests__/ShuttleRepositorySharedTests.test.ts +++ b/src/repositories/shuttle/__tests__/ShuttleRepositorySharedTests.test.ts @@ -18,7 +18,7 @@ class UnoptimizedInMemoryShuttleRepositoryHolder implements RepositoryHolder { return new UnoptimizedInMemoryShuttleRepository(); }; - teardown = async () => {}; + teardown = async () => { }; } class RedisShuttleRepositoryHolder implements RepositoryHolder { @@ -477,6 +477,28 @@ describe.each(repositoryImplementations)('$name', (holder) => { const result = await repository.getShuttles(); expect(result).toEqual([]); }); + + test("also clears last stop data", async () => { + const { route, stop1, stop2, systemId } = await setupRouteAndOrderedStops(); + + const mockShuttles = generateMockShuttles(); + mockShuttles[0].coordinates = stop1.coordinates; + mockShuttles[1].coordinates = stop2.coordinates; + + for (const shuttle of mockShuttles) { + shuttle.routeId = route.id; + shuttle.systemId = systemId; + + await repository.addOrUpdateShuttle(shuttle); + } + + await repository.clearShuttleData(); + + for (const shuttle of mockShuttles) { + const result = await repository.getShuttleLastStopArrival(shuttle.id); + expect(result).toBeUndefined(); + } + }); }); From f76126c951379baeb787c3b433c0dfd9667e6cd7 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Fri, 14 Nov 2025 10:19:15 -0800 Subject: [PATCH 2/4] Implement clearing of last stop data --- src/repositories/shuttle/RedisShuttleRepository.ts | 8 ++++++++ .../shuttle/UnoptimizedInMemoryShuttleRepository.ts | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src/repositories/shuttle/RedisShuttleRepository.ts b/src/repositories/shuttle/RedisShuttleRepository.ts index cd90147..1a6b4d0 100644 --- a/src/repositories/shuttle/RedisShuttleRepository.ts +++ b/src/repositories/shuttle/RedisShuttleRepository.ts @@ -566,6 +566,7 @@ export class RedisShuttleRepository extends BaseRedisRepository implements Shutt if (keys.length > 0) { await this.redisClient.del(keys); } + await this.clearShuttleLastStopData(); } public async clearOrderedStopData(): Promise { @@ -588,4 +589,11 @@ export class RedisShuttleRepository extends BaseRedisRepository implements Shutt await this.redisClient.del(keys); } } + + private async clearShuttleLastStopData(): Promise { + const keys = await this.redisClient.keys('shuttle:laststop:*'); + if (keys.length > 0) { + await this.redisClient.del(keys); + } + } } diff --git a/src/repositories/shuttle/UnoptimizedInMemoryShuttleRepository.ts b/src/repositories/shuttle/UnoptimizedInMemoryShuttleRepository.ts index 14ba7d7..8b7a3d5 100644 --- a/src/repositories/shuttle/UnoptimizedInMemoryShuttleRepository.ts +++ b/src/repositories/shuttle/UnoptimizedInMemoryShuttleRepository.ts @@ -284,6 +284,7 @@ export class UnoptimizedInMemoryShuttleRepository public async clearShuttleData(): Promise { this.shuttles = []; + await this.clearShuttleLastStopData(); } public async clearOrderedStopData(): Promise { @@ -298,4 +299,7 @@ export class UnoptimizedInMemoryShuttleRepository this.stops = []; } + private async clearShuttleLastStopData(): Promise { + this.shuttleLastStopArrivals.clear(); + } } From 1511b3c1184f8d80f30a66f79172d4326be4940e Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Fri, 14 Nov 2025 10:23:02 -0800 Subject: [PATCH 3/4] Add test case to check that last stop data is removed --- .../__tests__/ShuttleRepositorySharedTests.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/repositories/shuttle/__tests__/ShuttleRepositorySharedTests.test.ts b/src/repositories/shuttle/__tests__/ShuttleRepositorySharedTests.test.ts index 038ea56..f875f2e 100644 --- a/src/repositories/shuttle/__tests__/ShuttleRepositorySharedTests.test.ts +++ b/src/repositories/shuttle/__tests__/ShuttleRepositorySharedTests.test.ts @@ -386,6 +386,20 @@ describe.each(repositoryImplementations)('$name', (holder) => { expect(remainingShuttles).toHaveLength(mockShuttles.length - 1); }); + test("removes shuttle last stop if exists", async () => { + const { route, stop1, systemId } = await setupRouteAndOrderedStops(); + const mockShuttle = generateMockShuttles()[0]; + mockShuttle.routeId = route.id; + mockShuttle.coordinates = stop1.coordinates; + mockShuttle.systemId = systemId; + + await repository.addOrUpdateShuttle(mockShuttle); + await repository.removeShuttleIfExists(mockShuttle.id); + + const lastStopData = await repository.getShuttleLastStopArrival(mockShuttle.id); + expect(lastStopData).toBeUndefined(); + }); + test("does nothing if shuttle doesn't exist", async () => { const systemId = "1"; const mockShuttles = generateMockShuttles(); From f06e778b80a723cb2260b0f766bf4491626e84c6 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Fri, 14 Nov 2025 10:26:52 -0800 Subject: [PATCH 4/4] Implement removal of last stop data on shuttle removal --- src/repositories/shuttle/RedisShuttleRepository.ts | 14 +++++++++++++- .../UnoptimizedInMemoryShuttleRepository.ts | 5 +++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/repositories/shuttle/RedisShuttleRepository.ts b/src/repositories/shuttle/RedisShuttleRepository.ts index 1a6b4d0..763dde5 100644 --- a/src/repositories/shuttle/RedisShuttleRepository.ts +++ b/src/repositories/shuttle/RedisShuttleRepository.ts @@ -534,6 +534,9 @@ export class RedisShuttleRepository extends BaseRedisRepository implements Shutt const key = this.createShuttleKey(shuttleId); await this.redisClient.del(key); this.emit(ShuttleRepositoryEvent.SHUTTLE_REMOVED, shuttle); + + await this.removeShuttleLastStopIfExists(shuttleId); + return shuttle; } return null; @@ -559,6 +562,15 @@ export class RedisShuttleRepository extends BaseRedisRepository implements Shutt return null; } + private async removeShuttleLastStopIfExists(shuttleId: string) { + const lastStop = await this.getShuttleLastStopArrival(shuttleId); + if (lastStop) { + const key = this.createShuttleLastStopKey(shuttleId); + await this.redisClient.del(key); + return lastStop; + } + return null; + } // Clear methods public async clearShuttleData(): Promise { @@ -589,7 +601,7 @@ export class RedisShuttleRepository extends BaseRedisRepository implements Shutt await this.redisClient.del(keys); } } - + private async clearShuttleLastStopData(): Promise { const keys = await this.redisClient.keys('shuttle:laststop:*'); if (keys.length > 0) { diff --git a/src/repositories/shuttle/UnoptimizedInMemoryShuttleRepository.ts b/src/repositories/shuttle/UnoptimizedInMemoryShuttleRepository.ts index 8b7a3d5..a3e7dac 100644 --- a/src/repositories/shuttle/UnoptimizedInMemoryShuttleRepository.ts +++ b/src/repositories/shuttle/UnoptimizedInMemoryShuttleRepository.ts @@ -267,6 +267,7 @@ export class UnoptimizedInMemoryShuttleRepository const shuttle = await this.removeEntityByIdIfExists(shuttleId, this.shuttles); if (shuttle != null) { this.emit(ShuttleRepositoryEvent.SHUTTLE_REMOVED, shuttle); + await this.removeShuttleLastStopIfExists(shuttleId); } return shuttle; } @@ -282,6 +283,10 @@ export class UnoptimizedInMemoryShuttleRepository }, this.orderedStops); } + private async removeShuttleLastStopIfExists(shuttleId: string) { + this.shuttleLastStopArrivals.delete(shuttleId); + } + public async clearShuttleData(): Promise { this.shuttles = []; await this.clearShuttleLastStopData();