From a0790f0b484cd3e7c8b5c52b17e54580b7c46dfb Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Thu, 20 Feb 2025 13:29:19 +0400 Subject: [PATCH 1/2] fixed the heirarchy device fetching issue --- src/device/services/device.service.ts | 35 +++++++++++++++++-- src/space/services/space-device.service.ts | 6 ++-- .../services/space-validation.service.ts | 28 +++++++++++++++ 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/device/services/device.service.ts b/src/device/services/device.service.ts index 49a6a86..9a67d65 100644 --- a/src/device/services/device.service.ts +++ b/src/device/services/device.service.ts @@ -1021,10 +1021,13 @@ export class DeviceService { } } - const spaceHierarchy = await this.getFullSpaceHierarchy( + const spaceHierarchy = await this.getParentHierarchy( device?.spaceDevice, ); - const orderedHierarchy = spaceHierarchy.reverse(); + const orderedHierarchy = [ + device?.spaceDevice, + ...spaceHierarchy.reverse(), + ]; return { spaces: orderedHierarchy.map((space) => ({ @@ -1515,4 +1518,32 @@ export class DeviceService { } return project; } + + async getParentHierarchy( + space: SpaceEntity, + ): Promise<{ uuid: string; spaceName: string }[]> { + try { + const targetSpace = await this.spaceRepository.findOne({ + where: { uuid: space.uuid }, + relations: ['parent'], + }); + + if (!targetSpace) { + throw new HttpException('Space not found', HttpStatus.NOT_FOUND); + } + + const ancestors = await this.fetchAncestors(targetSpace); + + return ancestors.map((parentSpace) => ({ + uuid: parentSpace.uuid, + spaceName: parentSpace.spaceName, + })); + } catch (error) { + console.error('Error fetching parent hierarchy:', error.message); + throw new HttpException( + 'Error fetching parent hierarchy', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } } diff --git a/src/space/services/space-device.service.ts b/src/space/services/space-device.service.ts index 490cca7..773c7d5 100644 --- a/src/space/services/space-device.service.ts +++ b/src/space/services/space-device.service.ts @@ -32,10 +32,10 @@ export class SpaceDeviceService { ); } - // Fetch space hierarchy **once** and reverse it to get an ordered hierarchy const spaceHierarchy = - await this.validationService.getFullSpaceHierarchy(space); - const orderedHierarchy = spaceHierarchy.reverse(); + await this.validationService.getParentHierarchy(space); + + const orderedHierarchy = [space, ...spaceHierarchy.reverse()]; // Fetch Tuya details for each device in parallel using Promise.allSettled const deviceDetailsPromises = space.devices.map((device) => diff --git a/src/space/services/space-validation.service.ts b/src/space/services/space-validation.service.ts index 9dc614b..0358fc2 100644 --- a/src/space/services/space-validation.service.ts +++ b/src/space/services/space-validation.service.ts @@ -222,4 +222,32 @@ export class ValidationService { return descendants; } + + async getParentHierarchy( + space: SpaceEntity, + ): Promise<{ uuid: string; spaceName: string }[]> { + try { + const targetSpace = await this.spaceRepository.findOne({ + where: { uuid: space.uuid }, + relations: ['parent'], + }); + + if (!targetSpace) { + throw new HttpException('Space not found', HttpStatus.NOT_FOUND); + } + + const ancestors = await this.fetchAncestors(targetSpace); + + return ancestors.map((parentSpace) => ({ + uuid: parentSpace.uuid, + spaceName: parentSpace.spaceName, + })); + } catch (error) { + console.error('Error fetching parent hierarchy:', error.message); + throw new HttpException( + 'Error fetching parent hierarchy', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } } From 630b3ee2b98cae5426fa4507dd3af8a6ebc4db2e Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Tue, 25 Feb 2025 15:33:04 +0300 Subject: [PATCH 2/2] change set to transaction --- .../services/devices-status.service.ts | 78 +++++++++++-------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/libs/common/src/firebase/devices-status/services/devices-status.service.ts b/libs/common/src/firebase/devices-status/services/devices-status.service.ts index fbbc00c..9ef06a0 100644 --- a/libs/common/src/firebase/devices-status/services/devices-status.service.ts +++ b/libs/common/src/firebase/devices-status/services/devices-status.service.ts @@ -10,7 +10,13 @@ import { GetDeviceDetailsFunctionsStatusInterface } from 'src/device/interfaces/ import { TuyaContext } from '@tuya/tuya-connector-nodejs'; import { ConfigService } from '@nestjs/config'; import { firebaseDataBase } from '../../firebase.config'; -import { Database, DataSnapshot, get, ref, set } from 'firebase/database'; +import { + Database, + DataSnapshot, + get, + ref, + runTransaction, +} from 'firebase/database'; import { DeviceStatusLogRepository } from '@app/common/modules/device-status-log/repositories'; @Injectable() export class DeviceStatusFirebaseService { @@ -154,39 +160,48 @@ export class DeviceStatusFirebaseService { this.firebaseDb, `device-status/${addDeviceStatusDto.deviceUuid}`, ); - const snapshot: DataSnapshot = await get(dataRef); - const existingData = snapshot.val() || {}; - // Assign default values if fields are not present - if (!existingData.deviceTuyaUuid) { - existingData.deviceTuyaUuid = addDeviceStatusDto.deviceTuyaUuid; - } - if (!existingData.productUuid) { - existingData.productUuid = addDeviceStatusDto.productUuid; - } - if (!existingData.productType) { - existingData.productType = addDeviceStatusDto.productType; - } - if (!existingData.status) { - existingData.status = []; - } + // Use a transaction to handle concurrent updates + await runTransaction(dataRef, (existingData) => { + if (!existingData) { + existingData = {}; + } - // Create a map to track existing status codes - const statusMap = new Map( - existingData.status.map((item) => [item.code, item.value]), - ); + // Assign default values if fields are not present + if (!existingData.deviceTuyaUuid) { + existingData.deviceTuyaUuid = addDeviceStatusDto.deviceTuyaUuid; + } + if (!existingData.productUuid) { + existingData.productUuid = addDeviceStatusDto.productUuid; + } + if (!existingData.productType) { + existingData.productType = addDeviceStatusDto.productType; + } + if (!existingData.status) { + existingData.status = []; + } - // Update or add status codes + // Create a map to track existing status codes + const statusMap = new Map( + existingData.status.map((item) => [item.code, item.value]), + ); - for (const statusItem of addDeviceStatusDto.status) { - statusMap.set(statusItem.code, statusItem.value); - } + // Update or add status codes - // Convert the map back to an array format - existingData.status = Array.from(statusMap, ([code, value]) => ({ - code, - value, - })); + for (const statusItem of addDeviceStatusDto.status) { + statusMap.set(statusItem.code, statusItem.value); + } + + // Convert the map back to an array format + existingData.status = Array.from(statusMap, ([code, value]) => ({ + code, + value, + })); + + return existingData; + }); + + // Save logs to your repository const newLogs = addDeviceStatusDto.log.properties.map((property) => { return this.deviceStatusLogRepository.create({ deviceId: addDeviceStatusDto.deviceUuid, @@ -200,10 +215,9 @@ export class DeviceStatusFirebaseService { }); }); await this.deviceStatusLogRepository.save(newLogs); - // Save the updated data to Firebase - await set(dataRef, existingData); // Return the updated data - return existingData; + const snapshot: DataSnapshot = await get(dataRef); + return snapshot.val(); } }