From 2664f774b9f26426e9148ba76a035f5422177903 Mon Sep 17 00:00:00 2001 From: sumanvpacewisdom Date: Mon, 23 Mar 2026 22:25:20 +0530 Subject: [PATCH 1/6] Refactor cache handling in various services to improve clarity and efficiency. Updated cache set and delete methods in cacheHelper for session and user data. Simplified cache invalidation logic in EntityHelper and NotificationTemplateHelper by capturing old values before updates. Removed redundant cache invalidation after entity operations to streamline processing. --- src/generics/cacheHelper.js | 4 +- src/services/entity-type.js | 17 ++++---- src/services/entity.js | 82 +++--------------------------------- src/services/notification.js | 19 +++++---- 4 files changed, 29 insertions(+), 93 deletions(-) diff --git a/src/generics/cacheHelper.js b/src/generics/cacheHelper.js index 4a462037c..d31f97a84 100644 --- a/src/generics/cacheHelper.js +++ b/src/generics/cacheHelper.js @@ -484,7 +484,7 @@ const sessions = { if (sessionDetails) { // Cache the session data directly - await this.set(tenantCode, organizationCode, sessionId, sessionDetails) + await this.set(tenantCode, sessionId, sessionDetails) dbFetchedSessions.push(sessionDetails) console.log(`✅ [getSessionKafka] Session ${sessionId} fetched and cached`) } @@ -1322,7 +1322,7 @@ const mentee = { if (usersFromDb && usersFromDb.length > 0) { // Cache each fetched user individually for (const user of usersFromDb) { - await this.set(tenantCode, organizationCode, user.user_id, user) + await this.set(tenantCode, user.user_id, user) } // Add fetched users to result diff --git a/src/services/entity-type.js b/src/services/entity-type.js index eb1b85260..756d6644a 100644 --- a/src/services/entity-type.js +++ b/src/services/entity-type.js @@ -289,11 +289,12 @@ module.exports = class EntityHelper { } // Clear cache for affected models before deletion - await this._clearUserCachesForEntityTypeChange(organizationCode, tenantCode, { - id: entityToDelete.id, - value: entityToDelete.value, - modelNames: entityToDelete.model_names, - }) + await this._clearUserCachesForEntityTypeChange( + organizationCode, + tenantCode, + entityToDelete.model_names ? entityToDelete.model_names[0] : null, + entityToDelete.value + ) // SECOND: Delete from database const deleteCount = await entityTypeQueries.deleteOneEntityType(id, organizationCode, tenantCode) @@ -544,13 +545,13 @@ module.exports = class EntityHelper { }) ) - // 2. Clear entity type caches for unified model strategy + // 2. Clear entity type cache for the specific model + value if (modelName) { clearPromises.push( cacheHelper.entityTypes - .delete(tenantCode, organizationCode, `model:${modelName}:__ALL__`) + .delete(tenantCode, organizationCode, modelName, entityValue) .catch((error) => { - /* Failed to clear unified entity type cache - continue operation */ + /* Failed to clear entity type cache - continue operation */ }) ) } diff --git a/src/services/entity.js b/src/services/entity.js index 6b6d7a416..3dd55a118 100644 --- a/src/services/entity.js +++ b/src/services/entity.js @@ -50,27 +50,6 @@ module.exports = class EntityHelper { } } - // Invalidate entity list caches after creation - if (entity && sanitizedData.entity_type_id) { - // Separate try-catch for each cache deletion to ensure all caches are cleared - try { - await cacheHelper.forms.delete( - tenantCode, - common.SYSTEM, - 'entity_list', - sanitizedData.entity_type_id - ) - } catch (cacheError) { - console.error(`❌ Failed to invalidate entity_list cache after creation:`, cacheError) - } - - try { - await cacheHelper.forms.delete(tenantCode, common.SYSTEM, 'entity_list_all', 'all_entities') - } catch (cacheError) { - console.error(`❌ Failed to invalidate entity_list_all cache after creation:`, cacheError) - } - } - return responses.successResponse({ statusCode: httpStatusCode.created, message: 'ENTITY_CREATED_SUCCESSFULLY', @@ -163,23 +142,6 @@ module.exports = class EntityHelper { } } - // Invalidate entity list caches after update - if (updatedEntity && (updatedEntity.entity_type_id || sanitizedData.entity_type_id)) { - const entityTypeId = updatedEntity.entity_type_id || sanitizedData.entity_type_id - // Separate try-catch for each cache deletion to ensure all caches are cleared - try { - await cacheHelper.forms.delete(tenantCode, common.SYSTEM, 'entity_list', entityTypeId) - } catch (cacheError) { - console.error(`❌ Failed to invalidate entity_list cache after update:`, cacheError) - } - - try { - await cacheHelper.forms.delete(tenantCode, common.SYSTEM, 'entity_list_all', 'all_entities') - } catch (cacheError) { - console.error(`❌ Failed to invalidate entity_list_all cache after update:`, cacheError) - } - } - return responses.successResponse({ statusCode: httpStatusCode.accepted, message: 'ENTITY_UPDATED_SUCCESSFULLY', @@ -387,14 +349,6 @@ module.exports = class EntityHelper { } } - // Invalidate entity list caches after deletion - try { - // Clear all entity list caches since we don't know the entity_type_id after deletion - await cacheHelper.forms.delete(tenantCode, common.SYSTEM, 'entity_list_all', 'all_entities') - } catch (cacheError) { - console.error(`❌ Failed to invalidate entity list cache after deletion:`, cacheError) - } - return responses.successResponse({ statusCode: httpStatusCode.accepted, message: 'ENTITY_DELETED_SUCCESSFULLY', @@ -441,35 +395,13 @@ module.exports = class EntityHelper { filter['entity_type_id'] = entityType } - // Try to get entities from cache first (only cache paginated lists without search) - const cacheKey = `${entityType || 'all'}_page${pageNo}_limit${pageSize}` - let entities = null - - if (!searchText) { - entities = await cacheHelper.forms.get(tenantCode, common.SYSTEM, 'entity_list', cacheKey) - if (entities) { - } - } - - if (!entities) { - // Optimized: Get entities with entity_type details included - eliminates N+1 queries for clients - entities = await entityQueries.getAllEntitiesWithEntityTypeDetails( - filter, - [tenantCode], - pageNo, - pageSize, - searchText - ) - - // Cache the result if no search text (searchable results shouldn't be cached) - if (!searchText && entities) { - try { - await cacheHelper.forms.set(tenantCode, common.SYSTEM, 'entity_list', cacheKey, entities) - } catch (cacheError) { - console.error(`❌ Failed to cache entity list:`, cacheError) - } - } - } + const entities = await entityQueries.getAllEntitiesWithEntityTypeDetails( + filter, + [tenantCode], + pageNo, + pageSize, + searchText + ) if (entities.rows == 0 || entities.count == 0) { return responses.failureResponse({ diff --git a/src/services/notification.js b/src/services/notification.js index 916db26bb..f4f0232ef 100644 --- a/src/services/notification.js +++ b/src/services/notification.js @@ -76,6 +76,11 @@ module.exports = class NotificationTemplateHelper { bodyData['organization_code'] = tokenInformation.organization_code bodyData['updated_by'] = tokenInformation.id + // Fetch original template BEFORE update to capture old code for cache invalidation + const existingTemplates = await notificationTemplateQueries.findTemplatesByFilter(filter) + const existingTemplate = existingTemplates?.[0] + const oldCode = existingTemplate?.code || filter.code + const result = await notificationTemplateQueries.updateTemplate(filter, bodyData, tenantCode) if (result == 0) { return responses.failureResponse({ @@ -85,23 +90,21 @@ module.exports = class NotificationTemplateHelper { }) } - // Delete old cache - const existingTemplates = await notificationTemplateQueries.findTemplatesByFilter(filter) - const existingTemplate = existingTemplates?.[0] - const templateCode = bodyData.code || existingTemplate?.code || filter.code + // Delete cache using old code (captured before update) and new code (if changed) + const newCode = bodyData.code || oldCode try { - if (templateCode) { + if (oldCode) { await cacheHelper.notificationTemplates.delete( tenantCode, tokenInformation.organization_code, - templateCode + oldCode ) } - if (existingTemplate?.code && existingTemplate.code !== templateCode) { + if (newCode && newCode !== oldCode) { await cacheHelper.notificationTemplates.delete( tenantCode, tokenInformation.organization_code, - existingTemplate.code + newCode ) } } catch (cacheError) { From 08f9883d513a3b9728fa587d149bbd900440978d Mon Sep 17 00:00:00 2001 From: sumanvpacewisdom Date: Thu, 26 Mar 2026 21:07:18 +0530 Subject: [PATCH 2/6] Refactor cache handling in session and user retrieval methods across services to improve efficiency. Updated cache deletion logic in AdminService and streamlined user cache clearing in EntityHelper. Enhanced organization extension updates in OrganizationService by including tenantCode in the upsert method. --- src/generics/cacheHelper.js | 19 +++++++----------- src/services/admin.js | 2 +- src/services/entity-type.js | 39 ++++++++++++++++++------------------ src/services/organization.js | 2 +- 4 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/generics/cacheHelper.js b/src/generics/cacheHelper.js index d31f97a84..c98cc4fcc 100644 --- a/src/generics/cacheHelper.js +++ b/src/generics/cacheHelper.js @@ -439,7 +439,7 @@ const sessions = { try { // Handle single session ID case if (typeof sessionIds === 'string') { - return await this.get(tenantCode, organizationCode, sessionIds) + return await this.get(tenantCode, sessionIds) } // Handle array case - smart caching with immediate DB fetch @@ -508,7 +508,7 @@ const sessions = { const fallbackResults = [] for (const sessionId of Array.isArray(sessionIds) ? sessionIds : [sessionIds]) { try { - const session = await this.get(tenantCode, organizationCode, sessionId) + const session = await this.get(tenantCode, sessionId) if (session) fallbackResults.push(session) } catch (fallbackError) { console.error( @@ -1033,7 +1033,7 @@ const mentor = { try { // Handle single user ID case if (typeof userIds === 'string') { - return await this.get(tenantCode, organizationCode, userIds) + return await this.get(tenantCode, userIds) } // Handle array case - smart caching with immediate DB fetch @@ -1061,7 +1061,7 @@ const mentor = { // Step 4: Fetch missing users from DB immediately using getUsersByUserIds const dbFetchedUsers = [] - const userMentorEntries = [] + let userMentorEntries = [] if (missingUserIds.length > 0) { try { const usersFromDb = await userQueries.getUsersByUserIds(missingUserIds, {}, tenantCode, false) @@ -1102,7 +1102,7 @@ const mentor = { const fallbackResults = [] for (const userId of Array.isArray(userIds) ? userIds : [userIds]) { try { - const user = await this.get(tenantCode, organizationCode, userId) + const user = await this.get(tenantCode, userId) if (user) fallbackResults.push(user) } catch (fallbackError) { console.error(`❌ [getMenteeKafka] Fallback failed for user ${userId}:`, fallbackError.message) @@ -1280,7 +1280,7 @@ const mentee = { try { // Handle single user ID case if (typeof userIds === 'string') { - return await this.get(tenantCode, organizationCode, userIds) + return await this.get(tenantCode, userIds) } // Handle array case - smart caching with immediate DB fetch @@ -1308,7 +1308,6 @@ const mentee = { // Step 3: Fetch missing users from DB immediately using getUsersByUserIds const dbFetchedUsers = [] - let userMentorEntries = [] if (missingUserIds.length > 0) { try { console.log(`🔄 [getMenteeKafka] Fetching ${missingUserIds.length} users from database`) @@ -1328,10 +1327,6 @@ const mentee = { // Add fetched users to result dbFetchedUsers.push(...usersFromDb) - // Create user ID to is_mentor mapping using map - const userMentorEntries = usersFromDb.map((user) => [user.user_id, user.is_mentor || false]) - Object.assign(userIsMentorMap, Object.fromEntries(userMentorEntries)) - console.log(`✅ [getMenteeKafka] ${usersFromDb.length} users fetched from DB and cached`) } } catch (dbError) { @@ -1349,7 +1344,7 @@ const mentee = { const fallbackResults = [] for (const userId of Array.isArray(userIds) ? userIds : [userIds]) { try { - const user = await this.get(tenantCode, organizationCode, userId) + const user = await this.get(tenantCode, userId) if (user) fallbackResults.push(user) } catch (fallbackError) { console.error(`❌ [getMenteeKafka] Fallback failed for user ${userId}:`, fallbackError.message) diff --git a/src/services/admin.js b/src/services/admin.js index 4baacf9bb..941f49e8d 100644 --- a/src/services/admin.js +++ b/src/services/admin.js @@ -694,7 +694,7 @@ module.exports = class AdminService { if (unenrollDetails && unenrollDetails.deletedCount > 0 && Array.isArray(unenrollDetails.deletedRecords)) { for (const menteeData of unenrollDetails.deletedRecords) { try { - await cacheHelper.mentee.delete(tenantCode, menteeData.organization_code, menteeData.mentee_id) + await cacheHelper.mentee.delete(tenantCode, menteeData.mentee_id) } catch (cacheError) { console.error(`Cache deletion failed for mentee ${menteeId}:`, cacheError) } diff --git a/src/services/entity-type.js b/src/services/entity-type.js index 756d6644a..21ece3e03 100644 --- a/src/services/entity-type.js +++ b/src/services/entity-type.js @@ -118,12 +118,13 @@ module.exports = class EntityHelper { // Clear user caches since entity types affect user profiles const updatedEntity = updatedEntityType[0] - await this._clearUserCachesForEntityTypeChange( - orgCode, - tenantCode, - updatedEntity.model_names ? updatedEntity.model_names[0] : null, - updatedEntity.value - ) + const updatedModelNames = updatedEntity.model_names || [] + for (const modelName of updatedModelNames) { + await this._clearUserCachesForEntityTypeChange(orgCode, tenantCode, modelName, updatedEntity.value) + } + if (updatedModelNames.length === 0) { + await this._clearUserCachesForEntityTypeChange(orgCode, tenantCode, null, updatedEntity.value) + } return responses.successResponse({ statusCode: httpStatusCode.accepted, @@ -289,12 +290,18 @@ module.exports = class EntityHelper { } // Clear cache for affected models before deletion - await this._clearUserCachesForEntityTypeChange( - organizationCode, - tenantCode, - entityToDelete.model_names ? entityToDelete.model_names[0] : null, - entityToDelete.value - ) + const deleteModelNames = entityToDelete.model_names || [] + for (const modelName of deleteModelNames) { + await this._clearUserCachesForEntityTypeChange( + organizationCode, + tenantCode, + modelName, + entityToDelete.value + ) + } + if (deleteModelNames.length === 0) { + await this._clearUserCachesForEntityTypeChange(organizationCode, tenantCode, null, entityToDelete.value) + } // SECOND: Delete from database const deleteCount = await entityTypeQueries.deleteOneEntityType(id, organizationCode, tenantCode) @@ -340,14 +347,6 @@ module.exports = class EntityHelper { } } - // Clear user caches since entity types affect user profiles - await this._clearUserCachesForEntityTypeChange( - organizationCode, - tenantCode, - entityToDelete.model_names ? entityToDelete.model_names[0] : null, - entityToDelete.value - ) - return responses.successResponse({ statusCode: httpStatusCode.accepted, message: 'ENTITY_TYPE_DELETED_SUCCESSFULLY', diff --git a/src/services/organization.js b/src/services/organization.js index 5652a8972..900adf551 100644 --- a/src/services/organization.js +++ b/src/services/organization.js @@ -37,7 +37,7 @@ module.exports = class OrganizationService { mentor_feedback_question_set: bodyData.mentor_feedback_question_set, updated_by: decodedToken.id, } - const orgExtension = await organisationExtensionQueries.upsert(extensionData) + const orgExtension = await organisationExtensionQueries.upsert(extensionData, tenantCode) // Update cache with fresh data after update try { From 74785635ee299de19d232e5344e36d83c7095d49 Mon Sep 17 00:00:00 2001 From: sumanvpacewisdom Date: Fri, 27 Mar 2026 17:29:33 +0530 Subject: [PATCH 3/6] fix :Delete cache call and error log variable name --- src/services/admin.js | 2 +- src/services/entity-type.js | 30 +++++++++++------------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/services/admin.js b/src/services/admin.js index 941f49e8d..3399485ac 100644 --- a/src/services/admin.js +++ b/src/services/admin.js @@ -696,7 +696,7 @@ module.exports = class AdminService { try { await cacheHelper.mentee.delete(tenantCode, menteeData.mentee_id) } catch (cacheError) { - console.error(`Cache deletion failed for mentee ${menteeId}:`, cacheError) + console.error(`Cache deletion failed for mentee ${menteeData.mentee_id}:`, cacheError) } } } diff --git a/src/services/entity-type.js b/src/services/entity-type.js index 21ece3e03..eb1f20bd9 100644 --- a/src/services/entity-type.js +++ b/src/services/entity-type.js @@ -118,13 +118,9 @@ module.exports = class EntityHelper { // Clear user caches since entity types affect user profiles const updatedEntity = updatedEntityType[0] - const updatedModelNames = updatedEntity.model_names || [] - for (const modelName of updatedModelNames) { + for (const modelName of updatedEntity.model_names) { await this._clearUserCachesForEntityTypeChange(orgCode, tenantCode, modelName, updatedEntity.value) } - if (updatedModelNames.length === 0) { - await this._clearUserCachesForEntityTypeChange(orgCode, tenantCode, null, updatedEntity.value) - } return responses.successResponse({ statusCode: httpStatusCode.accepted, @@ -289,20 +285,6 @@ module.exports = class EntityHelper { }) } - // Clear cache for affected models before deletion - const deleteModelNames = entityToDelete.model_names || [] - for (const modelName of deleteModelNames) { - await this._clearUserCachesForEntityTypeChange( - organizationCode, - tenantCode, - modelName, - entityToDelete.value - ) - } - if (deleteModelNames.length === 0) { - await this._clearUserCachesForEntityTypeChange(organizationCode, tenantCode, null, entityToDelete.value) - } - // SECOND: Delete from database const deleteCount = await entityTypeQueries.deleteOneEntityType(id, organizationCode, tenantCode) if (deleteCount === 0) { @@ -313,6 +295,16 @@ module.exports = class EntityHelper { }) } + // Clear user caches after successful deletion + for (const modelName of entityToDelete.model_names) { + await this._clearUserCachesForEntityTypeChange( + organizationCode, + tenantCode, + modelName, + entityToDelete.value + ) + } + // THIRD: Remove individual entity type from cache try { // For each model this entity belonged to From d94f0f6c837558e3a1a1291bb93e82f02a9c1c18 Mon Sep 17 00:00:00 2001 From: sumanvpacewisdom Date: Mon, 30 Mar 2026 16:12:52 +0530 Subject: [PATCH 4/6] Removed array format tenant from query --- src/services/entity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/entity.js b/src/services/entity.js index 3dd55a118..5d12c21ae 100644 --- a/src/services/entity.js +++ b/src/services/entity.js @@ -397,7 +397,7 @@ module.exports = class EntityHelper { const entities = await entityQueries.getAllEntitiesWithEntityTypeDetails( filter, - [tenantCode], + tenantCode, pageNo, pageSize, searchText From e360deeb0cfffea0a0aeb8f939f36a221d70882c Mon Sep 17 00:00:00 2001 From: sumanvpacewisdom Date: Mon, 30 Mar 2026 16:43:45 +0530 Subject: [PATCH 5/6] removed dead code for update template --- src/services/notification.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/services/notification.js b/src/services/notification.js index 100ed8ab4..1f3f38e67 100644 --- a/src/services/notification.js +++ b/src/services/notification.js @@ -89,8 +89,6 @@ module.exports = class NotificationTemplateHelper { }) } - // Delete cache using old code (captured before update) and new code (if changed) - const newCode = bodyData.code || oldCode try { if (oldCode) { await cacheHelper.notificationTemplates.delete( @@ -99,13 +97,6 @@ module.exports = class NotificationTemplateHelper { oldCode ) } - if (newCode && newCode !== oldCode) { - await cacheHelper.notificationTemplates.delete( - tenantCode, - tokenInformation.organization_code, - newCode - ) - } } catch (cacheError) { console.error(`❌ Failed to update notification template cache:`, cacheError) } From 46ed073cec26c14eacf0fb3096f9b8e4afae1ad2 Mon Sep 17 00:00:00 2001 From: sumanvpacewisdom Date: Mon, 30 Mar 2026 18:39:15 +0530 Subject: [PATCH 6/6] Added Back saish changes with my changes --- src/services/notification.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/services/notification.js b/src/services/notification.js index 1e41cfa62..3599d9068 100644 --- a/src/services/notification.js +++ b/src/services/notification.js @@ -86,10 +86,9 @@ module.exports = class NotificationTemplateHelper { bodyData['organization_code'] = tokenInformation.organization_code bodyData['updated_by'] = tokenInformation.id - // Fetch original template BEFORE update to capture old code for cache invalidation + // Fetch existing template BEFORE update to capture the old code for cache invalidation const existingTemplates = await notificationTemplateQueries.findTemplatesByFilter(filter) const existingTemplate = existingTemplates?.[0] - const oldCode = existingTemplate?.code || filter.code const result = await notificationTemplateQueries.updateTemplate(filter, bodyData, tenantCode) if (result == 0) { @@ -100,6 +99,10 @@ module.exports = class NotificationTemplateHelper { }) } + // Delete cache for both old code and new code (in case code was changed) + const oldCode = existingTemplate?.code + const newCode = bodyData.code + const isDefaultOrg = tokenInformation.organization_code === process.env.DEFAULT_ORGANISATION_CODE try { if (oldCode) { if (isDefaultOrg) { @@ -112,6 +115,17 @@ module.exports = class NotificationTemplateHelper { ) } } + if (newCode && newCode !== oldCode) { + if (isDefaultOrg) { + await cacheHelper.notificationTemplates.deleteNotificationsAcrossAllOrgs(tenantCode, newCode) + } else { + await cacheHelper.notificationTemplates.delete( + tenantCode, + tokenInformation.organization_code, + newCode + ) + } + } } catch (cacheError) { console.error(`❌ Failed to update notification template cache:`, cacheError) }