mirror of
https://github.com/brendan-ch/project-inter-server.git
synced 2026-04-17 07:50:31 +00:00
update timed loader to use class composition
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import { ShuttleRepositoryLoader } from "../loaders/ShuttleRepositoryLoader";
|
|
||||||
import { ETANotificationScheduler } from "../notifications/schedulers/ETANotificationScheduler";
|
import { ETANotificationScheduler } from "../notifications/schedulers/ETANotificationScheduler";
|
||||||
import { TimedApiBasedShuttleRepositoryLoader } from "../loaders/TimedApiBasedShuttleRepositoryLoader";
|
import { TimedApiBasedRepositoryLoader } from "../loaders/TimedApiBasedRepositoryLoader";
|
||||||
import { UnoptimizedInMemoryShuttleRepository } from "../repositories/UnoptimizedInMemoryShuttleRepository";
|
import { UnoptimizedInMemoryShuttleRepository } from "../repositories/UnoptimizedInMemoryShuttleRepository";
|
||||||
import { RedisNotificationRepository } from "../repositories/RedisNotificationRepository";
|
import { RedisNotificationRepository } from "../repositories/RedisNotificationRepository";
|
||||||
import { NotificationRepository } from "../repositories/NotificationRepository";
|
import { NotificationRepository } from "../repositories/NotificationRepository";
|
||||||
@@ -27,7 +26,7 @@ export class InterchangeSystem {
|
|||||||
constructor(
|
constructor(
|
||||||
public name: string,
|
public name: string,
|
||||||
public id: string,
|
public id: string,
|
||||||
public shuttleDataLoader: ShuttleRepositoryLoader,
|
public shuttleTimedDataLoader: TimedApiBasedRepositoryLoader,
|
||||||
public shuttleRepository: ShuttleGetterSetterRepository,
|
public shuttleRepository: ShuttleGetterSetterRepository,
|
||||||
public notificationScheduler: ETANotificationScheduler,
|
public notificationScheduler: ETANotificationScheduler,
|
||||||
public notificationRepository: NotificationRepository,
|
public notificationRepository: NotificationRepository,
|
||||||
@@ -43,12 +42,15 @@ export class InterchangeSystem {
|
|||||||
args: InterchangeSystemBuilderArguments,
|
args: InterchangeSystemBuilderArguments,
|
||||||
) {
|
) {
|
||||||
const shuttleRepository = new UnoptimizedInMemoryShuttleRepository();
|
const shuttleRepository = new UnoptimizedInMemoryShuttleRepository();
|
||||||
const shuttleDataLoader = new TimedApiBasedShuttleRepositoryLoader(
|
const shuttleDataLoader = new ApiBasedShuttleRepositoryLoader(
|
||||||
args.passioSystemId,
|
args.passioSystemId,
|
||||||
args.id,
|
args.id,
|
||||||
shuttleRepository
|
shuttleRepository
|
||||||
);
|
);
|
||||||
await shuttleDataLoader.start();
|
const timedShuttleDataLoader = new TimedApiBasedRepositoryLoader(
|
||||||
|
shuttleDataLoader,
|
||||||
|
);
|
||||||
|
await timedShuttleDataLoader.start();
|
||||||
|
|
||||||
const notificationRepository = new RedisNotificationRepository();
|
const notificationRepository = new RedisNotificationRepository();
|
||||||
await notificationRepository.connect();
|
await notificationRepository.connect();
|
||||||
@@ -62,7 +64,7 @@ export class InterchangeSystem {
|
|||||||
return new InterchangeSystem(
|
return new InterchangeSystem(
|
||||||
args.name,
|
args.name,
|
||||||
args.id,
|
args.id,
|
||||||
shuttleDataLoader,
|
timedShuttleDataLoader,
|
||||||
shuttleRepository,
|
shuttleRepository,
|
||||||
notificationScheduler,
|
notificationScheduler,
|
||||||
notificationRepository,
|
notificationRepository,
|
||||||
@@ -84,6 +86,11 @@ export class InterchangeSystem {
|
|||||||
args.id,
|
args.id,
|
||||||
shuttleRepository
|
shuttleRepository
|
||||||
);
|
);
|
||||||
|
// Note that this loader should not be started,
|
||||||
|
// so the test data doesn't get overwritten
|
||||||
|
const timedShuttleLoader = new TimedApiBasedRepositoryLoader(
|
||||||
|
shuttleDataLoader,
|
||||||
|
);
|
||||||
|
|
||||||
const notificationRepository = new InMemoryNotificationRepository();
|
const notificationRepository = new InMemoryNotificationRepository();
|
||||||
const notificationScheduler = new ETANotificationScheduler(
|
const notificationScheduler = new ETANotificationScheduler(
|
||||||
@@ -96,7 +103,7 @@ export class InterchangeSystem {
|
|||||||
return new InterchangeSystem(
|
return new InterchangeSystem(
|
||||||
args.name,
|
args.name,
|
||||||
args.id,
|
args.id,
|
||||||
shuttleDataLoader,
|
timedShuttleLoader,
|
||||||
shuttleRepository,
|
shuttleRepository,
|
||||||
notificationScheduler,
|
notificationScheduler,
|
||||||
notificationRepository,
|
notificationRepository,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { ShuttleGetterSetterRepository } from "../repositories/ShuttleGetterSetterRepository";
|
import { RepositoryLoader } from "./RepositoryLoader";
|
||||||
import { ApiBasedShuttleRepositoryLoader } from "./ApiBasedShuttleRepositoryLoader";
|
|
||||||
|
|
||||||
// Ideas to break this into smaller pieces in the future:
|
// Ideas to break this into smaller pieces in the future:
|
||||||
// Have one repository data loader running for each supported system
|
// Have one repository data loader running for each supported system
|
||||||
@@ -15,18 +14,15 @@ import { ApiBasedShuttleRepositoryLoader } from "./ApiBasedShuttleRepositoryLoad
|
|||||||
// - OrderedStops: reload every few minutes
|
// - OrderedStops: reload every few minutes
|
||||||
// - Systems: reload once a day
|
// - Systems: reload once a day
|
||||||
|
|
||||||
export class TimedApiBasedShuttleRepositoryLoader extends ApiBasedShuttleRepositoryLoader {
|
export class TimedApiBasedRepositoryLoader {
|
||||||
private shouldBeRunning: boolean = false;
|
private shouldBeRunning: boolean = false;
|
||||||
private timer: any;
|
private timer: any;
|
||||||
|
|
||||||
readonly timeout = 10000;
|
readonly timeout = 10000;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public passioSystemId: string,
|
public loader: RepositoryLoader,
|
||||||
public systemIdForConstructedData: string,
|
|
||||||
repository: ShuttleGetterSetterRepository,
|
|
||||||
) {
|
) {
|
||||||
super(passioSystemId, systemIdForConstructedData, repository);
|
|
||||||
this.startFetchDataAndUpdate = this.startFetchDataAndUpdate.bind(this);
|
this.startFetchDataAndUpdate = this.startFetchDataAndUpdate.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,14 +44,7 @@ export class TimedApiBasedShuttleRepositoryLoader extends ApiBasedShuttleReposit
|
|||||||
if (!this.shouldBeRunning) return;
|
if (!this.shouldBeRunning) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.fetchAndUpdateRouteDataForSystem();
|
await this.loader.fetchAndUpdateAll();
|
||||||
await this.fetchAndUpdateStopAndPolylineDataForRoutesInSystem();
|
|
||||||
await this.fetchAndUpdateShuttleDataForSystem();
|
|
||||||
|
|
||||||
// Because ETA method doesn't support pruning yet,
|
|
||||||
// add a call to the clear method here
|
|
||||||
await this.repository.clearEtaData();
|
|
||||||
await this.fetchAndUpdateEtaDataForExistingStopsForSystem();
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, jest } from "@jest/globals";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, jest } from "@jest/globals";
|
||||||
import { TimedApiBasedShuttleRepositoryLoader } from "../../src/loaders/TimedApiBasedShuttleRepositoryLoader";
|
import { TimedApiBasedRepositoryLoader } from "../../src/loaders/TimedApiBasedRepositoryLoader";
|
||||||
import { resetGlobalFetchMockJson } from "../testHelpers/fetchMockHelpers";
|
import { resetGlobalFetchMockJson } from "../testHelpers/fetchMockHelpers";
|
||||||
import { UnoptimizedInMemoryShuttleRepository } from "../../src/repositories/UnoptimizedInMemoryShuttleRepository";
|
import { UnoptimizedInMemoryShuttleRepository } from "../../src/repositories/UnoptimizedInMemoryShuttleRepository";
|
||||||
|
import { ApiBasedShuttleRepositoryLoader } from "../../src/loaders/ApiBasedShuttleRepositoryLoader";
|
||||||
|
|
||||||
describe("TimedApiBasedRepositoryLoader", () => {
|
describe("TimedApiBasedRepositoryLoader", () => {
|
||||||
let loader: TimedApiBasedShuttleRepositoryLoader;
|
let timedLoader: TimedApiBasedRepositoryLoader;
|
||||||
let spies: any;
|
let spies: any;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
@@ -15,17 +16,17 @@ describe("TimedApiBasedRepositoryLoader", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
resetGlobalFetchMockJson();
|
resetGlobalFetchMockJson();
|
||||||
|
|
||||||
loader = new TimedApiBasedShuttleRepositoryLoader(
|
const mockLoader = new ApiBasedShuttleRepositoryLoader(
|
||||||
"1",
|
"1",
|
||||||
"1",
|
"1",
|
||||||
new UnoptimizedInMemoryShuttleRepository()
|
new UnoptimizedInMemoryShuttleRepository(),
|
||||||
|
);
|
||||||
|
timedLoader = new TimedApiBasedRepositoryLoader(
|
||||||
|
mockLoader,
|
||||||
);
|
);
|
||||||
|
|
||||||
spies = {
|
spies = {
|
||||||
fetchAndUpdateRouteDataForSystem: jest.spyOn(loader, 'fetchAndUpdateRouteDataForSystem'),
|
fetchAndUpdateAll: jest.spyOn(mockLoader, 'fetchAndUpdateAll'),
|
||||||
fetchAndUpdateStopAndPolylineDataForRoutesInSystem: jest.spyOn(loader, 'fetchAndUpdateStopAndPolylineDataForRoutesInSystem'),
|
|
||||||
fetchAndUpdateShuttleDataForSystem: jest.spyOn(loader, 'fetchAndUpdateShuttleDataForSystem'),
|
|
||||||
fetchAndUpdateEtaDataForExistingStopsForSystem: jest.spyOn(loader, 'fetchAndUpdateEtaDataForExistingStopsForSystem')
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.values(spies).forEach((spy: any) => {
|
Object.values(spies).forEach((spy: any) => {
|
||||||
@@ -40,20 +41,20 @@ describe("TimedApiBasedRepositoryLoader", () => {
|
|||||||
|
|
||||||
describe("start", () => {
|
describe("start", () => {
|
||||||
it("should update internal state, call data fetching methods, and start a timer", async () => {
|
it("should update internal state, call data fetching methods, and start a timer", async () => {
|
||||||
await loader.start();
|
await timedLoader.start();
|
||||||
expect(loader["shouldBeRunning"]).toBe(true);
|
expect(timedLoader["shouldBeRunning"]).toBe(true);
|
||||||
|
|
||||||
Object.values(spies).forEach((spy: any) => {
|
Object.values(spies).forEach((spy: any) => {
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), loader.timeout);
|
expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), timedLoader.timeout);
|
||||||
expect(loader.timeout).not.toBeUndefined();
|
expect(timedLoader.timeout).not.toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does nothing if timer is already running", async () => {
|
it("does nothing if timer is already running", async () => {
|
||||||
await loader.start();
|
await timedLoader.start();
|
||||||
await loader.start();
|
await timedLoader.start();
|
||||||
|
|
||||||
Object.values(spies).forEach((spy: any) => {
|
Object.values(spies).forEach((spy: any) => {
|
||||||
expect(spy).toHaveBeenCalledTimes(1);
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
@@ -63,8 +64,8 @@ describe("TimedApiBasedRepositoryLoader", () => {
|
|||||||
|
|
||||||
describe("stop", () => {
|
describe("stop", () => {
|
||||||
it("should update internal state", async () => {
|
it("should update internal state", async () => {
|
||||||
loader.stop();
|
timedLoader.stop();
|
||||||
expect(loader['shouldBeRunning']).toBe(false);
|
expect(timedLoader['shouldBeRunning']).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user