Skip to content

Commit d134449

Browse files
committed
hubspot integration sync errors fix & better error handling
1 parent 0de71df commit d134449

File tree

7 files changed

+141
-65
lines changed

7 files changed

+141
-65
lines changed

services/apps/data_sink_worker/src/service/member.service.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,8 @@ export default class MemberService extends LoggerBase {
299299
(!member.identities || member.identities.length === 0)
300300
) {
301301
const errorMessage = `Member can't be enriched. It is missing both emails and identities fields.`
302-
this.log.error(errorMessage)
303-
throw new Error(errorMessage)
302+
this.log.warn(errorMessage)
303+
return
304304
}
305305

306306
await this.store.transactionally(async (txStore) => {
@@ -317,7 +317,10 @@ export default class MemberService extends LoggerBase {
317317
const segmentId = dbIntegration.segmentId
318318

319319
// first try finding the member using the identity
320-
const identity = singleOrDefault(member.identities, (i) => i.platform === platform)
320+
const identity = singleOrDefault(
321+
member.identities,
322+
(i) => i.platform === platform && i.sourceId !== null,
323+
)
321324
let dbMember = await txRepo.findMember(tenantId, segmentId, platform, identity.username)
322325

323326
if (!dbMember && member.emails && member.emails.length > 0) {

services/apps/data_sink_worker/src/service/organization.service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ export class OrganizationService extends LoggerBase {
341341
const txRepo = new OrganizationRepository(txStore, this.log)
342342
const txIntegrationRepo = new IntegrationRepository(txStore, this.log)
343343

344+
const txService = new OrganizationService(txStore, this.log)
345+
344346
const dbIntegration = await txIntegrationRepo.findById(integrationId)
345347
const segmentId = dbIntegration.segmentId
346348

@@ -381,7 +383,7 @@ export class OrganizationService extends LoggerBase {
381383
organization.identities.unshift(...existingIdentities)
382384
}
383385

384-
await this.findOrCreate(tenantId, segmentId, integrationId, organization)
386+
await txService.findOrCreate(tenantId, segmentId, integrationId, organization)
385387
} else {
386388
this.log.debug(
387389
'No organization found for enriching. This organization enrich process had no affect.',
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const integrationNotFound = (integrationId: string): string =>
2+
`Integration ${integrationId} not found!`
3+
4+
export const automationNotFound = (automationId: string): string =>
5+
`Automation ${automationId} not found!`

services/apps/integration_sync_worker/src/service/member.sync.service.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
import { IDbIntegration } from '@/repo/integration.data'
1818
import { AutomationRepository } from '@/repo/automation.repo'
1919
import { AutomationExecutionRepository } from '@/repo/automationExecution.repo'
20+
import { automationNotFound, integrationNotFound } from '@/errors'
2021

2122
export class MemberSyncService extends LoggerBase {
2223
private readonly memberRepo: MemberRepository
@@ -45,14 +46,33 @@ export class MemberSyncService extends LoggerBase {
4546
): Promise<void> {
4647
const integration = await this.integrationRepo.findById(integrationId)
4748

49+
if (!integration) {
50+
const message = integrationNotFound(integrationId)
51+
this.log.warn(message)
52+
return
53+
}
54+
4855
const member = await this.memberRepo.findMember(memberId)
4956

57+
if (!member) {
58+
this.log.warn(`Member ${memberId} is not found for syncing remote!`)
59+
return
60+
}
61+
5062
const syncRemote = await this.memberRepo.findSyncRemoteById(syncRemoteId)
5163

5264
const membersToCreate = []
5365
const membersToUpdate = []
5466

5567
if (syncRemote.sourceId) {
68+
member.attributes = {
69+
...member.attributes,
70+
sourceId: {
71+
...(member.attributes.sourceId || {}),
72+
[integration.platform]: syncRemote.sourceId,
73+
},
74+
}
75+
5676
membersToUpdate.push(member)
5777
} else {
5878
membersToCreate.push(member)
@@ -96,6 +116,12 @@ export class MemberSyncService extends LoggerBase {
96116
): Promise<void> {
97117
const integration: IDbIntegration = await this.integrationRepo.findById(integrationId)
98118

119+
if (!integration) {
120+
const message = integrationNotFound(integrationId)
121+
this.log.warn(message)
122+
return
123+
}
124+
99125
const platforms = await this.memberRepo.getExistingPlatforms(tenantId)
100126

101127
const attributes = await this.memberRepo.getTenantMemberAttributes(tenantId)
@@ -173,6 +199,7 @@ export class MemberSyncService extends LoggerBase {
173199
translatedMembers[0].attributes = {
174200
...translatedMembers[0].attributes,
175201
sourceId: {
202+
...(translatedMembers[0].attributes.sourceId || {}),
176203
[integration.platform]: memberToSync.sourceId,
177204
},
178205
}
@@ -228,8 +255,20 @@ export class MemberSyncService extends LoggerBase {
228255
batchSize = 50,
229256
) {
230257
const integration: IDbIntegration = await this.integrationRepo.findById(integrationId)
258+
259+
if (!integration) {
260+
const message = integrationNotFound(integrationId)
261+
this.log.warn(message)
262+
return
263+
}
231264
const automation = await this.automationRepo.findById(automationId)
232265

266+
if (!automation) {
267+
const message = automationNotFound(automationId)
268+
this.log.warn(message)
269+
return
270+
}
271+
233272
const platforms = await this.memberRepo.getExistingPlatforms(tenantId)
234273

235274
const attributes = await this.memberRepo.getTenantMemberAttributes(tenantId)
@@ -362,6 +401,7 @@ export class MemberSyncService extends LoggerBase {
362401
memberToSync.attributes = {
363402
...memberToSync.attributes,
364403
sourceId: {
404+
...(memberToSync.attributes.sourceId || {}),
365405
[integration.platform]: syncRemote.sourceId,
366406
},
367407
}
@@ -453,8 +493,20 @@ export class MemberSyncService extends LoggerBase {
453493
) {
454494
const integration: IDbIntegration = await this.integrationRepo.findById(integrationId)
455495

496+
if (!integration) {
497+
const message = integrationNotFound(integrationId)
498+
this.log.warn(message)
499+
return
500+
}
501+
456502
const automation = await this.automationRepo.findById(automationId)
457503

504+
if (!automation) {
505+
const message = automationNotFound(automationId)
506+
this.log.warn(message)
507+
return
508+
}
509+
458510
let organizationMembers
459511
let offset
460512

@@ -495,6 +547,7 @@ export class MemberSyncService extends LoggerBase {
495547
member.attributes = {
496548
...member.attributes,
497549
sourceId: {
550+
...(member.attributes.sourceId || {}),
498551
[integration.platform]: syncRemote.sourceId,
499552
},
500553
}

services/apps/integration_sync_worker/src/service/organization.sync.service.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ export class OrganizationSyncService extends LoggerBase {
4646
const organizationsToUpdate = []
4747

4848
if (syncRemote.sourceId) {
49+
organization.attributes = {
50+
...organization.attributes,
51+
sourceId: {
52+
...(organization.attributes.sourceId || {}),
53+
[integration.platform]: syncRemote.sourceId,
54+
},
55+
}
4956
organizationsToUpdate.push(organization)
5057
} else {
5158
oranizationsToCreate.push(organization)
@@ -121,6 +128,7 @@ export class OrganizationSyncService extends LoggerBase {
121128
organization.attributes = {
122129
...organization.attributes,
123130
sourceId: {
131+
...(organization.attributes.sourceId || {}),
124132
[integration.platform]: organizationToSync.sourceId,
125133
},
126134
}
@@ -235,6 +243,7 @@ export class OrganizationSyncService extends LoggerBase {
235243
organization.attributes = {
236244
...organization.attributes,
237245
sourceId: {
246+
...(organization.attributes.sourceId || {}),
238247
[integration.platform]: syncRemote.sourceId,
239248
},
240249
}

services/libs/integrations/src/integrations/premium/hubspot/api/batchUpdateMembers.ts

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -26,49 +26,51 @@ export const batchUpdateMembers = async (
2626
const hubspotMembers = []
2727

2828
for (const member of members) {
29-
const hubspotSourceId = member.attributes?.sourceId?.hubspot
30-
31-
if (!hubspotSourceId) {
32-
ctx.log.warn(
33-
`Member ${member.id} can't be updated in hubspot! Member doesn't have a hubspot sourceId in attributes.`,
34-
)
35-
} else {
36-
const hsMember = {
37-
id: hubspotSourceId,
38-
properties: {},
39-
} as any
40-
41-
const fields = memberMapper.getAllCrowdFields()
42-
43-
for (const crowdField of fields) {
44-
const hubspotField = memberMapper.getHubspotFieldName(crowdField)
45-
if (crowdField.startsWith('attributes')) {
46-
const attributeName = crowdField.split('.')[1] || null
47-
48-
if (
49-
attributeName &&
50-
hubspotField &&
51-
member.attributes[attributeName]?.default !== undefined
52-
) {
53-
hsMember.properties[hubspotField] = member.attributes[attributeName].default
29+
if (member) {
30+
const hubspotSourceId = member.attributes?.sourceId?.hubspot
31+
32+
if (!hubspotSourceId) {
33+
ctx.log.warn(
34+
`Member ${member.id} can't be updated in hubspot! Member doesn't have a hubspot sourceId in attributes.`,
35+
)
36+
} else {
37+
const hsMember = {
38+
id: hubspotSourceId,
39+
properties: {},
40+
} as any
41+
42+
const fields = memberMapper.getAllCrowdFields()
43+
44+
for (const crowdField of fields) {
45+
const hubspotField = memberMapper.getHubspotFieldName(crowdField)
46+
if (crowdField.startsWith('attributes')) {
47+
const attributeName = crowdField.split('.')[1] || null
48+
49+
if (
50+
attributeName &&
51+
hubspotField &&
52+
member.attributes[attributeName]?.default !== undefined
53+
) {
54+
hsMember.properties[hubspotField] = member.attributes[attributeName].default
55+
}
56+
} else if (crowdField.startsWith('identities')) {
57+
const identityPlatform = crowdField.split('.')[1] || null
58+
59+
const identityFound = member.identities.find((i) => i.platform === identityPlatform)
60+
61+
if (identityPlatform && hubspotField && identityFound) {
62+
hsMember.properties[hubspotField] = identityFound.username
63+
}
64+
} else if (crowdField === 'organizationName') {
65+
// send latest org of member as value
66+
} else if (hubspotField && member[crowdField] !== undefined) {
67+
hsMember.properties[hubspotField] = memberMapper.getHubspotValue(member, crowdField)
5468
}
55-
} else if (crowdField.startsWith('identities')) {
56-
const identityPlatform = crowdField.split('.')[1] || null
57-
58-
const identityFound = member.identities.find((i) => i.platform === identityPlatform)
59-
60-
if (identityPlatform && hubspotField && identityFound) {
61-
hsMember.properties[hubspotField] = identityFound.username
62-
}
63-
} else if (crowdField === 'organizationName') {
64-
// send latest org of member as value
65-
} else if (hubspotField && member[crowdField] !== undefined) {
66-
hsMember.properties[hubspotField] = memberMapper.getHubspotValue(member, crowdField)
6769
}
68-
}
6970

70-
if (Object.keys(hsMember.properties).length > 0) {
71-
hubspotMembers.push(hsMember)
71+
if (Object.keys(hsMember.properties).length > 0) {
72+
hubspotMembers.push(hsMember)
73+
}
7274
}
7375
}
7476
}

services/libs/integrations/src/integrations/premium/hubspot/api/batchUpdateOrganizations.ts

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,33 +26,35 @@ export const batchUpdateOrganizations = async (
2626
const hubspotCompanies = []
2727

2828
for (const organization of organizations) {
29-
const hubspotSourceId = organization.attributes?.sourceId?.hubspot
29+
if (organization) {
30+
const hubspotSourceId = organization.attributes?.sourceId?.hubspot
3031

31-
if (!hubspotSourceId) {
32-
ctx.log.warn(
33-
`Organization ${organization.id} can't be updated in hubspot! Organization doesn't have a hubspot sourceId.`,
34-
)
35-
} else {
36-
const hubspotCompany = {
37-
id: hubspotSourceId,
38-
properties: {},
39-
} as any
32+
if (!hubspotSourceId) {
33+
ctx.log.warn(
34+
`Organization ${organization.id} can't be updated in hubspot! Organization doesn't have a hubspot sourceId.`,
35+
)
36+
} else {
37+
const hubspotCompany = {
38+
id: hubspotSourceId,
39+
properties: {},
40+
} as any
4041

41-
const fields = organizationMapper.getAllCrowdFields()
42+
const fields = organizationMapper.getAllCrowdFields()
4243

43-
for (const crowdField of fields) {
44-
const hubspotField = organizationMapper.getHubspotFieldName(crowdField)
44+
for (const crowdField of fields) {
45+
const hubspotField = organizationMapper.getHubspotFieldName(crowdField)
4546

46-
if (hubspotField && organization[crowdField] !== undefined) {
47-
hubspotCompany.properties[hubspotField] = organizationMapper.getHubspotValue(
48-
organization,
49-
crowdField,
50-
)
47+
if (hubspotField && organization[crowdField] !== undefined) {
48+
hubspotCompany.properties[hubspotField] = organizationMapper.getHubspotValue(
49+
organization,
50+
crowdField,
51+
)
52+
}
5153
}
52-
}
5354

54-
if (Object.keys(hubspotCompany.properties).length > 0) {
55-
hubspotCompanies.push(hubspotCompany)
55+
if (Object.keys(hubspotCompany.properties).length > 0) {
56+
hubspotCompanies.push(hubspotCompany)
57+
}
5658
}
5759
}
5860
}

0 commit comments

Comments
 (0)