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 { 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 { 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); } }