From 0699b82f2b5670c76e376d4cfc5cc0f37721945a Mon Sep 17 00:00:00 2001 From: vlasis-perdikidis Date: Fri, 17 Apr 2026 13:59:26 +0000 Subject: [PATCH 1/6] emit metrics for supplier-allocator --- .gitleaksignore | 6 +++ .../src/handler/allocate-handler.ts | 44 +++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/.gitleaksignore b/.gitleaksignore index 743843dbe..6758264a1 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -25,3 +25,9 @@ debc75a97cfe551a69fd1e8694be483213322a9d:pact-contracts/pacts/letter-rendering/s 4fa1923947bbff2387218d698d766cbb7c121a0f:pact-contracts/pacts/letter-rendering/supplier-api-letter-request-prepared.json:generic-api-key:10 d005112adcfd286c3bef076214836dbb2fe8d0b5:.npmrc:npm-access-token:9 d005112adcfd286c3bef076214836dbb2fe8d0b5:.npmrc:github-pat:7 +ff889d4c3f29da4468ecf1f05f467fe84d35b2a1:lambdas/supplier-mock/.aws-sam/build/SupplierMockFunction/index.js.map:ipv4:4 +ff889d4c3f29da4468ecf1f05f467fe84d35b2a1:lambdas/supplier-mock/.aws-sam/build/SupplierMockFunction/index.js:ipv4:63 +ff889d4c3f29da4468ecf1f05f467fe84d35b2a1:lambdas/supplier-mock/.aws-sam/build/SupplierMockFunction/index.js:ipv4:62 +ff889d4c3f29da4468ecf1f05f467fe84d35b2a1:lambdas/supplier-mock/.aws-sam/build/SupplierMockFunction/index.js:ipv4:60 +ff889d4c3f29da4468ecf1f05f467fe84d35b2a1:lambdas/supplier-mock/.aws-sam/build/SupplierMockFunction/index.js:ipv4:59 +ff889d4c3f29da4468ecf1f05f467fe84d35b2a1:lambdas/supplier-mock/.aws-sam/build/SupplierMockFunction/index.js:ipv4:24 diff --git a/lambdas/supplier-allocator/src/handler/allocate-handler.ts b/lambdas/supplier-allocator/src/handler/allocate-handler.ts index 2288fae12..0aa4a08c6 100644 --- a/lambdas/supplier-allocator/src/handler/allocate-handler.ts +++ b/lambdas/supplier-allocator/src/handler/allocate-handler.ts @@ -144,6 +144,28 @@ function emitMetrics( } } +function emitSupCampaignClientMetric( + letterEvent: PreparedEvents, + supplier: string, + status: MetricStatus, + deps: Deps, +) { + const namespace = "supplier-allocator"; + const clientId = letterEvent ? letterEvent.data.clientId : "unknown"; + const campaignId = letterEvent ? letterEvent.data.campaignId : "unknown"; + const dimensions: Record = { + Supplier: supplier, + ClientId: clientId, + CampaignId: campaignId || "unknown", + }; + const metric: MetricEntry = { + key: status, + value: 1, + unit: Unit.Count, + }; + deps.logger.info(buildEMFObject(namespace, dimensions, metric)); +} + export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler { return async (event: SQSEvent) => { const batchItemFailures: SQSBatchItemFailure[] = []; @@ -153,8 +175,9 @@ export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler { const tasks = event.Records.map(async (record) => { let supplier = "unknown"; let priority = "unknown"; + let letterEvent: PreparedEvents | undefined; try { - const letterEvent: unknown = JSON.parse(record.body); + letterEvent = JSON.parse(record.body) as PreparedEvents; deps.logger.info({ description: "Extracted letter event", @@ -163,8 +186,8 @@ export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler { validateType(letterEvent); - const supplierSpec = getSupplier(letterEvent as PreparedEvents, deps); - await getSupplierFromConfig(letterEvent as PreparedEvents, deps); + const supplierSpec = getSupplier(letterEvent, deps); + await getSupplierFromConfig(letterEvent, deps); supplier = supplierSpec.supplierId; priority = String(supplierSpec.priority); @@ -199,6 +222,15 @@ export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler { ); incrementMetric(perAllocationSuccess, supplier, priority); + // increment clientid + // increment campaignid + // emit metric with current supplier, clientId and campaignId + emitSupCampaignClientMetric( + letterEvent, + supplier, + MetricStatus.Success, + deps, + ); } catch (error) { deps.logger.error({ description: "Error processing allocation of record", @@ -208,6 +240,12 @@ export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler { }); incrementMetric(perAllocationFailure, supplier, priority); batchItemFailures.push({ itemIdentifier: record.messageId }); + emitSupCampaignClientMetric( + letterEvent as PreparedEvents, + supplier, + MetricStatus.Failure, + deps, + ); } }); From 3e690b4c33a416dda222ccde6babe1afa41ddce1 Mon Sep 17 00:00:00 2001 From: vlasis-perdikidis Date: Fri, 17 Apr 2026 18:05:31 +0000 Subject: [PATCH 2/6] ensure that clientId and campaignId is never undefined when emiting metric --- .../src/handler/allocate-handler.ts | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lambdas/supplier-allocator/src/handler/allocate-handler.ts b/lambdas/supplier-allocator/src/handler/allocate-handler.ts index 0aa4a08c6..2fa7b554d 100644 --- a/lambdas/supplier-allocator/src/handler/allocate-handler.ts +++ b/lambdas/supplier-allocator/src/handler/allocate-handler.ts @@ -151,12 +151,12 @@ function emitSupCampaignClientMetric( deps: Deps, ) { const namespace = "supplier-allocator"; - const clientId = letterEvent ? letterEvent.data.clientId : "unknown"; - const campaignId = letterEvent ? letterEvent.data.campaignId : "unknown"; + const clientId = getClientId(letterEvent); + const campaignId = getCampaignId(letterEvent); const dimensions: Record = { Supplier: supplier, ClientId: clientId, - CampaignId: campaignId || "unknown", + CampaignId: campaignId, }; const metric: MetricEntry = { key: status, @@ -166,6 +166,20 @@ function emitSupCampaignClientMetric( deps.logger.info(buildEMFObject(namespace, dimensions, metric)); } +function getClientId(letterEvent: PreparedEvents): string { + if (letterEvent && letterEvent.data && letterEvent.data.clientId) { + return letterEvent.data.clientId; + } + return "unknown"; +} + +function getCampaignId(letterEvent: PreparedEvents): string { + if (letterEvent && letterEvent.data && letterEvent.data.campaignId) { + return letterEvent.data.campaignId; + } + return "unknown"; +} + export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler { return async (event: SQSEvent) => { const batchItemFailures: SQSBatchItemFailure[] = []; From e26fa9767a58225c1afbc657360e6bbe77e494f0 Mon Sep 17 00:00:00 2001 From: vlasis-perdikidis Date: Tue, 21 Apr 2026 10:59:31 +0000 Subject: [PATCH 3/6] use distinct the name for the new metric --- .../supplier-allocator/src/handler/allocate-handler.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lambdas/supplier-allocator/src/handler/allocate-handler.ts b/lambdas/supplier-allocator/src/handler/allocate-handler.ts index 2fa7b554d..c8c151351 100644 --- a/lambdas/supplier-allocator/src/handler/allocate-handler.ts +++ b/lambdas/supplier-allocator/src/handler/allocate-handler.ts @@ -147,7 +147,7 @@ function emitMetrics( function emitSupCampaignClientMetric( letterEvent: PreparedEvents, supplier: string, - status: MetricStatus, + status: string, deps: Deps, ) { const namespace = "supplier-allocator"; @@ -242,7 +242,7 @@ export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler { emitSupCampaignClientMetric( letterEvent, supplier, - MetricStatus.Success, + "supplier_Campaign_Client", deps, ); } catch (error) { @@ -254,12 +254,6 @@ export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler { }); incrementMetric(perAllocationFailure, supplier, priority); batchItemFailures.push({ itemIdentifier: record.messageId }); - emitSupCampaignClientMetric( - letterEvent as PreparedEvents, - supplier, - MetricStatus.Failure, - deps, - ); } }); From 3b75bb4a846fb34f156ec9d299fb2824332bcc9e Mon Sep 17 00:00:00 2001 From: vlasis-perdikidis Date: Tue, 21 Apr 2026 12:49:36 +0000 Subject: [PATCH 4/6] get unit tests to pass --- .../__tests__/allocate-handler.test.ts | 33 ++++++++++++++++++- .../src/handler/allocate-handler.ts | 20 ++--------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/lambdas/supplier-allocator/src/handler/__tests__/allocate-handler.test.ts b/lambdas/supplier-allocator/src/handler/__tests__/allocate-handler.test.ts index eb1a3bfdb..b4606c4f6 100644 --- a/lambdas/supplier-allocator/src/handler/__tests__/allocate-handler.test.ts +++ b/lambdas/supplier-allocator/src/handler/__tests__/allocate-handler.test.ts @@ -69,7 +69,7 @@ function createPreparedV1Event( requestItemId: "requestItem1", requestItemPlanId: "requestItemPlan1", clientId: "client1", - campaignId: "campaign1", + campaignId: overrides.campaignId ?? "campaign1", templateId: "template1", url: overrides.url ?? "s3://letterDataBucket/letter1.pdf", sha256Hash: @@ -230,6 +230,37 @@ describe("createSupplierAllocatorHandler", () => { }); }); + test("parses SNS notification and sends message to SQS queue for v2 event without a campaignId", async () => { + const preparedEvent = createPreparedV2Event({ campaignId: "" }); + const evt: SQSEvent = createSQSEvent([ + createSqsRecord("msg1", JSON.stringify(preparedEvent)), + ]); + + setupDefaultMocks(); + process.env.UPSERT_LETTERS_QUEUE_URL = "https://sqs.test.queue"; + + const handler = createSupplierAllocatorHandler(mockedDeps); + const result = await handler(evt, {} as any, {} as any); + + expect(result).toBeDefined(); + if (!result) throw new Error("expected BatchResponse, got void"); + + expect(result.batchItemFailures).toHaveLength(0); + + expect(mockSqsClient.send).toHaveBeenCalledTimes(1); + const sendCall = (mockSqsClient.send as jest.Mock).mock.calls[0][0]; + expect(sendCall).toBeInstanceOf(SendMessageCommand); + + const messageBody = JSON.parse(sendCall.input.MessageBody); + expect(messageBody.letterEvent).toEqual(preparedEvent); + expect(messageBody.supplierSpec).toEqual({ + supplierId: "supplier1", + specId: "spec1", + priority: 1, + billingId: "billing1", + }); + }); + test("parses SNS notification and sends message to SQS queue for v1 event", async () => { const preparedEvent = createPreparedV1Event(); diff --git a/lambdas/supplier-allocator/src/handler/allocate-handler.ts b/lambdas/supplier-allocator/src/handler/allocate-handler.ts index c8c151351..beaf79c23 100644 --- a/lambdas/supplier-allocator/src/handler/allocate-handler.ts +++ b/lambdas/supplier-allocator/src/handler/allocate-handler.ts @@ -151,12 +151,12 @@ function emitSupCampaignClientMetric( deps: Deps, ) { const namespace = "supplier-allocator"; - const clientId = getClientId(letterEvent); - const campaignId = getCampaignId(letterEvent); + const { campaignId, clientId } = letterEvent.data; + console.log("VLASIS and the campaignId is:", campaignId); const dimensions: Record = { Supplier: supplier, ClientId: clientId, - CampaignId: campaignId, + CampaignId: campaignId || "unknown", }; const metric: MetricEntry = { key: status, @@ -166,20 +166,6 @@ function emitSupCampaignClientMetric( deps.logger.info(buildEMFObject(namespace, dimensions, metric)); } -function getClientId(letterEvent: PreparedEvents): string { - if (letterEvent && letterEvent.data && letterEvent.data.clientId) { - return letterEvent.data.clientId; - } - return "unknown"; -} - -function getCampaignId(letterEvent: PreparedEvents): string { - if (letterEvent && letterEvent.data && letterEvent.data.campaignId) { - return letterEvent.data.campaignId; - } - return "unknown"; -} - export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler { return async (event: SQSEvent) => { const batchItemFailures: SQSBatchItemFailure[] = []; From 6e722e4be5fe504a3abeb2c52597f60e4ac00386 Mon Sep 17 00:00:00 2001 From: vlasis-perdikidis Date: Tue, 21 Apr 2026 14:00:43 +0000 Subject: [PATCH 5/6] add a dummy supplier --- lambdas/supplier-allocator/src/handler/allocate-handler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambdas/supplier-allocator/src/handler/allocate-handler.ts b/lambdas/supplier-allocator/src/handler/allocate-handler.ts index beaf79c23..d4f77933c 100644 --- a/lambdas/supplier-allocator/src/handler/allocate-handler.ts +++ b/lambdas/supplier-allocator/src/handler/allocate-handler.ts @@ -154,7 +154,7 @@ function emitSupCampaignClientMetric( const { campaignId, clientId } = letterEvent.data; console.log("VLASIS and the campaignId is:", campaignId); const dimensions: Record = { - Supplier: supplier, + Supplier: "supplierVlasis", ClientId: clientId, CampaignId: campaignId || "unknown", }; From e5377f4dad9d6a53dd7103df4527ff59fa4b08b5 Mon Sep 17 00:00:00 2001 From: vlasis-perdikidis Date: Wed, 22 Apr 2026 12:14:52 +0000 Subject: [PATCH 6/6] remove comments --- lambdas/supplier-allocator/src/handler/allocate-handler.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lambdas/supplier-allocator/src/handler/allocate-handler.ts b/lambdas/supplier-allocator/src/handler/allocate-handler.ts index d4f77933c..8218a6db8 100644 --- a/lambdas/supplier-allocator/src/handler/allocate-handler.ts +++ b/lambdas/supplier-allocator/src/handler/allocate-handler.ts @@ -152,9 +152,8 @@ function emitSupCampaignClientMetric( ) { const namespace = "supplier-allocator"; const { campaignId, clientId } = letterEvent.data; - console.log("VLASIS and the campaignId is:", campaignId); const dimensions: Record = { - Supplier: "supplierVlasis", + Supplier: supplier, ClientId: clientId, CampaignId: campaignId || "unknown", }; @@ -222,9 +221,6 @@ export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler { ); incrementMetric(perAllocationSuccess, supplier, priority); - // increment clientid - // increment campaignid - // emit metric with current supplier, clientId and campaignId emitSupCampaignClientMetric( letterEvent, supplier,