mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-10 07:07:21 +00:00

- Added SchedulerModule and SchedulerService to handle hourly data updates for AQI, occupancy, and energy consumption. - Refactored existing services to remove unused device repository dependencies and streamline procedure execution. - Updated SQL procedures to use correct parameter indexing. - Enhanced error handling and logging for scheduled tasks. - Integrated new repositories for presence sensor and AQI pollutant stats across multiple modules. - Added NestJS schedule package for task scheduling capabilities.
85 lines
2.6 KiB
TypeScript
85 lines
2.6 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { DataSource } from 'typeorm';
|
|
import { SQL_PROCEDURES_PATH } from '@app/common/constants/sql-query-path';
|
|
import { SqlLoaderService } from './sql-loader.service';
|
|
|
|
@Injectable()
|
|
export class PowerClampService {
|
|
constructor(
|
|
private readonly sqlLoader: SqlLoaderService,
|
|
private readonly dataSource: DataSource,
|
|
) {}
|
|
|
|
async updateEnergyConsumedHistoricalData(): Promise<void> {
|
|
try {
|
|
const { dateStr, monthYear } = this.getFormattedDates();
|
|
|
|
// Execute all procedures in parallel
|
|
await Promise.all([
|
|
this.executeProcedureWithRetry(
|
|
'fact_hourly_device_energy_consumed_procedure',
|
|
[dateStr],
|
|
'fact_device_energy_consumed',
|
|
),
|
|
this.executeProcedureWithRetry(
|
|
'fact_daily_device_energy_consumed_procedure',
|
|
[dateStr],
|
|
'fact_device_energy_consumed',
|
|
),
|
|
this.executeProcedureWithRetry(
|
|
'fact_monthly_device_energy_consumed_procedure',
|
|
[monthYear],
|
|
'fact_device_energy_consumed',
|
|
),
|
|
]);
|
|
} catch (err) {
|
|
console.error('Failed to update energy consumption data:', err);
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
private getFormattedDates(): { dateStr: string; monthYear: string } {
|
|
const now = new Date();
|
|
return {
|
|
dateStr: now.toLocaleDateString('en-CA'), // YYYY-MM-DD
|
|
monthYear: now
|
|
.toLocaleDateString('en-US', {
|
|
month: '2-digit',
|
|
year: 'numeric',
|
|
})
|
|
.replace('/', '-'), // MM-YYYY
|
|
};
|
|
}
|
|
|
|
private async executeProcedureWithRetry(
|
|
procedureFileName: string,
|
|
params: (string | number | null)[],
|
|
folderName: string,
|
|
retries = 3,
|
|
): Promise<void> {
|
|
try {
|
|
const query = this.loadQuery(folderName, procedureFileName);
|
|
await this.dataSource.query(query, params);
|
|
console.log(`Procedure ${procedureFileName} executed successfully.`);
|
|
} catch (err) {
|
|
if (retries > 0) {
|
|
const delayMs = 1000 * (4 - retries); // Exponential backoff
|
|
console.warn(`Retrying ${procedureFileName} (${retries} retries left)`);
|
|
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
return this.executeProcedureWithRetry(
|
|
procedureFileName,
|
|
params,
|
|
folderName,
|
|
retries - 1,
|
|
);
|
|
}
|
|
console.error(`Failed to execute ${procedureFileName}:`, err);
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
private loadQuery(folderName: string, fileName: string): string {
|
|
return this.sqlLoader.loadQuery(folderName, fileName, SQL_PROCEDURES_PATH);
|
|
}
|
|
}
|