@@ -20,10 +20,9 @@ import (
2020
2121const (
2222 // KV key prefixes for secondary indexes written to v1-mappings.
23- kvKeyUsernamePrefix = "v1-user.username."
24- kvKeyEmailPrefix = "v1-user.email."
25- kvKeyAlternateEmailsPrefix = "v1-merged-user.alternate-emails."
26- kvKeyPrimaryEmailByUserSfid = "v1-user.primary-email."
23+ kvKeyUsernamePrefix = "v1-user.username."
24+ kvKeyEmailPrefix = "v1-user.email."
25+ kvKeyAlternateEmailsPrefix = "v1-merged-user.alternate-emails."
2726
2827 // v1-objects KV key prefixes as replicated by Meltano.
2928 v1MergedUserKVPrefix = "salesforce-merged_user."
5756
5857// handleMergedUserDelete dependencies, split out so tests can inject fakes
5958// without needing a live NATS connection.
60- var (
61- getPrimaryEmailForUserFn = getCachedPrimaryEmailForUser
62- publishUserDeletedEventFn = publishUserDeletedEvent
63- )
59+ var publishUserDeletedEventFn = publishUserDeletedEvent
6460
6561// toKVKey normalizes a user-provided string and encodes it as a URL-safe base64
6662// key segment safe for NATS KV. Order: TrimSpace → ToLower → NFC → RawURLEncoding.
@@ -156,18 +152,7 @@ func handleMergedUserDelete(ctx context.Context, key, userSfid string, v1Data ma
156152 // without its alternate emails being deleted first, those entries will be orphaned.
157153
158154 if username != "" {
159- email , emailErr := getPrimaryEmailForUserFn (ctx , userSfid )
160- if emailErr != nil {
161- logger .With (errKey , emailErr , "key" , key , "user_sfid" , userSfid ).
162- WarnContext (ctx , "failed to look up primary email for deleted user; committee username scrub skipped" )
163- } else {
164- publishUserDeletedEventFn (ctx , key , username , email )
165- // Best-effort cleanup of the cached primary-email key.
166- if err := deleteIndexKeyFn (ctx , kvKeyPrimaryEmailByUserSfid + userSfid ); err != nil {
167- logger .With (errKey , err , "key" , key , "user_sfid" , userSfid ).
168- WarnContext (ctx , "failed to delete cached primary email after user-deleted event" )
169- }
170- }
155+ publishUserDeletedEventFn (ctx , key , username )
171156 }
172157
173158 return false
@@ -178,15 +163,14 @@ func handleMergedUserDelete(ctx context.Context, key, userSfid string, v1Data ma
178163// the username from committee members and settings writers/auditors.
179164type userDeletedEvent struct {
180165 Username string `json:"username"`
181- Email string `json:"email"`
182166}
183167
184168const v1SyncHelperUserDeletedSubject = "lfx.v1-sync-helper.user.deleted"
185169
186170// publishUserDeletedEvent publishes a user-deleted NATS event. Best-effort: publish
187171// errors are logged and do not affect the delete handler's return value.
188- func publishUserDeletedEvent (ctx context.Context , key , username , email string ) {
189- payload , err := json .Marshal (userDeletedEvent {Username : username , Email : email })
172+ func publishUserDeletedEvent (ctx context.Context , key , username string ) {
173+ payload , err := json .Marshal (userDeletedEvent {Username : username })
190174 if err != nil {
191175 logger .With (errKey , err , "key" , key ).
192176 ErrorContext (ctx , "failed to marshal user-deleted event; committee username scrub skipped" )
@@ -201,21 +185,6 @@ func publishUserDeletedEvent(ctx context.Context, key, username, email string) {
201185 InfoContext (ctx , "published user-deleted event for committee username scrub" )
202186}
203187
204- // getCachedPrimaryEmailForUser returns the primary email for a user. It first
205- // checks the v1-mappings cache written by handleAlternateEmailUpdate (which
206- // survives alternate-email row deletion), then falls back to the live KV
207- // lookup. The cache avoids an ordering problem where alternate-email rows are
208- // cleaned up before the merged-user deletion event is processed.
209- func getCachedPrimaryEmailForUser (ctx context.Context , userSfid string ) (string , error ) {
210- cacheKey := kvKeyPrimaryEmailByUserSfid + userSfid
211- if entry , err := mappingsKV .Get (ctx , cacheKey ); err == nil {
212- if email := strings .TrimSpace (string (entry .Value ())); email != "" {
213- return email , nil
214- }
215- }
216- return getPrimaryEmailForUser (ctx , userSfid )
217- }
218-
219188// syncMergedUserProfile calls syncProfileToAuth0Fn synchronously and returns
220189// true if the error is retryable so the caller can NACK the JetStream message.
221190func syncMergedUserProfile (ctx context.Context , key , auth0UserID string , v1Data map [string ]any ) bool {
@@ -292,18 +261,8 @@ func handleAlternateEmailUpdate(ctx context.Context, key string, v1Data map[stri
292261 }
293262 }
294263
295- // Primary emails are not linked as Auth0 identities (they are the Auth0
296- // user's own email). Cache the address in mappings so handleMergedUserDelete
297- // can supply it to the committee scrub even after the alternate-email rows
298- // have been cleaned up ahead of the merged-user row.
264+ // Primary emails are not linked as Auth0 identities (they are the Auth0 user's own email).
299265 if isPrimary , _ := v1Data ["primary_email__c" ].(bool ); isPrimary {
300- if emailAddr != "" {
301- cacheKey := kvKeyPrimaryEmailByUserSfid + leadorcontactid
302- if _ , err := mappingsKV .Put (ctx , cacheKey , []byte (emailAddr )); err != nil {
303- logger .With (errKey , err , "key" , key , "user_sfid" , leadorcontactid ).
304- WarnContext (ctx , "failed to cache primary email for user deletion scrub" )
305- }
306- }
307266 return false
308267 }
309268
0 commit comments