Skip to content

Commit ec088b6

Browse files
authored
feat: use member id for caching specific calls (#3690)
1 parent a0b6b2e commit ec088b6

File tree

3 files changed

+51
-21
lines changed

3 files changed

+51
-21
lines changed

backend/src/api/member/memberMerge.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { CommonMemberService } from '@crowd/common_services'
2-
import { MemberQueryCache, optionsQx } from '@crowd/data-access-layer'
2+
import { optionsQx } from '@crowd/data-access-layer'
3+
4+
import MemberService from '@/services/memberService'
35

46
import Permissions from '../../security/permissions'
57
import track from '../../segment/track'
@@ -8,14 +10,14 @@ import PermissionChecker from '../../services/user/permissionChecker'
810
export default async (req, res) => {
911
new PermissionChecker(req).validateHas(Permissions.values.memberEdit)
1012

11-
const memberService = new CommonMemberService(optionsQx(req), req.temporal, req.log)
13+
const commonMemberService = new CommonMemberService(optionsQx(req), req.temporal, req.log)
14+
const memberService = new MemberService(req)
1215

13-
const payload = await memberService.merge(req.params.memberId, req.body.memberToMerge, req)
16+
const payload = await commonMemberService.merge(req.params.memberId, req.body.memberToMerge, req)
1417

1518
// Invalidate member query cache after merge
1619
try {
17-
const cache = new MemberQueryCache(req.redis)
18-
await cache.invalidateAll()
20+
await memberService.invalidateMemberQueryCache([req.params.memberId, req.body.memberToMerge])
1921
req.log.debug('Invalidated member query cache after merge')
2022
} catch (error) {
2123
// Don't fail the merge if cache invalidation fails

backend/src/services/memberService.ts

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { CommonMemberService, getGithubInstallationToken } from '@crowd/common_s
1010
import { findMemberAffiliations } from '@crowd/data-access-layer/src/member_segment_affiliations'
1111
import {
1212
MemberField,
13+
MemberQueryCache,
1314
addMemberRole,
1415
fetchManyMemberOrgsWithOrgData,
1516
fetchMemberBotSuggestionsBySegment,
@@ -67,18 +68,6 @@ import SettingsService from './settingsService'
6768
export default class MemberService extends LoggerBase {
6869
options: IServiceOptions
6970

70-
private async invalidateMemberQueryCache(): Promise<void> {
71-
this.log.info('Member cache invalidation is temporary disabled')
72-
// try {
73-
// const cache = new MemberQueryCache(this.options.redis)
74-
// await cache.invalidateAll()
75-
// this.log.debug('Invalidated member query cache')
76-
// } catch (error) {
77-
// // Don't fail the operation if cache invalidation fails
78-
// this.log.warn('Failed to invalidate member query cache', { error })
79-
// }
80-
}
81-
8271
constructor(options: IServiceOptions) {
8372
super(options.log)
8473
this.options = options
@@ -758,7 +747,7 @@ export default class MemberService extends LoggerBase {
758747
await SequelizeRepository.commitTransaction(tx)
759748

760749
// Invalidate member query cache after unmerge
761-
await this.invalidateMemberQueryCache()
750+
await this.invalidateMemberQueryCache([memberId, secondaryMember.id])
762751

763752
return { member, secondaryMember }
764753
}),
@@ -1269,7 +1258,7 @@ export default class MemberService extends LoggerBase {
12691258
await SequelizeRepository.commitTransaction(transaction)
12701259

12711260
// Invalidate member query cache after update
1272-
await this.invalidateMemberQueryCache()
1261+
await this.invalidateMemberQueryCache([id])
12731262

12741263
const commonMemberService = new CommonMemberService(
12751264
optionsQx(this.options),
@@ -1324,7 +1313,7 @@ export default class MemberService extends LoggerBase {
13241313
await SequelizeRepository.commitTransaction(transaction)
13251314

13261315
// Invalidate member query cache after bulk delete
1327-
await this.invalidateMemberQueryCache()
1316+
await this.invalidateMemberQueryCache(ids)
13281317
} catch (error) {
13291318
await SequelizeRepository.rollbackTransaction(transaction)
13301319
throw error
@@ -1473,4 +1462,25 @@ export default class MemberService extends LoggerBase {
14731462
const qx = SequelizeRepository.getQueryExecutor(this.options)
14741463
return fetchMemberBotSuggestionsBySegment(qx, segmentId, args.limit ?? 10, args.offset ?? 0)
14751464
}
1465+
1466+
async invalidateMemberQueryCache(memberIds?: string[]): Promise<void> {
1467+
try {
1468+
const cache = new MemberQueryCache(this.options.redis)
1469+
1470+
if (memberIds && memberIds.length > 0) {
1471+
// Invalidate specific member cache entries
1472+
for (const memberId of memberIds) {
1473+
await cache.invalidateByPattern(`members_advanced:${memberId}:*`)
1474+
}
1475+
this.log.debug(`Invalidated member query cache for ${memberIds.length} specific members`)
1476+
} else {
1477+
// Invalidate all cache entries
1478+
await cache.invalidateAll()
1479+
this.log.debug('Invalidated all member query cache')
1480+
}
1481+
} catch (error) {
1482+
// Don't fail the operation if cache invalidation fails
1483+
this.log.warn('Failed to invalidate member query cache', { error })
1484+
}
1485+
}
14761486
}

services/libs/data-access-layer/src/members/queryCache.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,14 @@ export class MemberQueryCache {
5151
)
5252

5353
const hash = createHash('md5').update(JSON.stringify(cleanParams)).digest('hex')
54-
return `members_advanced_${hash}`
54+
55+
const filterId = (params.filter?.id as Record<string, unknown>)?.eq
56+
57+
if (filterId && typeof filterId === 'string') {
58+
return `members_advanced:${filterId}:${hash}`
59+
}
60+
61+
return `members_advanced:${hash}`
5562
}
5663

5764
async get(cacheKey: string): Promise<PageData<IDbMemberData> | null> {
@@ -97,4 +104,15 @@ export class MemberQueryCache {
97104
log.warn('Error invalidating member query cache', { error })
98105
}
99106
}
107+
108+
async invalidateByPattern(pattern: string): Promise<void> {
109+
try {
110+
const keysDeleted = await this.cache.deleteByKeyPattern(pattern)
111+
log.info(
112+
`Invalidated member query cache by pattern: ${keysDeleted} entries deleted for pattern ${pattern}`,
113+
)
114+
} catch (error) {
115+
log.warn('Error invalidating member query cache by pattern', { error, pattern })
116+
}
117+
}
100118
}

0 commit comments

Comments
 (0)