Skip to content

Commit 0daa93a

Browse files
committed
fix: cache regression
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
1 parent f07fc1b commit 0daa93a

3 files changed

Lines changed: 21 additions & 10 deletions

File tree

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,23 +195,23 @@ export async function queryMembersAdvanced(
195195
// Initialize cache
196196
const cache = new MemberQueryCache(redis)
197197

198-
// Build cache key
198+
// Build cache key — countOnly is excluded so count and full-result caches share the same key.
199+
// Normalize empty search to null so "" and null produce the same key (buildSearchCTE treats them identically).
199200
const cacheKey = cache.buildCacheKey({
200-
countOnly,
201201
fields,
202202
filter,
203203
include,
204204
includeAllAttributes,
205205
limit,
206206
offset,
207207
orderBy,
208-
search,
208+
search: search || null,
209209
segmentId,
210210
})
211211

212212
// Try to get from cache first
213213
const cachedResult = countOnly ? null : await cache.get(cacheKey)
214-
const cachedCount = countOnly ? null : await cache.getCount(cacheKey)
214+
const cachedCount = countOnly ? await cache.getCount(cacheKey) : null
215215

216216
if (cachedResult) {
217217
refreshCacheInBackground(bgQx, redis, cacheKey, {
@@ -343,7 +343,9 @@ export async function executeQuery(
343343
withAggregates,
344344
searchConfig,
345345
filterString,
346-
includeMemberOrgs: include.memberOrganizations,
346+
// Count never needs org data in SELECT — filterHasMo inside buildCountQuery already
347+
// handles the case where the filter itself references mo.* columns.
348+
includeMemberOrgs: false,
347349
})
348350

349351
if (countOnly) {
@@ -537,7 +539,10 @@ export async function executeQuery(
537539

538540
const result = { rows, count, limit, offset }
539541

540-
await cache.set(cacheKey, result, 21600) // 6 hours TTL
542+
await Promise.all([
543+
cache.set(cacheKey, result, 21600), // 6 hours TTL
544+
cache.setCount(cacheKey, count, 21600), // also warm count cache so countOnly=true hits next time
545+
])
541546

542547
return result
543548
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,9 +464,13 @@ export const buildCountQuery = ({
464464
searchConfig.join,
465465
].filter(Boolean)
466466

467+
// When withAggregates is true the join is on memberSegmentsAgg_pkey (unique on memberId+segmentId),
468+
// so there are no duplicate m.id values — COUNT(*) is equivalent to COUNT(DISTINCT m.id) but cheaper.
469+
const countExpr = withAggregates ? 'COUNT(*)' : 'COUNT(DISTINCT m.id)'
470+
467471
return `
468472
${ctes.length > 0 ? `WITH ${ctes.join(',\n')}` : ''}
469-
SELECT COUNT(DISTINCT m.id) AS count
473+
SELECT ${countExpr} AS count
470474
FROM members m
471475
${joins.join('\n')}
472476
WHERE (${filterString})

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ export class MemberQueryCache {
2626
}
2727

2828
buildCacheKey(params: {
29-
countOnly?: boolean
3029
fields?: string[]
3130
filter?: Record<string, unknown>
3231
include?: IncludeOptions
@@ -39,7 +38,6 @@ export class MemberQueryCache {
3938
}): string {
4039
const cleanParams = Object.fromEntries(
4140
Object.entries({
42-
countOnly: params.countOnly,
4341
fields: params.fields?.sort(),
4442
filter: params.filter,
4543
include: params.include,
@@ -90,7 +88,11 @@ export class MemberQueryCache {
9088
}
9189

9290
async setCount(cacheKey: string, count: number, ttlSeconds: number): Promise<void> {
93-
await this.countCache.set(cacheKey, count.toString(), ttlSeconds)
91+
try {
92+
await this.countCache.set(cacheKey, count.toString(), ttlSeconds)
93+
} catch (error) {
94+
log.warn('Error saving count to cache', { error })
95+
}
9496
}
9597

9698
async invalidateAll(): Promise<void> {

0 commit comments

Comments
 (0)