@adtrackify/at-service-common 4.0.12 → 4.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/cjs/__tests__/identity-cache/helpers.spec.js +37 -38
  2. package/dist/cjs/__tests__/identity-cache/helpers.spec.js.map +1 -1
  3. package/dist/cjs/__tests__/identity-cache/identity-cache-tier-routing.spec.js +83 -344
  4. package/dist/cjs/__tests__/identity-cache/identity-cache-tier-routing.spec.js.map +1 -1
  5. package/dist/cjs/__tests__/identity-cache/identity-client.spec.js +360 -0
  6. package/dist/cjs/__tests__/identity-cache/identity-client.spec.js.map +1 -0
  7. package/dist/cjs/__tests__/identity-cache/identity-gateway-service.spec.js +335 -1261
  8. package/dist/cjs/__tests__/identity-cache/identity-gateway-service.spec.js.map +1 -1
  9. package/dist/cjs/clients/internal-api/identity-client.d.ts +12 -2
  10. package/dist/cjs/clients/internal-api/identity-client.js +59 -13
  11. package/dist/cjs/clients/internal-api/identity-client.js.map +1 -1
  12. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.d.ts +1 -7
  13. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js +0 -305
  14. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js.map +1 -1
  15. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.d.ts +10 -9
  16. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.js +116 -321
  17. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.js.map +1 -1
  18. package/dist/cjs/services/db/identity-cache-dynamodb-service/index.d.ts +0 -1
  19. package/dist/cjs/services/db/identity-cache-dynamodb-service/index.js +0 -1
  20. package/dist/cjs/services/db/identity-cache-dynamodb-service/index.js.map +1 -1
  21. package/dist/cjs/services/db/identity-cache-dynamodb-service/types.d.ts +9 -157
  22. package/dist/cjs/services/db/identity-cache-dynamodb-service/types.js +1 -15
  23. package/dist/cjs/services/db/identity-cache-dynamodb-service/types.js.map +1 -1
  24. package/dist/esm/__tests__/identity-cache/helpers.spec.js +26 -27
  25. package/dist/esm/__tests__/identity-cache/helpers.spec.js.map +1 -1
  26. package/dist/esm/__tests__/identity-cache/identity-cache-tier-routing.spec.js +83 -344
  27. package/dist/esm/__tests__/identity-cache/identity-cache-tier-routing.spec.js.map +1 -1
  28. package/dist/esm/__tests__/identity-cache/identity-client.spec.js +358 -0
  29. package/dist/esm/__tests__/identity-cache/identity-client.spec.js.map +1 -0
  30. package/dist/esm/__tests__/identity-cache/identity-gateway-service.spec.js +335 -1261
  31. package/dist/esm/__tests__/identity-cache/identity-gateway-service.spec.js.map +1 -1
  32. package/dist/esm/clients/internal-api/identity-client.d.ts +12 -2
  33. package/dist/esm/clients/internal-api/identity-client.js +60 -14
  34. package/dist/esm/clients/internal-api/identity-client.js.map +1 -1
  35. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.d.ts +1 -7
  36. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js +1 -303
  37. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js.map +1 -1
  38. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.d.ts +10 -9
  39. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.js +119 -321
  40. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.js.map +1 -1
  41. package/dist/esm/services/db/identity-cache-dynamodb-service/index.d.ts +0 -1
  42. package/dist/esm/services/db/identity-cache-dynamodb-service/index.js +0 -1
  43. package/dist/esm/services/db/identity-cache-dynamodb-service/index.js.map +1 -1
  44. package/dist/esm/services/db/identity-cache-dynamodb-service/types.d.ts +9 -157
  45. package/dist/esm/services/db/identity-cache-dynamodb-service/types.js +0 -14
  46. package/dist/esm/services/db/identity-cache-dynamodb-service/types.js.map +1 -1
  47. package/package.json +2 -2
  48. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-db-service-v2-comparison.spec.js +0 -646
  49. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-db-service-v2-comparison.spec.js.map +0 -1
  50. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js +0 -325
  51. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js.map +0 -1
  52. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service.spec.d.ts +0 -1
  53. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js +0 -1286
  54. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js.map +0 -1
  55. package/dist/cjs/services/db/identity-cache-dynamodb-service/helpers.d.ts +0 -26
  56. package/dist/cjs/services/db/identity-cache-dynamodb-service/helpers.js +0 -252
  57. package/dist/cjs/services/db/identity-cache-dynamodb-service/helpers.js.map +0 -1
  58. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service-v2-comparison.spec.d.ts +0 -1
  59. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service-v2-comparison.spec.js +0 -644
  60. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service-v2-comparison.spec.js.map +0 -1
  61. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.d.ts +0 -1
  62. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js +0 -323
  63. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js.map +0 -1
  64. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service.spec.d.ts +0 -1
  65. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js +0 -1284
  66. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js.map +0 -1
  67. package/dist/esm/services/db/identity-cache-dynamodb-service/helpers.d.ts +0 -26
  68. package/dist/esm/services/db/identity-cache-dynamodb-service/helpers.js +0 -235
  69. package/dist/esm/services/db/identity-cache-dynamodb-service/helpers.js.map +0 -1
  70. /package/dist/cjs/__tests__/identity-cache/{identity-cache-dynamodb-db-service-v2-comparison.spec.d.ts → identity-client.spec.d.ts} +0 -0
  71. /package/dist/{cjs/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.d.ts → esm/__tests__/identity-cache/identity-client.spec.d.ts} +0 -0
@@ -1,7 +1,5 @@
1
1
  import { ADDRESS_INFO_SOURCE } from '@adtrackify/at-tracking-event-types';
2
- import { IDENTITY_CACHE_STALENESS_TIER } from '@adtrackify/at-shared-utils';
3
- import { CACHE_WRITE_REASON } from '../../services/db/identity-cache-dynamodb-service';
4
- const mockInvokeFunction = jest.fn();
2
+ const mockLambdaInvoke = jest.fn();
5
3
  const mockBuildAndSendMessage = jest.fn();
6
4
  const mockSQSClientConstructor = jest.fn();
7
5
  jest.mock('../../clients/index.js', () => ({
@@ -15,7 +13,7 @@ jest.mock('../../clients/index.js', () => ({
15
13
  batchWrite: jest.fn(),
16
14
  },
17
15
  LambdaInvokeClient: jest.fn().mockImplementation(() => ({
18
- invokeFunction: mockInvokeFunction,
16
+ invokeFunction: mockLambdaInvoke,
19
17
  })),
20
18
  SQSClient: jest.fn().mockImplementation((_region, _accountId, _queueName) => {
21
19
  mockSQSClientConstructor(_region, _accountId, _queueName);
@@ -33,15 +31,19 @@ jest.mock('../../helpers/index.js', () => ({
33
31
  error: jest.fn(),
34
32
  },
35
33
  }));
34
+ const mockGetIdentity = jest.fn();
35
+ jest.mock('../../clients/internal-api/identity-client.js', () => ({
36
+ IdentityClient: jest.fn().mockImplementation(() => ({
37
+ getIdentity: mockGetIdentity,
38
+ })),
39
+ }));
36
40
  import { IdentityGatewayService, } from '../../services/db/identity-cache-dynamodb-service/identity-gateway-service.js';
37
41
  import { IDENTITY_CACHE_WITH_CACHING_OUTCOME, } from '../../services/db/identity-cache-dynamodb-service/types.js';
38
- import { IdentityCacheDynamoDbDbService } from '../../services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js';
39
42
  import { DynamoDbClient, SQSClient } from '../../clients/index.js';
40
43
  const mockedDynamoDbClient = DynamoDbClient;
41
44
  const _mockedSQSClient = SQSClient;
42
45
  describe('Identity Cache Three-Tier Routing', () => {
43
46
  const pixelId = 'pixel123';
44
- const lambdaArn = 'arn:aws:lambda:us-east-1:123456789:function:identity-private';
45
47
  beforeEach(() => {
46
48
  jest.clearAllMocks();
47
49
  mockedDynamoDbClient.safeGet.mockReset();
@@ -51,13 +53,14 @@ describe('Identity Cache Three-Tier Routing', () => {
51
53
  mockedDynamoDbClient.safeBatchWrite.mockReset();
52
54
  mockedDynamoDbClient.safeQueryByGSI.mockReset();
53
55
  mockedDynamoDbClient.batchWrite.mockReset();
54
- mockInvokeFunction.mockReset();
56
+ mockGetIdentity.mockReset();
55
57
  mockBuildAndSendMessage.mockReset();
56
58
  mockSQSClientConstructor.mockReset();
57
59
  _mockedSQSClient.mockClear();
58
- IdentityGatewayService.lambdaInvokeClient = undefined;
60
+ IdentityGatewayService.identityClient = undefined;
59
61
  IdentityGatewayService.sqsClient = undefined;
60
62
  IdentityGatewayService.sqsQueueUrl = undefined;
63
+ IdentityGatewayService.configure({ identifyPrivateLambdaArn: 'arn:aws:lambda:us-east-1:123456789:function:identity-private' });
61
64
  });
62
65
  describe('TIER: VOLATILE_ONLY — Returns merged identity, NO Neptune, NO cache write', () => {
63
66
  it('should return merged identity without Neptune call when only ipAddress is stale', async () => {
@@ -82,10 +85,10 @@ describe('Identity Cache Three-Tier Routing', () => {
82
85
  updatedAt: new Date().toISOString(),
83
86
  };
84
87
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
85
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
88
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
86
89
  expect(result.identity).toBeDefined();
87
90
  expect(result.identity?.identityId).toBe('identity456');
88
- expect(mockInvokeFunction).not.toHaveBeenCalled();
91
+ expect(mockGetIdentity).not.toHaveBeenCalled();
89
92
  expect(mockedDynamoDbClient.safeBatchWrite).not.toHaveBeenCalled();
90
93
  });
91
94
  it('should return merged identity without Neptune call when only userAgent is stale', async () => {
@@ -110,9 +113,9 @@ describe('Identity Cache Three-Tier Routing', () => {
110
113
  updatedAt: new Date().toISOString(),
111
114
  };
112
115
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
113
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
116
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
114
117
  expect(result.identity).toBeDefined();
115
- expect(mockInvokeFunction).not.toHaveBeenCalled();
118
+ expect(mockGetIdentity).not.toHaveBeenCalled();
116
119
  expect(mockedDynamoDbClient.safeBatchWrite).not.toHaveBeenCalled();
117
120
  });
118
121
  it('should return merged identity without Neptune call when only IP-sourced addresses are stale', async () => {
@@ -137,117 +140,12 @@ describe('Identity Cache Three-Tier Routing', () => {
137
140
  updatedAt: new Date().toISOString(),
138
141
  };
139
142
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
140
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
143
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
141
144
  expect(result.identity).toBeDefined();
142
- expect(mockInvokeFunction).not.toHaveBeenCalled();
145
+ expect(mockGetIdentity).not.toHaveBeenCalled();
143
146
  expect(mockedDynamoDbClient.safeBatchWrite).not.toHaveBeenCalled();
144
147
  });
145
148
  });
146
- describe('TIER: ADDRESS_UPDATE — Enqueues async update, NO Neptune call, NO sync cache write', () => {
147
- it('should enqueue async update but skip Neptune when new non-IP address is added', async () => {
148
- IdentityGatewayService.configure({
149
- awsRegion: 'us-east-1',
150
- awsAccountId: '123456789',
151
- asyncUpdateQueueName: 'test-queue',
152
- });
153
- mockBuildAndSendMessage.mockResolvedValueOnce({ MessageId: 'test-msg-id' });
154
- const incomingIdentity = {
155
- identityId: 'identity456',
156
- traits: {
157
- emails: ['test@email.com'],
158
- addresses: [{ city: 'Boston', firstName: 'John', s: ADDRESS_INFO_SOURCE.INPUT }],
159
- },
160
- };
161
- const cachedResponse = {
162
- pk: `identity#${pixelId}#identity456`,
163
- pixelId,
164
- identityId: 'identity456',
165
- response: {
166
- identityId: 'identity456',
167
- traits: {
168
- emails: ['test@email.com'],
169
- addresses: [],
170
- },
171
- },
172
- updatedAt: new Date().toISOString(),
173
- };
174
- mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
175
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
176
- expect(result.identity).toBeDefined();
177
- expect(result.identity?.traits?.addresses).toHaveLength(1);
178
- expect(mockInvokeFunction).not.toHaveBeenCalled();
179
- expect(mockedDynamoDbClient.safeBatchWrite).not.toHaveBeenCalled();
180
- expect(mockBuildAndSendMessage).toHaveBeenCalled();
181
- });
182
- it('should enqueue async update and skip Neptune when address with PII but no source is added', async () => {
183
- IdentityGatewayService.configure({
184
- awsRegion: 'us-east-1',
185
- awsAccountId: '123456789',
186
- asyncUpdateQueueName: 'test-queue',
187
- });
188
- mockBuildAndSendMessage.mockResolvedValueOnce({ MessageId: 'test-msg-id' });
189
- const incomingIdentity = {
190
- identityId: 'identity456',
191
- traits: {
192
- emails: ['test@email.com'],
193
- addresses: [{ city: 'Miami', lastName: 'Smith' }],
194
- },
195
- };
196
- const cachedResponse = {
197
- pk: `identity#${pixelId}#identity456`,
198
- pixelId,
199
- identityId: 'identity456',
200
- response: {
201
- identityId: 'identity456',
202
- traits: {
203
- emails: ['test@email.com'],
204
- addresses: [],
205
- },
206
- },
207
- updatedAt: new Date().toISOString(),
208
- };
209
- mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
210
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
211
- expect(result.identity).toBeDefined();
212
- expect(mockInvokeFunction).not.toHaveBeenCalled();
213
- expect(mockedDynamoDbClient.safeBatchWrite).not.toHaveBeenCalled();
214
- expect(mockBuildAndSendMessage).toHaveBeenCalled();
215
- });
216
- it('should return ADDRESS_UPDATE_ASYNC outcome in summary', async () => {
217
- IdentityGatewayService.configure({
218
- awsRegion: 'us-east-1',
219
- awsAccountId: '123456789',
220
- asyncUpdateQueueName: 'test-queue',
221
- });
222
- mockBuildAndSendMessage.mockResolvedValueOnce({ MessageId: 'test-msg-id' });
223
- const incomingIdentity = {
224
- identityId: 'identity456',
225
- traits: {
226
- emails: ['test@email.com'],
227
- addresses: [{ city: 'Seattle', s: ADDRESS_INFO_SOURCE.INPUT }],
228
- },
229
- };
230
- const cachedResponse = {
231
- pk: `identity#${pixelId}#identity456`,
232
- pixelId,
233
- identityId: 'identity456',
234
- response: {
235
- identityId: 'identity456',
236
- traits: {
237
- emails: ['test@email.com'],
238
- addresses: [],
239
- },
240
- },
241
- updatedAt: new Date().toISOString(),
242
- };
243
- mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
244
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
245
- expect(result.summary.outcome).toBe(IDENTITY_CACHE_WITH_CACHING_OUTCOME.ADDRESS_UPDATE_ASYNC);
246
- expect(result.summary.didSkipNeptune).toBe(true);
247
- expect(result.summary.didWriteCache).toBe(false);
248
- expect(result.summary.didEnqueueAsync).toBe(true);
249
- });
250
- });
251
149
  describe('TIER: IDENTITY_STALE — Calls Neptune AND writes to cache', () => {
252
150
  it('should call Neptune and write to cache when emails are stale', async () => {
253
151
  const incomingIdentity = {
@@ -269,18 +167,13 @@ describe('Identity Cache Three-Tier Routing', () => {
269
167
  updatedAt: new Date().toISOString(),
270
168
  };
271
169
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
272
- mockInvokeFunction.mockResolvedValueOnce({
273
- statusCode: 200,
274
- body: JSON.stringify({
275
- identity: {
276
- identityId: 'identity456',
277
- traits: { emails: ['old@email.com', 'new@email.com', 'resolved@email.com'] },
278
- },
279
- }),
170
+ mockGetIdentity.mockResolvedValueOnce({
171
+ identityId: 'identity456',
172
+ traits: { emails: ['old@email.com', 'new@email.com', 'resolved@email.com'] },
280
173
  });
281
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
174
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
282
175
  expect(result.identity).toBeDefined();
283
- expect(mockInvokeFunction).toHaveBeenCalled();
176
+ expect(mockGetIdentity).toHaveBeenCalled();
284
177
  expect(mockedDynamoDbClient.safeBatchWrite).not.toHaveBeenCalled();
285
178
  });
286
179
  it('should call Neptune and write to cache when phones are stale', async () => {
@@ -303,18 +196,13 @@ describe('Identity Cache Three-Tier Routing', () => {
303
196
  updatedAt: new Date().toISOString(),
304
197
  };
305
198
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
306
- mockInvokeFunction.mockResolvedValueOnce({
307
- statusCode: 200,
308
- body: JSON.stringify({
309
- identity: {
310
- identityId: 'identity456',
311
- traits: { phones: ['+1234567890', '+9876543210'] },
312
- },
313
- }),
199
+ mockGetIdentity.mockResolvedValueOnce({
200
+ identityId: 'identity456',
201
+ traits: { phones: ['+1234567890', '+9876543210'] },
314
202
  });
315
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
203
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
316
204
  expect(result.identity).toBeDefined();
317
- expect(mockInvokeFunction).toHaveBeenCalled();
205
+ expect(mockGetIdentity).toHaveBeenCalled();
318
206
  expect(mockedDynamoDbClient.safeBatchWrite).not.toHaveBeenCalled();
319
207
  });
320
208
  it('should return NEPTUNE_WRITE_BACK outcome with staleTraits in summary', async () => {
@@ -335,20 +223,15 @@ describe('Identity Cache Three-Tier Routing', () => {
335
223
  updatedAt: new Date().toISOString(),
336
224
  };
337
225
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
338
- mockInvokeFunction.mockResolvedValueOnce({
339
- statusCode: 200,
340
- body: JSON.stringify({
341
- identity: {
342
- identityId: 'identity456',
343
- traits: { emails: ['old@email.com', 'new@email.com'] },
344
- },
345
- }),
226
+ mockGetIdentity.mockResolvedValueOnce({
227
+ identityId: 'identity456',
228
+ traits: { emails: ['old@email.com', 'new@email.com'] },
346
229
  });
347
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
348
- expect(result.summary.outcome).toBe(IDENTITY_CACHE_WITH_CACHING_OUTCOME.NEPTUNE_RESOLVED);
349
- expect(result.summary.staleTraits).toContain('emails');
350
- expect(result.summary.didCallNeptune).toBe(true);
351
- expect(result.summary.didWriteCache).toBe(false);
230
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
231
+ expect(result.outcome).toBe(IDENTITY_CACHE_WITH_CACHING_OUTCOME.NEPTUNE_RESOLVED);
232
+ expect(result.stalenessResult?.staleTraits).toContain('emails');
233
+ expect(result.didCallNeptune).toBe(true);
234
+ expect(result.didWriteCache).toBe(false);
352
235
  });
353
236
  });
354
237
  describe('CACHE_MISS — Calls Neptune AND writes to cache', () => {
@@ -358,18 +241,13 @@ describe('Identity Cache Three-Tier Routing', () => {
358
241
  traits: { emails: ['test@email.com'] },
359
242
  };
360
243
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(null);
361
- mockInvokeFunction.mockResolvedValueOnce({
362
- statusCode: 200,
363
- body: JSON.stringify({
364
- identity: {
365
- identityId: 'identity456',
366
- traits: { emails: ['test@email.com'] },
367
- },
368
- }),
244
+ mockGetIdentity.mockResolvedValueOnce({
245
+ identityId: 'identity456',
246
+ traits: { emails: ['test@email.com'] },
369
247
  });
370
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
248
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
371
249
  expect(result.identity).toBeDefined();
372
- expect(mockInvokeFunction).toHaveBeenCalled();
250
+ expect(mockGetIdentity).toHaveBeenCalled();
373
251
  expect(mockedDynamoDbClient.safeBatchWrite).not.toHaveBeenCalled();
374
252
  });
375
253
  it('should return NEPTUNE_WRITE_BACK outcome for cache miss', async () => {
@@ -378,19 +256,14 @@ describe('Identity Cache Three-Tier Routing', () => {
378
256
  traits: { emails: ['test@email.com'] },
379
257
  };
380
258
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(null);
381
- mockInvokeFunction.mockResolvedValueOnce({
382
- statusCode: 200,
383
- body: JSON.stringify({
384
- identity: {
385
- identityId: 'identity456',
386
- traits: { emails: ['test@email.com'] },
387
- },
388
- }),
259
+ mockGetIdentity.mockResolvedValueOnce({
260
+ identityId: 'identity456',
261
+ traits: { emails: ['test@email.com'] },
389
262
  });
390
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
391
- expect(result.summary.outcome).toBe(IDENTITY_CACHE_WITH_CACHING_OUTCOME.NEPTUNE_RESOLVED);
392
- expect(result.summary.didCallNeptune).toBe(true);
393
- expect(result.summary.didWriteCache).toBe(false);
263
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
264
+ expect(result.outcome).toBe(IDENTITY_CACHE_WITH_CACHING_OUTCOME.NEPTUNE_RESOLVED);
265
+ expect(result.didCallNeptune).toBe(true);
266
+ expect(result.didWriteCache).toBe(false);
394
267
  });
395
268
  });
396
269
  describe('EMAIL_POINTER_DISCOVERY — Calls Neptune with discovered identityId', () => {
@@ -406,35 +279,28 @@ describe('Identity Cache Three-Tier Routing', () => {
406
279
  updatedAt: new Date().toISOString(),
407
280
  };
408
281
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(pointerRecord);
409
- mockInvokeFunction.mockResolvedValueOnce({
410
- statusCode: 200,
411
- body: JSON.stringify({
412
- identity: {
413
- identityId: 'discovered-id',
414
- traits: { emails: ['test@email.com', 'other@email.com'] },
415
- },
416
- }),
282
+ mockGetIdentity.mockResolvedValueOnce({
283
+ identityId: 'discovered-id',
284
+ traits: { emails: ['test@email.com', 'other@email.com'] },
417
285
  });
418
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
286
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
419
287
  expect(result.identity?.identityId).toBe('discovered-id');
420
- expect(mockInvokeFunction).toHaveBeenCalledWith(lambdaArn, expect.objectContaining({
421
- context: {
422
- identity: expect.objectContaining({
423
- traits: { emails: ['test@email.com'] },
424
- }),
425
- },
288
+ expect(mockGetIdentity).toHaveBeenCalledWith(pixelId, expect.objectContaining({
289
+ identity: expect.objectContaining({
290
+ identityId: 'discovered-id',
291
+ traits: expect.objectContaining({ emails: ['test@email.com'] }),
292
+ }),
426
293
  }));
427
294
  });
428
295
  });
429
296
  });
430
297
  describe('Identity Cache stripAddressTimestamps', () => {
431
298
  const pixelId = 'pixel123';
432
- const lambdaArn = 'arn:aws:lambda:us-east-1:123456789:function:identity-private';
433
299
  beforeEach(() => {
434
300
  jest.clearAllMocks();
435
301
  mockedDynamoDbClient.safeGet.mockReset();
436
302
  mockedDynamoDbClient.safeBatchWrite.mockReset();
437
- mockInvokeFunction.mockReset();
303
+ mockGetIdentity.mockReset();
438
304
  IdentityGatewayService.lambdaInvokeClient = undefined;
439
305
  });
440
306
  it('should strip cra and upa from addresses during comparison', async () => {
@@ -473,9 +339,9 @@ describe('Identity Cache stripAddressTimestamps', () => {
473
339
  updatedAt: new Date().toISOString(),
474
340
  };
475
341
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
476
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
342
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
477
343
  expect(result.identity).toBeDefined();
478
- expect(mockInvokeFunction).not.toHaveBeenCalled();
344
+ expect(mockGetIdentity).not.toHaveBeenCalled();
479
345
  });
480
346
  it('should NOT mutate the original object when stripping timestamps', async () => {
481
347
  const originalAddress = {
@@ -512,7 +378,7 @@ describe('Identity Cache stripAddressTimestamps', () => {
512
378
  updatedAt: new Date().toISOString(),
513
379
  };
514
380
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
515
- await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
381
+ await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
516
382
  expect(incomingIdentity.traits?.addresses?.[0]).toHaveProperty('cra');
517
383
  expect(incomingIdentity.traits?.addresses?.[0]).toHaveProperty('upa');
518
384
  expect(cachedResponse.response.traits?.addresses?.[0]).toHaveProperty('cra');
@@ -538,9 +404,9 @@ describe('Identity Cache stripAddressTimestamps', () => {
538
404
  updatedAt: new Date().toISOString(),
539
405
  };
540
406
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
541
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
407
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
542
408
  expect(result.identity).toBeDefined();
543
- expect(mockInvokeFunction).not.toHaveBeenCalled();
409
+ expect(mockGetIdentity).not.toHaveBeenCalled();
544
410
  });
545
411
  it('should handle identity with empty addresses array', async () => {
546
412
  const incomingIdentity = {
@@ -564,9 +430,9 @@ describe('Identity Cache stripAddressTimestamps', () => {
564
430
  updatedAt: new Date().toISOString(),
565
431
  };
566
432
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
567
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
433
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
568
434
  expect(result.identity).toBeDefined();
569
- expect(mockInvokeFunction).not.toHaveBeenCalled();
435
+ expect(mockGetIdentity).not.toHaveBeenCalled();
570
436
  });
571
437
  it('should handle addresses without cra/upa (no-op)', async () => {
572
438
  const incomingIdentity = {
@@ -590,19 +456,18 @@ describe('Identity Cache stripAddressTimestamps', () => {
590
456
  updatedAt: new Date().toISOString(),
591
457
  };
592
458
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
593
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
459
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
594
460
  expect(result.identity).toBeDefined();
595
- expect(mockInvokeFunction).not.toHaveBeenCalled();
461
+ expect(mockGetIdentity).not.toHaveBeenCalled();
596
462
  });
597
463
  });
598
464
  describe('Identity Cache fastDeepEqual with Timestamp Stripping', () => {
599
465
  const pixelId = 'pixel123';
600
- const lambdaArn = 'arn:aws:lambda:us-east-1:123456789:function:identity-private';
601
466
  beforeEach(() => {
602
467
  jest.clearAllMocks();
603
468
  mockedDynamoDbClient.safeGet.mockReset();
604
469
  mockedDynamoDbClient.safeBatchWrite.mockReset();
605
- mockInvokeFunction.mockReset();
470
+ mockGetIdentity.mockReset();
606
471
  IdentityGatewayService.lambdaInvokeClient = undefined;
607
472
  });
608
473
  it('should treat cached and merged as equal when they differ ONLY in cra/upa', async () => {
@@ -645,9 +510,9 @@ describe('Identity Cache fastDeepEqual with Timestamp Stripping', () => {
645
510
  updatedAt: new Date().toISOString(),
646
511
  };
647
512
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
648
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
513
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
649
514
  expect(result.identity).toBeDefined();
650
- expect(mockInvokeFunction).not.toHaveBeenCalled();
515
+ expect(mockGetIdentity).not.toHaveBeenCalled();
651
516
  expect(mockedDynamoDbClient.safeBatchWrite).not.toHaveBeenCalled();
652
517
  });
653
518
  it('should treat cached and merged as NOT equal when address content differs (plus cra/upa)', async () => {
@@ -688,18 +553,17 @@ describe('Identity Cache fastDeepEqual with Timestamp Stripping', () => {
688
553
  updatedAt: new Date().toISOString(),
689
554
  };
690
555
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
691
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
556
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
692
557
  expect(result.identity).toBeDefined();
693
558
  });
694
559
  });
695
560
  describe('Identity Cache Logging Levels', () => {
696
561
  const pixelId = 'pixel123';
697
- const lambdaArn = 'arn:aws:lambda:us-east-1:123456789:function:identity-private';
698
562
  beforeEach(() => {
699
563
  jest.clearAllMocks();
700
564
  mockedDynamoDbClient.safeGet.mockReset();
701
565
  mockedDynamoDbClient.safeBatchWrite.mockReset();
702
- mockInvokeFunction.mockReset();
566
+ mockGetIdentity.mockReset();
703
567
  IdentityGatewayService.lambdaInvokeClient = undefined;
704
568
  });
705
569
  it('should return fresh cache hit without calling Neptune or writing cache', async () => {
@@ -722,45 +586,11 @@ describe('Identity Cache Logging Levels', () => {
722
586
  updatedAt: new Date().toISOString(),
723
587
  };
724
588
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
725
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
726
- expect(result.summary.outcome).toBe(IDENTITY_CACHE_WITH_CACHING_OUTCOME.FRESH_CACHE_HIT);
727
- expect(mockInvokeFunction).not.toHaveBeenCalled();
589
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
590
+ expect(result.outcome).toBe(IDENTITY_CACHE_WITH_CACHING_OUTCOME.FRESH_CACHE_HIT);
591
+ expect(mockGetIdentity).not.toHaveBeenCalled();
728
592
  expect(mockedDynamoDbClient.safeBatchWrite).not.toHaveBeenCalled();
729
593
  });
730
- it('should return ADDRESS_UPDATE_ASYNC outcome for address update path', async () => {
731
- IdentityGatewayService.configure({
732
- awsRegion: 'us-east-1',
733
- awsAccountId: '123456789',
734
- asyncUpdateQueueName: 'test-queue',
735
- });
736
- mockBuildAndSendMessage.mockResolvedValueOnce({ MessageId: 'test-msg-id' });
737
- const incomingIdentity = {
738
- identityId: 'identity456',
739
- traits: {
740
- emails: ['test@email.com'],
741
- addresses: [{ city: 'New City', s: ADDRESS_INFO_SOURCE.INPUT }],
742
- },
743
- };
744
- const cachedResponse = {
745
- pk: `identity#${pixelId}#identity456`,
746
- pixelId,
747
- identityId: 'identity456',
748
- response: {
749
- identityId: 'identity456',
750
- traits: {
751
- emails: ['test@email.com'],
752
- addresses: [],
753
- },
754
- },
755
- updatedAt: new Date().toISOString(),
756
- };
757
- mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
758
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
759
- expect(result.summary.outcome).toBe(IDENTITY_CACHE_WITH_CACHING_OUTCOME.ADDRESS_UPDATE_ASYNC);
760
- expect(result.summary.didSkipNeptune).toBe(true);
761
- expect(result.summary.didWriteCache).toBe(false);
762
- expect(result.summary.didEnqueueAsync).toBe(true);
763
- });
764
594
  it('should return NEPTUNE_WRITE_BACK outcome with traitChanges for stale traits', async () => {
765
595
  const incomingIdentity = {
766
596
  identityId: 'identity456',
@@ -781,107 +611,16 @@ describe('Identity Cache Logging Levels', () => {
781
611
  updatedAt: new Date().toISOString(),
782
612
  };
783
613
  mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
784
- mockInvokeFunction.mockResolvedValueOnce({
785
- statusCode: 200,
786
- body: JSON.stringify({
787
- identity: {
788
- identityId: 'identity456',
789
- traits: { emails: ['old@email.com', 'new@email.com'] },
790
- },
791
- }),
792
- });
793
- const result = await IdentityGatewayService.getIdentityWithCachingV2(pixelId, incomingIdentity, lambdaArn);
794
- expect(result.summary.outcome).toBe(IDENTITY_CACHE_WITH_CACHING_OUTCOME.NEPTUNE_RESOLVED);
795
- expect(result.summary.staleTraits).toContain('emails');
796
- expect(result.summary.traitChanges).toBeDefined();
797
- expect(result.summary.didCallNeptune).toBe(true);
798
- expect(result.summary.didWriteCache).toBe(false);
799
- });
800
- });
801
- describe('getIdentityFromCache staleness tier results', () => {
802
- const pixelId = 'pixel123';
803
- beforeEach(() => {
804
- jest.clearAllMocks();
805
- mockedDynamoDbClient.safeGet.mockReset();
806
- });
807
- it('should return staleTier NONE when cached and incoming are deep equal', async () => {
808
- const incomingIdentity = {
809
- identityId: 'identity456',
810
- traits: {
811
- emails: ['test@email.com'],
812
- },
813
- };
814
- const cachedResponse = {
815
- pk: `identity#${pixelId}#identity456`,
816
- pixelId,
817
- identityId: 'identity456',
818
- response: {
819
- identityId: 'identity456',
820
- traits: {
821
- emails: ['test@email.com'],
822
- },
823
- },
824
- updatedAt: new Date().toISOString(),
825
- };
826
- mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
827
- const result = await IdentityCacheDynamoDbDbService.getIdentityFromCache(pixelId, incomingIdentity);
828
- expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.NONE);
829
- expect(result.isCacheStale).toBe(false);
830
- expect(result.skipNeptune).toBeUndefined();
831
- });
832
- it('should return staleTier ADDRESS_UPDATE and skipNeptune=true for new non-IP address', async () => {
833
- const incomingIdentity = {
834
- identityId: 'identity456',
835
- traits: {
836
- emails: ['test@email.com'],
837
- addresses: [{ city: 'New City', s: ADDRESS_INFO_SOURCE.INPUT }],
838
- },
839
- };
840
- const cachedResponse = {
841
- pk: `identity#${pixelId}#identity456`,
842
- pixelId,
843
- identityId: 'identity456',
844
- response: {
845
- identityId: 'identity456',
846
- traits: {
847
- emails: ['test@email.com'],
848
- addresses: [],
849
- },
850
- },
851
- updatedAt: new Date().toISOString(),
852
- };
853
- mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
854
- const result = await IdentityCacheDynamoDbDbService.getIdentityFromCache(pixelId, incomingIdentity);
855
- expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.ADDRESS_UPDATE);
856
- expect(result.isCacheStale).toBe(true);
857
- expect(result.skipNeptune).toBe(true);
858
- expect(result.writeReason).toBe(CACHE_WRITE_REASON.ADDRESS_UPDATE);
859
- });
860
- it('should return staleTier IDENTITY_STALE and skipNeptune=false for new email', async () => {
861
- const incomingIdentity = {
614
+ mockGetIdentity.mockResolvedValueOnce({
862
615
  identityId: 'identity456',
863
- traits: {
864
- emails: ['old@email.com', 'new@email.com'],
865
- },
866
- };
867
- const cachedResponse = {
868
- pk: `identity#${pixelId}#identity456`,
869
- pixelId,
870
- identityId: 'identity456',
871
- response: {
872
- identityId: 'identity456',
873
- traits: {
874
- emails: ['old@email.com'],
875
- },
876
- },
877
- updatedAt: new Date().toISOString(),
878
- };
879
- mockedDynamoDbClient.safeGet.mockResolvedValueOnce(cachedResponse);
880
- const result = await IdentityCacheDynamoDbDbService.getIdentityFromCache(pixelId, incomingIdentity);
881
- expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
882
- expect(result.isCacheStale).toBe(true);
883
- expect(result.skipNeptune).toBe(false);
884
- expect(result.writeReason).toBe(CACHE_WRITE_REASON.STALE_TRAITS);
616
+ traits: { emails: ['old@email.com', 'new@email.com'] },
617
+ });
618
+ const result = await IdentityGatewayService.resolveIdentityWithCaching(pixelId, incomingIdentity);
619
+ expect(result.outcome).toBe(IDENTITY_CACHE_WITH_CACHING_OUTCOME.NEPTUNE_RESOLVED);
620
+ expect(result.stalenessResult?.staleTraits).toContain('emails');
621
+ expect(result.traitChanges).toBeDefined();
622
+ expect(result.didCallNeptune).toBe(true);
623
+ expect(result.didWriteCache).toBe(false);
885
624
  });
886
625
  });
887
626
  //# sourceMappingURL=identity-cache-tier-routing.spec.js.map