Skip to content

Commit

Permalink
CB2-11819: Move SMC prohibition to SNS/SQS pattern (#21)
Browse files Browse the repository at this point in the history
* feat(CB2-11819): cahnged event type

* feat(CB2-11819): cahnged event type

* feat(CB2-11819): event handling

* feat(CB2-11819): event handling

* feat(CB2-11819): event handling

* feat(CB2-11819): event handling

* feat(CB2-11819): event handling

* feat(CB2-11819): event handling

* feat(CB2-11819): event handling

* feat(CB2-11819): event handling

* feat(CB2-11819): removed logs

* feat(CB2-11819): json parse change

* feat(CB2-11819): json parse change

* feat(CB2-11819): json parse change
  • Loading branch information
Daniel-Searle authored Jun 13, 2024
1 parent a787a56 commit 7dae2bf
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 55 deletions.
22 changes: 16 additions & 6 deletions src/handler.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* eslint-disable */

import { DynamoDBStreamEvent, Context, Callback } from 'aws-lambda';
import { Context, Callback, SQSEvent, DynamoDBRecord } from 'aws-lambda';
import { extractMCTestResults } from './utils/ExtractTestResults';
import { sendMCProhibition } from './eventbridge/Send';
import logger from './observability/Logger';
import { MCRequest } from './utils/MCRequest';

const handler = async (
event: DynamoDBStreamEvent,
event: SQSEvent,
_context: Context,
callback: Callback,
) => {
Expand All @@ -20,13 +21,22 @@ const handler = async (
try {
logger.debug(`Function triggered with '${JSON.stringify(event)}'.`);

// We want to process these in sequence to maintain order of database changes
for (const record of event.Records) {
const mcRequests: MCRequest[] = extractMCTestResults(record);
if (mcRequests != null) {
await sendMCProhibition(mcRequests);
const dynamoDBEvent: DynamoDBRecord = JSON.parse(record.body) as DynamoDBRecord;
if (dynamoDBEvent){
const mcRequests: MCRequest[] = extractMCTestResults(dynamoDBEvent);

if (mcRequests != null && mcRequests.length > 0) {
await sendMCProhibition(mcRequests);
} else {
logger.info(`No relevant MC test results found in the record: ${JSON.stringify(dynamoDBEvent)}`);
}
} else {
logger.info('Function not triggered, empty notification.');
callback(null, 'Function not triggered, empty notification.');
}
}

callback(null, 'Data processed successfully.');
} catch (error) {
if (error.body) {
Expand Down
5 changes: 3 additions & 2 deletions src/utils/ExtractTestResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import { unmarshall } from '@aws-sdk/util-dynamodb';
import { DateTime } from 'luxon';
import { DynamoDBRecord } from 'aws-lambda';
import { PROHIB_CLEARANCE_TEST_TYPE_IDS } from '../assets/Enums';
import logger from '../observability/Logger';
import { HTTPError } from './HTTPError';
Expand All @@ -20,8 +21,8 @@ import { ValidationUtil } from './ValidationUtil';
* required to be sent to MC in order to clear prohibitions
* @param record
*/
export const extractMCTestResults = (record: any): MCRequest[] => {
const testResultUnmarshall = unmarshall(record.dynamodb.NewImage as { any });
export const extractMCTestResults = (record: DynamoDBRecord): MCRequest[] => {
const testResultUnmarshall = unmarshall(record.dynamodb.NewImage as any);
logger.info(
`Processing testResultId: ${JSON.stringify(
testResultUnmarshall.testResultId,
Expand Down
111 changes: 64 additions & 47 deletions tests/unit/Handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
/* eslint-disable import/first */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable no-underscore-dangle */
/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable import/no-unresolved */
import { DynamoDBRecord, DynamoDBStreamEvent } from 'aws-lambda';
import { SQSEvent } from 'aws-lambda';
import { sendMCProhibition } from '../../src/eventbridge/Send';
import { SendResponse } from '../../src/eventbridge/SendResponse';
import { extractMCTestResults } from '../../src/utils/ExtractTestResults';
Expand All @@ -17,67 +10,91 @@ jest.mock('../../src/eventbridge/Send');
jest.mock('../../src/utils/ExtractTestResults');

describe('Application entry', () => {
let event: DynamoDBStreamEvent;
const event: SQSEvent = {
Records: [
{
messageId: '1317d15-a23b2-4c68-a2da-67cc685dda5b',
receiptHandle: 'aer3fiu34yufybuy34f334',
body: JSON.stringify({
Message: {
eventID: '...',
eventName: 'INSERT',
dynamodb: {
NewImage: dynamoRecordFiltered.dynamodb.NewImage,
},
},
}),
attributes: {
ApproximateReceiveCount: '1',
SentTimestamp: '1717678383236',
SenderId: 'AIDAISMY7JYY5F7RTT6AO',
ApproximateFirstReceiveTimestamp: '1717678383247',
},
messageAttributes: {},
md5OfBody: '45bd1375e48194d7e1563cf20462d',
eventSource: 'aws:sqs',
eventSourceARN: 'arn:aws:sqs:eu-west-1:local:cvs-smc-prohibition-local-queue',
awsRegion: 'eu-west-1',
},
],
};
const sendResponse: SendResponse = {
SuccessCount: 1,
FailCount: 0,
};

jest.mocked(extractMCTestResults).mockReturnValue(Array<MCRequest>());
afterEach(() => {
jest.clearAllMocks();
});

describe('Handler', () => {
it('When there is an event that gets processed successfully no errors are produced', async () => {
event = {
Records: [dynamoRecordFiltered as DynamoDBRecord],
};
const sendResponse: SendResponse = {
SuccessCount: 1,
FailCount: 0,
};
process.env.SEND_TO_SMC = 'True';
it('should process a valid event successfully', async () => {
const expectedMCRequests: MCRequest[] = [
{
vehicleIdentifier: 'ABC1234',
testDate: '14/01/2019',
vin: 'XMGDE02FS0H012303',
testResult: 'P',
hgvPsvTrailFlag: 'T',
testResultId: 'some-test-result-id',
},
];

jest.mocked(extractMCTestResults).mockReturnValue(expectedMCRequests);
jest.mocked(sendMCProhibition).mockResolvedValue(sendResponse);
await handler(event, null, (error: string | Error, result: string) => {
expect(result).toBe('Data processed successfully.');

await handler(event, null, (error, result) => {
expect(error).toBeNull();
expect(sendMCProhibition).toHaveBeenCalledTimes(1);
});
});
it('When there is an event that gets processed successfully in proper case then no errors are produced', async () => {
process.env.SEND_TO_SMC = 'True';
event = {
Records: [dynamoRecordFiltered as DynamoDBRecord],
};
const sendResponse: SendResponse = {
SuccessCount: 1,
FailCount: 0,
};
jest.mocked(sendMCProhibition).mockResolvedValue(sendResponse);
await handler(event, null, (error: string | Error, result: string) => {
expect(result).toBe('Data processed successfully.');
expect(error).toBeNull();
expect(sendMCProhibition).toHaveBeenCalledTimes(1);
expect(sendMCProhibition).toHaveBeenCalledWith(expectedMCRequests);
});
});
it('When there is an error when sending the object and error is produced', async () => {

it('should handle an error when sending the object', async () => {
process.env.SEND_TO_SMC = 'True';
event = {
Records: [dynamoRecordFiltered as DynamoDBRecord],
};
const expectedErrorMessage = 'Data processed unsuccessfully: Error: Oh no!';
jest.mocked(sendMCProhibition).mockRejectedValue(new Error('Oh no!'));
await handler(event, null, (error: string | Error, result: string) => {

await handler(event, null, (error, result) => {
expect(error).toBeNull();
expect(result).toBe('Data processed unsuccessfully: Error: Oh no!');
expect(result).toBe(expectedErrorMessage);
expect(sendMCProhibition).toHaveBeenCalledTimes(1);
});
});
it('When there is an invalid environment variable a log is produced', async () => {

it('should handle an invalid environment variable', async () => {
process.env.SEND_TO_SMC = 'false';
event = {
Records: [dynamoRecordFiltered as DynamoDBRecord],
};
jest.spyOn(console, 'log');

await handler(event, null, (error: string | Error, result: string) => {
await handler(event, null, (error, result) => {
expect(error).toBeNull();
expect(result).toBe('Function not triggered, Missing or not true environment variable present');
expect(extractMCTestResults).not.toHaveBeenCalled();
expect(sendMCProhibition).not.toHaveBeenCalled();
});
});
});
});


0 comments on commit 7dae2bf

Please sign in to comment.