Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 8 additions & 78 deletions src/services/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ module.exports = class EntityHelper {
// Invalidate entityType cache using the fetched entityType details
if (entityTypeDetails && entityTypeDetails.value && entityTypeDetails.model_names) {
try {
// Delete entityType cache for each model using the actual entityType value
for (const modelName of entityTypeDetails.model_names) {
await cacheHelper.entityTypes.delete(
tenantCode,
Expand All @@ -50,27 +49,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',
Expand Down Expand Up @@ -148,7 +126,6 @@ module.exports = class EntityHelper {
)

if (entityTypeDetails && entityTypeDetails.value && entityTypeDetails.model_names) {
// Delete entityType cache for each model using the actual entityType value
for (const modelName of entityTypeDetails.model_names) {
await cacheHelper.entityTypes.delete(
tenantCode,
Expand All @@ -163,23 +140,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',
Expand Down Expand Up @@ -373,7 +333,6 @@ module.exports = class EntityHelper {
// Invalidate entityType cache using the fetched entityType details
if (entityTypeDetails && entityTypeDetails.value && entityTypeDetails.model_names) {
try {
// Delete entityType cache for each model using the actual entityType value
for (const modelName of entityTypeDetails.model_names) {
await cacheHelper.entityTypes.delete(
tenantCode,
Expand All @@ -387,14 +346,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',
Expand Down Expand Up @@ -441,35 +392,14 @@ 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)
}
}
}
// Optimized: Get entities with entity_type details included - eliminates N+1 queries for clients
const entities = await entityQueries.getAllEntitiesWithEntityTypeDetails(
filter,
[tenantCode],
pageNo,
pageSize,
searchText
)

if (entities.rows == 0 || entities.count == 0) {
return responses.failureResponse({
Expand Down
52 changes: 10 additions & 42 deletions src/services/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,50 +160,18 @@ module.exports = class modulesHelper {
try {
const offset = common.getPaginationOffset(page, limit)

// Try to get modules from cache first (only cache without search)
const cacheKey = `page${page}_limit${limit}`
let modules = null

if (!search || search.trim() === '') {
modules = await cacheHelper.forms.get(
tenantCode,
organizationId || common.SYSTEM,
'modules_list',
cacheKey
)
if (modules) {
}
const filter = {
tenant_code: tenantCode,
}

if (!modules) {
const filter = {
tenant_code: tenantCode,
}
if (search && search.trim() !== '') {
filter.code = { [Op.iLike]: `%${search.trim()}%` }
}
const options = {
offset,
limit,
}
const attributes = ['id', 'code', 'status']
modules = await modulesQueries.findAllModules(filter, attributes, options, tenantCode)

// Cache the result if no search text
if ((!search || search.trim() === '') && modules) {
try {
await cacheHelper.forms.set(
tenantCode,
organizationId || common.SYSTEM,
'modules_list',
cacheKey,
modules
)
} catch (cacheError) {
console.error(`❌ Failed to cache modules list:`, cacheError)
}
}
if (search && search.trim() !== '') {
filter.code = { [Op.iLike]: `%${search.trim()}%` }
}
const options = {
offset,
limit,
}
const attributes = ['id', 'code', 'status']
const modules = await modulesQueries.findAllModules(filter, attributes, options, tenantCode)

if (modules.rows == 0 || modules.count == 0) {
return responses.failureResponse({
Expand Down
6 changes: 3 additions & 3 deletions src/services/sessions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1757,11 +1757,9 @@ module.exports = class SessionsHelper {

const validationData = removeDefaultOrgEntityTypes(sessionEntityTypes, defaults.orgCode)

const processDbResponse = utils.processDbResponse(sessionDetails, validationData)

if (utils.isNumeric(id)) {
try {
const cacheCopy = { ...processDbResponse }
const cacheCopy = { ...sessionDetails }
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we storing the raw response in the cache? Has the cache hit flow been updated to handle this new logic? What’s the reason behind this change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change was needed because processDbResponse() transforms type into an object { label: "PUBLIC", value: "PUBLIC" }. When the processed result was cached, it was breaking the session update and delete API flows — the comparison sessionDetail.type != bodyData.type was always true (object vs string), triggering CANNOT_EDIT_MENTOR_AND_TYPE incorrectly.

Storing raw data fixes that comparison. The cache-hit path in the details endpoint has been verified and works correctly with the raw data.

delete cacheCopy.is_enrolled
delete cacheCopy.enrolment_type
await cacheHelper.sessions.set(tenantCode, cacheCopy.id, cacheCopy)
Expand All @@ -1770,6 +1768,8 @@ module.exports = class SessionsHelper {
// Continue without caching - don't fail the request
}
}

const processDbResponse = utils.processDbResponse(sessionDetails, validationData)
processDbResponse['resources'] = await this.getResourceAccessibleUrl(processDbResponse['resources'])

if (userId != processDbResponse.mentor_id && userId != processDbResponse.created_by) {
Expand Down