change set of device IDs to object of device IDs to seconds threshold

This commit is contained in:
2025-03-25 15:09:32 -07:00
parent 07b80f2012
commit 50636e5582

View File

@@ -20,8 +20,10 @@ export interface ScheduledNotificationData {
secondsThreshold?: number; secondsThreshold?: number;
} }
type DeviceIdSecondsThresholdAssociation = { [key: string]: number };
export class ETANotificationScheduler { export class ETANotificationScheduler {
public readonly secondsThresholdForNotificationToFire = 180; public readonly defaultSecondsThresholdForNotificationToFire = 180;
constructor(private repository: GetterRepository, constructor(private repository: GetterRepository,
private appleNotificationSender = new AppleNotificationSender() private appleNotificationSender = new AppleNotificationSender()
@@ -37,9 +39,10 @@ export class ETANotificationScheduler {
* An object of device ID arrays to deliver notifications to. * An object of device ID arrays to deliver notifications to.
* The key should be a combination of the shuttle ID and * The key should be a combination of the shuttle ID and
* stop ID, which can be generated using `TupleKey`. * stop ID, which can be generated using `TupleKey`.
* The value is a dictionary of the device ID to the stored seconds threshold.
* @private * @private
*/ */
private deviceIdsToDeliverTo: { [key: string]: Set<string> } = {} private deviceIdsToDeliverTo: { [key: string]: DeviceIdSecondsThresholdAssociation } = {}
private async sendEtaNotificationImmediately(notificationData: ScheduledNotificationData): Promise<boolean> { private async sendEtaNotificationImmediately(notificationData: ScheduledNotificationData): Promise<boolean> {
const { deviceId, shuttleId, stopId } = notificationData; const { deviceId, shuttleId, stopId } = notificationData;
@@ -77,7 +80,7 @@ export class ETANotificationScheduler {
} }
const deviceIdsToRemove = new Set<string>(); const deviceIdsToRemove = new Set<string>();
for (let deviceId of this.deviceIdsToDeliverTo[tuple.toString()].values()) { for (let deviceId of Object.keys(this.deviceIdsToDeliverTo[tuple.toString()])) {
const deliveredSuccessfully = await this.sendEtaNotificationImmediatelyIfSecondsRemainingBelowThreshold(deviceId, eta); const deliveredSuccessfully = await this.sendEtaNotificationImmediatelyIfSecondsRemainingBelowThreshold(deviceId, eta);
if (deliveredSuccessfully) { if (deliveredSuccessfully) {
deviceIdsToRemove.add(deviceId); deviceIdsToRemove.add(deviceId);
@@ -85,12 +88,12 @@ export class ETANotificationScheduler {
} }
deviceIdsToRemove.forEach((deviceId) => { deviceIdsToRemove.forEach((deviceId) => {
this.deviceIdsToDeliverTo[tuple.toString()].delete(deviceId); delete this.deviceIdsToDeliverTo[tuple.toString()][deviceId]
}); });
} }
private async sendEtaNotificationImmediatelyIfSecondsRemainingBelowThreshold(deviceId: string, eta: IEta) { private async sendEtaNotificationImmediatelyIfSecondsRemainingBelowThreshold(deviceId: string, eta: IEta) {
if (eta.secondsRemaining > this.secondsThresholdForNotificationToFire) { if (eta.secondsRemaining > this.defaultSecondsThresholdForNotificationToFire) {
return false; return false;
} }
@@ -106,13 +109,20 @@ export class ETANotificationScheduler {
* @param deviceId The device ID to send the notification to. * @param deviceId The device ID to send the notification to.
* @param shuttleId Shuttle ID of ETA object to check. * @param shuttleId Shuttle ID of ETA object to check.
* @param stopId Stop ID of ETA object to check. * @param stopId Stop ID of ETA object to check.
* @param secondsThreshold Value which specifies the ETA of the shuttle for when
* the notification should fire.
*/ */
public async scheduleNotification({ deviceId, shuttleId, stopId }: ScheduledNotificationData) { public async scheduleNotification({ deviceId, shuttleId, stopId, secondsThreshold }: ScheduledNotificationData) {
const tuple = new TupleKey(shuttleId, stopId); const tuple = new TupleKey(shuttleId, stopId);
if (this.deviceIdsToDeliverTo[tuple.toString()] === undefined) { if (this.deviceIdsToDeliverTo[tuple.toString()] === undefined) {
this.deviceIdsToDeliverTo[tuple.toString()] = new Set(); this.deviceIdsToDeliverTo[tuple.toString()] = {};
}
if (secondsThreshold !== undefined) {
this.deviceIdsToDeliverTo[tuple.toString()][deviceId] = secondsThreshold;
} else {
this.deviceIdsToDeliverTo[tuple.toString()][deviceId] = this.defaultSecondsThresholdForNotificationToFire;
} }
this.deviceIdsToDeliverTo[tuple.toString()].add(deviceId);
this.repository.unsubscribeFromEtaUpdates(this.etaSubscriberCallback); this.repository.unsubscribeFromEtaUpdates(this.etaSubscriberCallback);
this.repository.subscribeToEtaUpdates(this.etaSubscriberCallback); this.repository.subscribeToEtaUpdates(this.etaSubscriberCallback);
@@ -128,12 +138,12 @@ export class ETANotificationScheduler {
const tupleKey = new TupleKey(shuttleId, stopId); const tupleKey = new TupleKey(shuttleId, stopId);
if ( if (
this.deviceIdsToDeliverTo[tupleKey.toString()] === undefined this.deviceIdsToDeliverTo[tupleKey.toString()] === undefined
|| !this.deviceIdsToDeliverTo[tupleKey.toString()].has(deviceId) || !(deviceId in this.deviceIdsToDeliverTo[tupleKey.toString()])
) { ) {
return; return;
} }
this.deviceIdsToDeliverTo[tupleKey.toString()].delete(deviceId); delete this.deviceIdsToDeliverTo[tupleKey.toString()][deviceId];
} }
/** /**
@@ -147,7 +157,7 @@ export class ETANotificationScheduler {
if (this.deviceIdsToDeliverTo[tuple.toString()] === undefined) { if (this.deviceIdsToDeliverTo[tuple.toString()] === undefined) {
return false; return false;
} }
return this.deviceIdsToDeliverTo[tuple.toString()].has(deviceId); return deviceId in this.deviceIdsToDeliverTo[tuple.toString()];
} }
/** /**
@@ -158,7 +168,7 @@ export class ETANotificationScheduler {
const scheduledNotifications: ScheduledNotificationData[] = []; const scheduledNotifications: ScheduledNotificationData[] = [];
for (const key of Object.keys(this.deviceIdsToDeliverTo)) { for (const key of Object.keys(this.deviceIdsToDeliverTo)) {
if (this.deviceIdsToDeliverTo[key].has(deviceId)) { if (deviceId in this.deviceIdsToDeliverTo[key]) {
const tupleKey = TupleKey.fromExistingStringKey(key); const tupleKey = TupleKey.fromExistingStringKey(key);
const shuttleId = tupleKey.tuple[0] const shuttleId = tupleKey.tuple[0]
const stopId = tupleKey.tuple[1]; const stopId = tupleKey.tuple[1];