From 64b2888b8094ae1a6340c72b332120d0a1a09a53 Mon Sep 17 00:00:00 2001 From: "Nilson.Henao" Date: Sun, 20 Sep 2026 15:14:38 +0000 Subject: [PATCH] fix: await change tracking when applications and microservices are updated Three loops in the application and microservice update paths iterated with `forEach(async ...)`, so the ChangeTrackingService updates inside them were started and never awaited. The endpoint returned before they had been written, and a node could poll in the gap and see no pending change: the update was stored in the Controller and never reached the agent. Observed on Controller 3.8.2 with Edgelet v1.0.3-rc.1: PUT /api/v3/application and PUT /api/v3/application/yaml stored a changed microservice and no node ever applied it; PATCH /api/v3/microservices/ did apply, in about 33 s. The difference is the awaited change tracking, not the payload. Replaces the three `forEach(async ...)` loops with `for ... of`, so every ChangeTrackingService.update is awaited inside the transaction that made the change. No API change. Signed-off-by: Nilson.Henao Co-Authored-By: Claude Opus 5 (1M context) --- src/services/application-service.js | 24 +++++++----------------- src/services/microservices-service.js | 6 ++++-- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/services/application-service.js b/src/services/application-service.js index c55254e9..9f7e1973 100644 --- a/src/services/application-service.js +++ b/src/services/application-service.js @@ -313,25 +313,15 @@ const _updateMicroservices = async function (application, microservices, isCLI, for (const microservice of updatedMicroservices) { await MicroserviceService.createMicroserviceEndPoint(microservice, isCLI, transaction) } - iofogUuids - .filter(onlyUnique) - .filter((val) => val !== null) - for (const iofogUuid of iofogUuids) { + for (const iofogUuid of iofogUuids.filter(onlyUnique).filter((val) => val !== null)) { await ChangeTrackingService.update(iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) } - oldMsvcsIofogUuids - .filter(onlyUnique) - .filter((val) => val !== null) - .forEach(async (iofogUuid) => { - await MicroserviceService.updateChangeTracking(true, iofogUuid, transaction) - }) - - updatedMsvcsUuid - .filter(onlyUnique) - .filter((val) => val !== null) - .forEach(async (iofogUuid) => { - await MicroserviceService.updateChangeTracking(true, iofogUuid, transaction) - }) + for (const iofogUuid of oldMsvcsIofogUuids.filter(onlyUnique).filter((val) => val !== null)) { + await MicroserviceService.updateChangeTracking(true, iofogUuid, transaction) + } + for (const iofogUuid of updatedMsvcsUuid.filter(onlyUnique).filter((val) => val !== null)) { + await MicroserviceService.updateChangeTracking(true, iofogUuid, transaction) + } } const getUserApplicationsEndPoint = async function (isCLI, transaction) { diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 00c64cd9..a973921e 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -1709,13 +1709,15 @@ async function deleteMicroserviceEndPoint (microserviceUuid, microserviceData, i async function deleteNotRunningMicroservices (fog, transaction) { const microservices = await MicroserviceManager.findAllWithStatuses({ iofogUuid: fog.uuid }, transaction) - microservices + const toDelete = microservices .filter((microservice) => microservice.delete) .filter((microservice) => microservice.microserviceStatus.status === MicroserviceStates.UNKNOWN || microservice.microserviceStatus.status === MicroserviceStates.STOPPING || microservice.microserviceStatus.status === MicroserviceStates.DELETING || microservice.microserviceStatus.status === MicroserviceStates.MARKED_FOR_DELETION) - .forEach(async (microservice) => { await deleteMicroserviceWithRoutesAndPortMappings(microservice, transaction) }) + for (const microservice of toDelete) { + await deleteMicroserviceWithRoutesAndPortMappings(microservice, transaction) + } } async function createPortMappingEndPoint (microserviceUuid, portMappingData, isCLI, transaction) {