@@ -7,18 +7,20 @@ import {
77 signalMemberUpdate ,
88} from '@crowd/common_services'
99import {
10+ MemberField ,
1011 QueryExecutor ,
1112 changeMemberOrganizationAffiliationOverrides ,
1213 createMemberOrganization ,
1314 deleteUndatedMemberOrganizations ,
1415 fetchManyOrganizationAffiliationPolicies ,
1516 fetchMemberOrganizationsBySource ,
17+ findMemberById ,
1618 updateMemberOrganization ,
1719} from '@crowd/data-access-layer'
1820import { WRITE_DB_CONFIG , getDbConnection } from '@crowd/data-access-layer/src/database'
1921import { deleteMemberSegmentAffiliations } from '@crowd/data-access-layer/src/member_segment_affiliations'
2022import { pgpQx } from '@crowd/data-access-layer/src/queryExecutor'
21- import { REDIS_CONFIG , RedisCache , getRedisClient } from '@crowd/redis'
23+ import { REDIS_CONFIG , RedisCache , RedisClient , getRedisClient } from '@crowd/redis'
2224import { TEMPORAL_CONFIG , getTemporalClient } from '@crowd/temporal'
2325import { MemberOrgDate , MemberOrgStintChange , OrganizationSource } from '@crowd/types'
2426
@@ -51,7 +53,18 @@ const job: IJobDefinition = {
5153 const rawMembers = await redis . sMembers ( datesKey )
5254
5355 if ( ! rawMembers ?. length ) {
54- await redis . sRem ( MEMBER_ORG_STINT_CHANGES_QUEUE , memberId )
56+ await purgeMember ( redis , memberId )
57+ continue
58+ }
59+
60+ // Skip if the member was hard-deleted (e.g., due to merge) after being queued.
61+ // This prevents memberOrganizations foreign key (FK) violations from stale Redis entries.
62+ const member = await findMemberById ( qx , memberId , [ MemberField . ID ] )
63+
64+ if ( ! member ) {
65+ ctx . log . warn ( { memberId } , 'Member no longer exists, removing from queue.' )
66+
67+ await purgeMember ( redis , memberId )
5568 continue
5669 }
5770
@@ -116,6 +129,15 @@ function parseSetMembers(members: string[]): MemberOrgDate[] {
116129 return results
117130}
118131
132+ /**
133+ * Purges a member from the queue and their associated Redis entries.
134+ */
135+ async function purgeMember ( redis : RedisClient , memberId : string ) : Promise < void > {
136+ const datesKey = `${ MEMBER_ORG_STINT_CHANGES_DATES_PREFIX } :${ memberId } `
137+
138+ await redis . multi ( ) . del ( datesKey ) . sRem ( MEMBER_ORG_STINT_CHANGES_QUEUE , memberId ) . exec ( )
139+ }
140+
119141/**
120142 * Applies the stint changes to the database.
121143 */
0 commit comments