diff --git a/src/repositories/RedisParkingRepository.ts b/src/repositories/RedisParkingRepository.ts index dcb96e8..fae968c 100644 --- a/src/repositories/RedisParkingRepository.ts +++ b/src/repositories/RedisParkingRepository.ts @@ -1,5 +1,5 @@ import { ParkingGetterSetterRepository } from "./ParkingGetterSetterRepository"; -import { IParkingStructure, IParkingStructureTimestampRecord } from "../entities/ParkingRepositoryEntities"; +import { IParkingStructure } from "../entities/ParkingRepositoryEntities"; import { HistoricalParkingAverageQueryResult, ParkingStructureCountOptions } from "./ParkingGetterRepository"; import { BaseRedisRepository } from "./BaseRedisRepository"; import { PARKING_LOGGING_INTERVAL_MS } from "./ParkingRepositoryConstants"; @@ -76,25 +76,7 @@ export class RedisParkingRepository extends BaseRedisRepository implements Parki }; getHistoricalAveragesOfParkingStructureCounts = async (id: string, options: ParkingStructureCountOptions): Promise => { - const keys = this.createRedisKeys(id); - - try { - const timeSeriesData = await this.redisClient.sendCommand([ - 'TS.RANGE', - keys.timeSeries, - options.startUnixEpochMs.toString(), - options.endUnixEpochMs.toString() - ]) as [string, string][]; - - if (!timeSeriesData || timeSeriesData.length === 0) { - return []; - } - - const records = this.convertTimeSeriesDataToRecords(timeSeriesData, id); - return this.calculateAveragesFromRecords(records, options); - } catch (error) { - return []; - } + return this.calculateAveragesFromRecords(id, options); }; private createRedisKeys = (structureId: string) => ({ @@ -173,30 +155,40 @@ export class RedisParkingRepository extends BaseRedisRepository implements Parki } }; - private convertTimeSeriesDataToRecords = (timeSeriesData: [string, string][], id: string): IParkingStructureTimestampRecord[] => { - return timeSeriesData.map(([timestamp, value]) => ({ - id, - timestampMs: parseInt(timestamp), - spotsAvailable: parseInt(value) - })); - }; - - private calculateAveragesFromRecords = ( - records: IParkingStructureTimestampRecord[], + private calculateAveragesFromRecords = async ( + id: string, options: ParkingStructureCountOptions - ): HistoricalParkingAverageQueryResult[] => { - const results: HistoricalParkingAverageQueryResult[] = []; + ): Promise => { + const keys = this.createRedisKeys(id); const { startUnixEpochMs, endUnixEpochMs, intervalMs } = options; + const results: HistoricalParkingAverageQueryResult[] = []; let currentIntervalStart = startUnixEpochMs; while (currentIntervalStart < endUnixEpochMs) { const currentIntervalEnd = Math.min(currentIntervalStart + intervalMs, endUnixEpochMs); - const recordsInInterval = this.getRecordsInTimeRange(records, currentIntervalStart, currentIntervalEnd); + + try { + const aggregationResult = await this.redisClient.sendCommand([ + 'TS.RANGE', + keys.timeSeries, + currentIntervalStart.toString(), + currentIntervalEnd.toString(), + 'AGGREGATION', + 'AVG', + intervalMs.toString() + ]) as [string, string][]; - if (recordsInInterval.length > 0) { - const averageResult = this.calculateAverageForInterval(currentIntervalStart, currentIntervalEnd, recordsInInterval); - results.push(averageResult); + if (aggregationResult && aggregationResult.length > 0) { + const [, averageValue] = aggregationResult[0]; + results.push({ + fromUnixEpochMs: currentIntervalStart, + toUnixEpochMs: currentIntervalEnd, + averageSpotsAvailable: parseFloat(averageValue) + }); + } + } catch (error) { + // If Redis aggregation fails, skip this interval } currentIntervalStart = currentIntervalEnd; @@ -205,31 +197,6 @@ export class RedisParkingRepository extends BaseRedisRepository implements Parki return results; }; - private getRecordsInTimeRange = ( - records: IParkingStructureTimestampRecord[], - startMs: number, - endMs: number - ): IParkingStructureTimestampRecord[] => { - return records.filter(record => - record.timestampMs >= startMs && record.timestampMs < endMs - ); - }; - - private calculateAverageForInterval = ( - fromMs: number, - toMs: number, - records: IParkingStructureTimestampRecord[] - ): HistoricalParkingAverageQueryResult => { - const totalSpotsAvailable = records.reduce((sum, record) => sum + record.spotsAvailable, 0); - const averageSpotsAvailable = totalSpotsAvailable / records.length; - - return { - fromUnixEpochMs: fromMs, - toUnixEpochMs: toMs, - averageSpotsAvailable - }; - }; - setLoggingInterval = (intervalMs: number): void => { this.loggingIntervalMs = intervalMs; };