From 7383c2d626ac77c6d8f25676188a95ce22ee55a4 Mon Sep 17 00:00:00 2001 From: Merul Dhiman Date: Fri, 14 Nov 2025 15:26:33 +0530 Subject: [PATCH 1/3] fix: issue with cerberus only triggering after an edit --- .../src/controllers/WebhookController.ts | 34 +++++++------- .../src/controllers/GroupController.ts | 46 +++++++++++++++++++ .../src/services/GroupService.ts | 22 ++++----- .../src/web3adapter/watchers/subscriber.ts | 18 ++++++++ 4 files changed, 89 insertions(+), 31 deletions(-) diff --git a/platforms/cerberus/src/controllers/WebhookController.ts b/platforms/cerberus/src/controllers/WebhookController.ts index d16c0116..0657712a 100644 --- a/platforms/cerberus/src/controllers/WebhookController.ts +++ b/platforms/cerberus/src/controllers/WebhookController.ts @@ -175,16 +175,15 @@ export class WebhookController { // Only process if there's actually a charter change, not just a message update if (newCharter !== undefined && newCharter !== null && oldCharter !== newCharter) { - try { - await this.cerberusTriggerService.processCharterChange( - group.id, - group.name, - oldCharter, - newCharter - ); - } catch (error) { + // Don't await - let it run asynchronously to avoid blocking webhook response + this.cerberusTriggerService.processCharterChange( + group.id, + group.name, + oldCharter, + newCharter + ).catch((error) => { console.error("Error in processCharterChange:", error); - } + }); } } else { // Check if group already exists by ename (only if ename is available) @@ -223,16 +222,15 @@ export class WebhookController { // Check if new group has a charter and send Cerberus welcome message if (group.charter) { - try { - await this.cerberusTriggerService.processCharterChange( - group.id, - group.name, - undefined, // No old charter for new groups - group.charter - ); - } catch (error) { + // Don't await - let it run asynchronously to avoid blocking webhook response + this.cerberusTriggerService.processCharterChange( + group.id, + group.name, + undefined, // No old charter for new groups + group.charter + ).catch((error) => { console.error("Error in processCharterChange for new group:", error); - } + }); } } } diff --git a/platforms/group-charter-manager-api/src/controllers/GroupController.ts b/platforms/group-charter-manager-api/src/controllers/GroupController.ts index e9c03b2b..edf1d92c 100644 --- a/platforms/group-charter-manager-api/src/controllers/GroupController.ts +++ b/platforms/group-charter-manager-api/src/controllers/GroupController.ts @@ -2,6 +2,7 @@ import { Request, Response } from "express"; import { GroupService } from "../services/GroupService"; import { CharterSignatureService } from "../services/CharterSignatureService"; import { spinUpEVault } from "web3-adapter"; +import { adapter } from "../web3adapter"; import dotenv from "dotenv"; dotenv.config(); @@ -27,6 +28,10 @@ export class GroupController { participants: [] }); + // Lock the group so it doesn't sync until charter+ename are added + adapter.addToLockedIds(group.id); + console.log("🔒 Locked group from syncing until charter is added:", group.id); + // Add participants including the creator const allParticipants = [...new Set([userId, ...participants])]; for (const participantId of allParticipants) { @@ -142,6 +147,15 @@ export class GroupController { updateData.ename = evaultResult.w3id; } + // Unlock the group so it CAN sync now that it has charter+ename + if (needsEVault) { + const lockIndex = adapter.lockedIds.indexOf(id); + if (lockIndex > -1) { + adapter.lockedIds.splice(lockIndex, 1); + console.log("🔓 Unlocked group for syncing with charter+ename:", id); + } + } + // Now save with both charter and ename (if provisioned) const updatedGroup = await this.groupService.updateGroup(id, updateData); @@ -149,6 +163,38 @@ export class GroupController { return res.status(404).json({ error: "Group not found" }); } + // HACK: Manually trigger sync after delay to ensure complete data is sent + if (needsEVault) { + console.log("⏰ Scheduling manual sync for group with charter+ename..."); + setTimeout(async () => { + try { + // Re-fetch the complete group entity with all relations + const completeGroup = await this.groupService.getGroupById(id); + if (completeGroup && completeGroup.charter && completeGroup.ename) { + console.log("📤 Manually syncing complete group:", { + id: completeGroup.id, + name: completeGroup.name, + hasCharter: !!completeGroup.charter, + charterLength: completeGroup.charter?.length || 0, + hasEname: !!completeGroup.ename, + ename: completeGroup.ename + }); + + // Convert to plain object and trigger the adapter manually + const plainGroup = JSON.parse(JSON.stringify(completeGroup)); + await adapter.handleChange({ + data: plainGroup, + tableName: "groups" + }); + + console.log("✅ Manual sync completed for group:", completeGroup.id); + } + } catch (error) { + console.error("❌ Error in manual sync:", error); + } + }, 2000); // 2 second delay + } + res.json(updatedGroup); } catch (error) { console.error("Error updating charter:", error); diff --git a/platforms/group-charter-manager-api/src/services/GroupService.ts b/platforms/group-charter-manager-api/src/services/GroupService.ts index 746c8031..401c1f60 100644 --- a/platforms/group-charter-manager-api/src/services/GroupService.ts +++ b/platforms/group-charter-manager-api/src/services/GroupService.ts @@ -28,29 +28,25 @@ export class GroupService { } async updateGroup(id: string, groupData: Partial): Promise { - // If updating the charter, we need to delete all existing signatures - // since the charter content has changed - if (groupData.charter !== undefined) { - // Get the current group to check if charter is being updated - const currentGroup = await this.getGroupById(id); - if (currentGroup && currentGroup.charter !== groupData.charter) { - // Charter content has changed, so delete all existing signatures - console.log(`Charter updated for group ${id}, deleting all existing signatures`); - await this.charterSignatureService.deleteAllSignaturesForGroup(id); - } - } - // Get the current group, merge the data, and save it to trigger ORM events const currentGroup = await this.getGroupById(id); if (!currentGroup) { throw new Error("Group not found"); } + // Check if charter is being updated/added to delete signatures BEFORE saving + const charterChanged = groupData.charter !== undefined && currentGroup.charter !== groupData.charter; + if (charterChanged) { + console.log(`Charter updated for group ${id}, deleting all existing signatures before save`); + await this.charterSignatureService.deleteAllSignaturesForGroup(id); + } + // Merge the new data with the existing group Object.assign(currentGroup, groupData); - // Save the merged group to trigger ORM subscribers + // Save the merged group to trigger ORM subscribers - ONE save with all data const updatedGroup = await this.groupRepository.save(currentGroup); + return updatedGroup; } diff --git a/platforms/group-charter-manager-api/src/web3adapter/watchers/subscriber.ts b/platforms/group-charter-manager-api/src/web3adapter/watchers/subscriber.ts index ecd06bc6..d4546c53 100644 --- a/platforms/group-charter-manager-api/src/web3adapter/watchers/subscriber.ts +++ b/platforms/group-charter-manager-api/src/web3adapter/watchers/subscriber.ts @@ -200,6 +200,12 @@ export class PostgresSubscriber implements EntitySubscriberInterface { // Handle regular entity changes const data = this.entityToPlain(entity); if (!data.id) return; + + // Skip groups without charter - they'll be manually synced when charter is added + if (tableName === "groups" && !data.charter) { + console.log("⏭️ Skipping group without charter:", entity.id); + return; + } try { setTimeout(async () => { @@ -227,6 +233,18 @@ export class PostgresSubscriber implements EntitySubscriberInterface { tableName ); + // Debug logging for groups + if (tableName === "groups") { + console.log("📤 Syncing group:", { + id: data.id, + name: data.name, + hasCharter: !!data.charter, + charterLength: data.charter?.length || 0, + hasEname: !!data.ename, + ename: data.ename + }); + } + const envelope = await this.adapter.handleChange({ data, tableName: tableName.toLowerCase(), From 719cde81ae7f76e5c9daaeb75d6273351f9dbf65 Mon Sep 17 00:00:00 2001 From: Merul Dhiman Date: Fri, 14 Nov 2025 15:28:19 +0530 Subject: [PATCH 2/3] chore: remove logs --- .../src/controllers/GroupController.ts | 16 +--------------- .../src/services/GroupService.ts | 1 - .../src/web3adapter/watchers/subscriber.ts | 13 ------------- 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/platforms/group-charter-manager-api/src/controllers/GroupController.ts b/platforms/group-charter-manager-api/src/controllers/GroupController.ts index edf1d92c..b980ab3f 100644 --- a/platforms/group-charter-manager-api/src/controllers/GroupController.ts +++ b/platforms/group-charter-manager-api/src/controllers/GroupController.ts @@ -30,7 +30,6 @@ export class GroupController { // Lock the group so it doesn't sync until charter+ename are added adapter.addToLockedIds(group.id); - console.log("🔒 Locked group from syncing until charter is added:", group.id); // Add participants including the creator const allParticipants = [...new Set([userId, ...participants])]; @@ -152,7 +151,6 @@ export class GroupController { const lockIndex = adapter.lockedIds.indexOf(id); if (lockIndex > -1) { adapter.lockedIds.splice(lockIndex, 1); - console.log("🔓 Unlocked group for syncing with charter+ename:", id); } } @@ -165,32 +163,20 @@ export class GroupController { // HACK: Manually trigger sync after delay to ensure complete data is sent if (needsEVault) { - console.log("⏰ Scheduling manual sync for group with charter+ename..."); setTimeout(async () => { try { // Re-fetch the complete group entity with all relations const completeGroup = await this.groupService.getGroupById(id); if (completeGroup && completeGroup.charter && completeGroup.ename) { - console.log("📤 Manually syncing complete group:", { - id: completeGroup.id, - name: completeGroup.name, - hasCharter: !!completeGroup.charter, - charterLength: completeGroup.charter?.length || 0, - hasEname: !!completeGroup.ename, - ename: completeGroup.ename - }); - // Convert to plain object and trigger the adapter manually const plainGroup = JSON.parse(JSON.stringify(completeGroup)); await adapter.handleChange({ data: plainGroup, tableName: "groups" }); - - console.log("✅ Manual sync completed for group:", completeGroup.id); } } catch (error) { - console.error("❌ Error in manual sync:", error); + console.error("Error in manual sync:", error); } }, 2000); // 2 second delay } diff --git a/platforms/group-charter-manager-api/src/services/GroupService.ts b/platforms/group-charter-manager-api/src/services/GroupService.ts index 401c1f60..bf9793cb 100644 --- a/platforms/group-charter-manager-api/src/services/GroupService.ts +++ b/platforms/group-charter-manager-api/src/services/GroupService.ts @@ -37,7 +37,6 @@ export class GroupService { // Check if charter is being updated/added to delete signatures BEFORE saving const charterChanged = groupData.charter !== undefined && currentGroup.charter !== groupData.charter; if (charterChanged) { - console.log(`Charter updated for group ${id}, deleting all existing signatures before save`); await this.charterSignatureService.deleteAllSignaturesForGroup(id); } diff --git a/platforms/group-charter-manager-api/src/web3adapter/watchers/subscriber.ts b/platforms/group-charter-manager-api/src/web3adapter/watchers/subscriber.ts index d4546c53..62a1b095 100644 --- a/platforms/group-charter-manager-api/src/web3adapter/watchers/subscriber.ts +++ b/platforms/group-charter-manager-api/src/web3adapter/watchers/subscriber.ts @@ -203,7 +203,6 @@ export class PostgresSubscriber implements EntitySubscriberInterface { // Skip groups without charter - they'll be manually synced when charter is added if (tableName === "groups" && !data.charter) { - console.log("⏭️ Skipping group without charter:", entity.id); return; } @@ -233,18 +232,6 @@ export class PostgresSubscriber implements EntitySubscriberInterface { tableName ); - // Debug logging for groups - if (tableName === "groups") { - console.log("📤 Syncing group:", { - id: data.id, - name: data.name, - hasCharter: !!data.charter, - charterLength: data.charter?.length || 0, - hasEname: !!data.ename, - ename: data.ename - }); - } - const envelope = await this.adapter.handleChange({ data, tableName: tableName.toLowerCase(), From 6aa6389347bf95fea3ac6b4fcb3e7f0db7845e80 Mon Sep 17 00:00:00 2001 From: Merul Dhiman Date: Fri, 14 Nov 2025 15:31:58 +0530 Subject: [PATCH 3/3] chore: increaase timeout to 5s --- .../src/controllers/GroupController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/group-charter-manager-api/src/controllers/GroupController.ts b/platforms/group-charter-manager-api/src/controllers/GroupController.ts index b980ab3f..c6664842 100644 --- a/platforms/group-charter-manager-api/src/controllers/GroupController.ts +++ b/platforms/group-charter-manager-api/src/controllers/GroupController.ts @@ -178,7 +178,7 @@ export class GroupController { } catch (error) { console.error("Error in manual sync:", error); } - }, 2000); // 2 second delay + }, 5000); // 5 second delay } res.json(updatedGroup);