mirror of
https://github.com/brendan-ch/project-inter-server.git
synced 2026-04-17 07:50:31 +00:00
Update RedisParkingRepository.ts to use Redis aggregation functions
This commit is contained in:
@@ -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<HistoricalParkingAverageQueryResult[]> => {
|
||||
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<HistoricalParkingAverageQueryResult[]> => {
|
||||
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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user