Skip to content

Commit 66fa5cd

Browse files
CCM-11976: Routing event publish (#774)
1 parent 55ad915 commit 66fa5cd

File tree

25 files changed

+1925
-98
lines changed

25 files changed

+1925
-98
lines changed

infrastructure/terraform/components/sandbox/module_backend_api.tf

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ module "backend_api" {
3131

3232
send_to_firehose = false
3333

34-
enable_routing_config_event_stream = true
35-
3634
email_domain = local.email_domain
3735
template_submitted_sender_email_address = local.sandbox_letter_supplier_mock_template_submitted_sender
3836
proof_requested_sender_email_address = local.sandbox_letter_supplier_mock_proof_requested_sender

infrastructure/terraform/modules/backend-api/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ No requirements.
1616
| <a name="input_csi"></a> [csi](#input\_csi) | CSI from the parent component | `string` | n/a | yes |
1717
| <a name="input_email_domain"></a> [email\_domain](#input\_email\_domain) | Email domain | `string` | n/a | yes |
1818
| <a name="input_enable_backup"></a> [enable\_backup](#input\_enable\_backup) | Enable Backups for the DynamoDB table? | `bool` | `true` | no |
19-
| <a name="input_enable_routing_config_event_stream"></a> [enable\_routing\_config\_event\_stream](#input\_enable\_routing\_config\_event\_stream) | Enable DynamoDB streaming from routing config table to EventBridge | `bool` | `false` | no |
2019
| <a name="input_environment"></a> [environment](#input\_environment) | The name of the tfscaffold environment | `string` | n/a | yes |
2120
| <a name="input_function_s3_bucket"></a> [function\_s3\_bucket](#input\_function\_s3\_bucket) | Name of S3 bucket to upload lambda artefacts to | `string` | n/a | yes |
2221
| <a name="input_group"></a> [group](#input\_group) | The group variables are being inherited from (often synonmous with account short-name) | `string` | n/a | yes |

infrastructure/terraform/modules/backend-api/pipes_pipe_routing_config_table_events.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ resource "aws_pipes_pipe" "routing_config_table_events" {
55
role_arn = aws_iam_role.pipe_routing_config_table_events.arn
66
source = aws_dynamodb_table.routing_configuration.stream_arn
77
target = module.sqs_template_mgmt_events.sqs_queue_arn
8-
desired_state = var.enable_routing_config_event_stream ? "RUNNING" : "STOPPED"
8+
desired_state = "RUNNING"
99
kms_key_identifier = var.kms_key_arn
1010

1111
source_parameters {

infrastructure/terraform/modules/backend-api/variables.tf

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,6 @@ variable "enable_backup" {
7171
default = true
7272
}
7373

74-
variable "enable_routing_config_event_stream" {
75-
type = bool
76-
description = "Enable DynamoDB streaming from routing config table to EventBridge"
77-
default = false
78-
}
79-
8074
variable "kms_key_arn" {
8175
type = string
8276
description = "KMS Key ARN"

lambdas/event-publisher/src/__tests__/domain/event-builder.test.ts

Lines changed: 219 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,11 @@ const publishableTemplateEventRecord = (
206206
tableName: tables.templates,
207207
});
208208

209-
const expectedEvent = (status: string, type: string, dataschema: string) => ({
209+
const expectedTemplateEvent = (
210+
status: string,
211+
type: string,
212+
dataschema: string
213+
) => ({
210214
id: '7f2ae4b0-82c2-4911-9b84-8997d7f3f40d',
211215
datacontenttype: 'application/json',
212216
time: '2022-01-01T09:00:00.000Z',
@@ -241,6 +245,130 @@ const expectedEvent = (status: string, type: string, dataschema: string) => ({
241245
},
242246
});
243247

248+
const publishableRoutingConfigEventRecord = (status: string) => ({
249+
dynamodb: {
250+
SequenceNumber: '4',
251+
NewImage: {
252+
owner: {
253+
S: 'owner',
254+
},
255+
id: {
256+
S: '92b676e9-470f-4d04-ab14-965ef145e15d',
257+
},
258+
clientId: {
259+
S: 'client-id',
260+
},
261+
campaignId: {
262+
S: 'campaign-id',
263+
},
264+
createdAt: {
265+
S: '2022-01-01T09:00:00.000Z',
266+
},
267+
name: {
268+
S: 'routing-config-name',
269+
},
270+
defaultCascadeGroup: {
271+
S: 'standard',
272+
},
273+
cascade: {
274+
L: [
275+
{
276+
M: {
277+
channel: { S: 'EMAIL' },
278+
channelType: { S: 'primary' },
279+
defaultTemplateId: { S: 'bed3398c-bbe3-435d-80c1-58154d4bf7dd' },
280+
cascadeGroups: { L: [{ S: 'standard' }] },
281+
},
282+
},
283+
{
284+
M: {
285+
channel: { S: 'LETTER' },
286+
channelType: { S: 'primary' },
287+
defaultTemplateId: { S: 'd290f1ee-6c54-4b01-90e6-d701748f0851' },
288+
cascadeGroups: { L: [{ S: 'standard' }] },
289+
},
290+
},
291+
{
292+
M: {
293+
channel: { S: 'LETTER' },
294+
channelType: { S: 'primary' },
295+
defaultTemplateId: { S: '3fa85f64-5717-4562-b3fc-2c963f66afa6' },
296+
cascadeGroups: { L: [{ S: 'translations' }] },
297+
},
298+
},
299+
],
300+
},
301+
cascadeGroupOverrides: {
302+
L: [
303+
{
304+
M: {
305+
name: { S: 'translations' },
306+
language: { L: [{ S: 'fr' }] },
307+
},
308+
},
309+
],
310+
},
311+
status: {
312+
S: status,
313+
},
314+
},
315+
},
316+
eventID: '7f2ae4b0-82c2-4911-9b84-8997d7f3f40d',
317+
tableName: tables.routing,
318+
});
319+
320+
const expectedRoutingConfigEvent = (
321+
status: string,
322+
type: string,
323+
dataschema: string
324+
) => ({
325+
id: '7f2ae4b0-82c2-4911-9b84-8997d7f3f40d',
326+
datacontenttype: 'application/json',
327+
time: '2022-01-01T09:00:00.000Z',
328+
source: 'event-source',
329+
type,
330+
specversion: '1.0',
331+
dataschema,
332+
dataschemaversion: VERSION,
333+
plane: 'control',
334+
subject: '92b676e9-470f-4d04-ab14-965ef145e15d',
335+
data: {
336+
id: '92b676e9-470f-4d04-ab14-965ef145e15d',
337+
clientId: 'client-id',
338+
campaignId: 'campaign-id',
339+
createdAt: '2022-01-01T09:00:00.000Z',
340+
name: 'routing-config-name',
341+
defaultCascadeGroup: 'standard',
342+
cascade: [
343+
{
344+
channel: 'EMAIL',
345+
channelType: 'primary',
346+
cascadeGroups: ['standard'],
347+
defaultTemplateId: 'bed3398c-bbe3-435d-80c1-58154d4bf7dd',
348+
},
349+
{
350+
channel: 'LETTER',
351+
channelType: 'primary',
352+
cascadeGroups: ['standard'],
353+
defaultTemplateId: 'd290f1ee-6c54-4b01-90e6-d701748f0851',
354+
},
355+
{
356+
channel: 'LETTER',
357+
channelType: 'primary',
358+
cascadeGroups: ['translations'],
359+
defaultTemplateId: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
360+
},
361+
],
362+
cascadeGroupOverrides: [
363+
{
364+
name: 'translations',
365+
language: ['fr'],
366+
},
367+
],
368+
status,
369+
},
370+
});
371+
244372
test('errors on unrecognised event table source', () => {
245373
const invalidpublishableTemplateEventRecord = {
246374
...publishableTemplateEventRecord('SUBMITTED'),
@@ -290,7 +418,7 @@ describe('template events', () => {
290418
);
291419

292420
expect(event).toEqual(
293-
expectedEvent(
421+
expectedTemplateEvent(
294422
'SUBMITTED',
295423
'uk.nhs.notify.template-management.TemplateCompleted.v1',
296424
'https://notify.nhs.uk/events/schemas/TemplateCompleted/v1.json'
@@ -304,7 +432,7 @@ describe('template events', () => {
304432
);
305433

306434
expect(event).toEqual(
307-
expectedEvent(
435+
expectedTemplateEvent(
308436
'PROOF_AVAILABLE',
309437
'uk.nhs.notify.template-management.TemplateDrafted.v1',
310438
'https://notify.nhs.uk/events/schemas/TemplateDrafted/v1.json'
@@ -327,7 +455,7 @@ describe('template events', () => {
327455
const event = eventBuilder.buildEvent(noOldImage);
328456

329457
expect(event).toEqual(
330-
expectedEvent(
458+
expectedTemplateEvent(
331459
'SUBMITTED',
332460
'uk.nhs.notify.template-management.TemplateCompleted.v1',
333461
'https://notify.nhs.uk/events/schemas/TemplateCompleted/v1.json'
@@ -341,7 +469,7 @@ describe('template events', () => {
341469
);
342470

343471
expect(event).toEqual(
344-
expectedEvent(
472+
expectedTemplateEvent(
345473
'DELETED',
346474
'uk.nhs.notify.template-management.TemplateDeleted.v1',
347475
'https://notify.nhs.uk/events/schemas/TemplateDeleted/v1.json'
@@ -361,7 +489,7 @@ describe('template events', () => {
361489
});
362490

363491
test('does not build template event on hard delete', () => {
364-
const hardDeletepublishableTemplateEventRecord = {
492+
const hardDeletePublishableTemplateEventRecord = {
365493
...publishableTemplateEventRecord('SUBMITTED'),
366494
dynamodb: {
367495
SequenceNumber: '4',
@@ -370,24 +498,100 @@ describe('template events', () => {
370498
};
371499

372500
const event = eventBuilder.buildEvent(
373-
hardDeletepublishableTemplateEventRecord
501+
hardDeletePublishableTemplateEventRecord
374502
);
375503

376504
expect(event).toEqual(undefined);
377505
});
378506
});
379507

380508
describe('routing config events', () => {
381-
test('should return undefined when table source is routing config table', () => {
382-
const event = eventBuilder.buildEvent({
509+
test('errors on output schema validation failure', () => {
510+
const valid = publishableRoutingConfigEventRecord('DRAFT');
511+
512+
const invalidDomainEventRecord = {
513+
...valid,
514+
dynamodb: {
515+
...valid.dynamodb,
516+
NewImage: {
517+
...valid.dynamodb.NewImage,
518+
cascade: {
519+
L: [
520+
{
521+
M: {
522+
channel: { S: 'EMAIL' },
523+
channelType: { S: 'primary' },
524+
defaultTemplateId: { S: null },
525+
cascadeGroups: { L: [{ S: 'standard' }] },
526+
},
527+
},
528+
],
529+
},
530+
},
531+
},
532+
};
533+
534+
const event = eventBuilder.buildEvent(
535+
invalidDomainEventRecord as unknown as PublishableEventRecord
536+
);
537+
538+
expect(event).toEqual(undefined);
539+
});
540+
541+
test('builds routing config completed event', () => {
542+
const event = eventBuilder.buildEvent(
543+
publishableRoutingConfigEventRecord('COMPLETED')
544+
);
545+
546+
expect(event).toEqual(
547+
expectedRoutingConfigEvent(
548+
'COMPLETED',
549+
'uk.nhs.notify.template-management.RoutingConfigCompleted.v1',
550+
'https://notify.nhs.uk/events/schemas/RoutingConfigCompleted/v1.json'
551+
)
552+
);
553+
});
554+
555+
test('builds routing config drafted event', () => {
556+
const event = eventBuilder.buildEvent(
557+
publishableRoutingConfigEventRecord('DRAFT')
558+
);
559+
560+
expect(event).toEqual(
561+
expectedRoutingConfigEvent(
562+
'DRAFT',
563+
'uk.nhs.notify.template-management.RoutingConfigDrafted.v1',
564+
'https://notify.nhs.uk/events/schemas/RoutingConfigDrafted/v1.json'
565+
)
566+
);
567+
});
568+
569+
test('builds routing config deleted event', () => {
570+
const event = eventBuilder.buildEvent(
571+
publishableRoutingConfigEventRecord('DELETED')
572+
);
573+
574+
expect(event).toEqual(
575+
expectedRoutingConfigEvent(
576+
'DELETED',
577+
'uk.nhs.notify.template-management.RoutingConfigDeleted.v1',
578+
'https://notify.nhs.uk/events/schemas/RoutingConfigDeleted/v1.json'
579+
)
580+
);
581+
});
582+
583+
test('does not build routing config event on hard delete', () => {
584+
const hardDeletePublishableRoutingConfigEventRecord = {
585+
...publishableRoutingConfigEventRecord('DRAFT'),
383586
dynamodb: {
384-
SequenceNumber: '1',
385-
NewImage: {},
386-
OldImage: {},
587+
SequenceNumber: '4',
588+
NewImage: undefined,
387589
},
388-
eventID: 'cf1344e0-fd57-426a-860a-3efc9d2b1977',
389-
tableName: tables.routing,
390-
});
590+
};
591+
592+
const event = eventBuilder.buildEvent(
593+
hardDeletePublishableRoutingConfigEventRecord
594+
);
391595

392596
expect(event).toEqual(undefined);
393597
});

0 commit comments

Comments
 (0)