Skip to content
Merged
Show file tree
Hide file tree
Changes from 164 commits
Commits
Show all changes
168 commits
Select commit Hold shift + click to select a range
76085aa
Add a notifications table definition. PK prescription ID, GSI NHS number
wildjames Apr 15, 2025
2a6a99c
Make capitalisation consistent
wildjames Apr 15, 2025
b26a0e9
Create a blank notifications lambda. Doesn't have a deployment defini…
wildjames Apr 15, 2025
36fda3d
Add nhs notify lambda to main lambda SAM template
wildjames Apr 15, 2025
5787256
Add scheduler, and update lambda handler
wildjames Apr 15, 2025
0e44d81
Merge branch 'main' into aea-5199-setup-notifications-lambda
wildjames Apr 15, 2025
a4e2c9a
Trigger PR title check again
wildjames Apr 15, 2025
6e645fa
Add mock event bridge type. Update dummy unit test
wildjames Apr 15, 2025
186ffef
Merge branch 'main' into aea-5199-setup-notifications-lambda
wildjames Apr 15, 2025
f9f3391
Refactor to not need permissions, mirroring cert checker lambda
wildjames Apr 15, 2025
61c72dc
Merge branch 'aea-5199-setup-notifications-lambda' of github.com:NHSD…
wildjames Apr 15, 2025
586aa34
typo in the version
wildjames Apr 16, 2025
ef9750d
Fix indentation
wildjames Apr 16, 2025
6c4bf0a
whitespace changes
wildjames Apr 16, 2025
2112fc2
using the wrong handler function
wildjames Apr 16, 2025
771de6d
Add SQS queue definition
wildjames Apr 16, 2025
6d5cfbe
Add messaging stack to main yaml
wildjames Apr 16, 2025
fba51c8
Fix import
wildjames Apr 16, 2025
1bffcb3
Retention period too long :(
wildjames Apr 16, 2025
be5e9d9
Empty function in PSU that will push data to SQS
wildjames Apr 16, 2025
f1a154d
Tests seembroken, but wrote an sqs client
wildjames Apr 16, 2025
b994b2b
fix test
wildjames Apr 17, 2025
d526e61
Add send message policy to the update prescription lambda
wildjames Apr 17, 2025
efbc621
Reset env between tests
wildjames Apr 17, 2025
ddbe840
Is it case sensitive?
wildjames Apr 17, 2025
328e1e0
Move permission definition
wildjames Apr 17, 2025
1cec26a
Merge branch 'main' into aea-5199-setup-notifications-lambda
wildjames Apr 17, 2025
f6c7829
add SQS policy to the nofity lambda
wildjames Apr 17, 2025
d4ac39a
Fix typo!
wildjames Apr 17, 2025
4b79e32
Forgot to specify arn export. Also, use stackname parameter
wildjames Apr 17, 2025
aa3ca5a
Nope, dont need the .Arn
wildjames Apr 17, 2025
544238a
Permissions for dealing with our customer-managed KMS
wildjames Apr 22, 2025
ff7be05
Add logic to catch failures of SQS
wildjames Apr 22, 2025
83de1b2
Log the message IDs that are getting pushed when debug is enabled
wildjames Apr 22, 2025
d0bd55b
Add missing permissions
wildjames Apr 22, 2025
367ee4d
Trigger build
wildjames Apr 22, 2025
e129789
Merge branch 'main' into aea-5199-setup-notifications-lambda
wildjames Apr 22, 2025
9261f45
Use a dedicated KMS - permissions are being difficult
wildjames Apr 22, 2025
6dc7c61
Forgot to add a policy
wildjames Apr 22, 2025
7a8b4e5
Merge branch 'main' into aea-5199-setup-notifications-lambda
wildjames Apr 22, 2025
7bfc023
Skip quality checks
wildjames Apr 22, 2025
b56af03
Merge branch 'aea-5199-setup-notifications-lambda' of github.com:NHSD…
wildjames Apr 22, 2025
d6d58cc
Make the notify lambda pull messages from SQS, and log them
wildjames Apr 22, 2025
8216f25
Update log message
wildjames Apr 22, 2025
6a2d224
Set up the consumer to be able to communicate with the table. Alos lo…
wildjames Apr 22, 2025
77821bc
Pass in static table name as a parameter
wildjames Apr 22, 2025
7c91533
Merge branch 'main' into aea-5199-setup-notifications-lambda
wildjames Apr 22, 2025
e39958a
Expand test coverage
wildjames Apr 22, 2025
61a897e
Merge branch 'aea-5199-setup-notifications-lambda' of github.com:NHSD…
wildjames Apr 22, 2025
adb055f
Minimal nhsnotifylambda dynamo unit test
wildjames Apr 23, 2025
804c06b
Expand test coverage
wildjames Apr 23, 2025
eb78c25
Start tests for the drainQueue functiton
wildjames Apr 23, 2025
35d8a92
Expand test coverage
wildjames Apr 23, 2025
9a55102
Merge branch 'main' into aea-5199-setup-notifications-lambda
wildjames Apr 23, 2025
ea0c3fe
Make a more official test for the handler
wildjames Apr 23, 2025
5da248d
Expand test coverage
wildjames Apr 23, 2025
90ccd53
Update type
wildjames Apr 23, 2025
338a135
Address some sonar things
wildjames Apr 23, 2025
17d6566
Move dataitem to a common types package
wildjames Apr 23, 2025
f27d70f
Minor tweaks from self-review
wildjames Apr 23, 2025
9cfb289
Use NHS number as the message ID
wildjames Apr 24, 2025
f0d35c5
Salt the nhs number and use it as the message ID.
wildjames Apr 24, 2025
6a77bde
Update log message
wildjames Apr 24, 2025
53abd70
Update tests to reflect logging change
wildjames Apr 24, 2025
440ac9e
Merge branch 'main' into aea-5274-deduplicate-notification-queue-by-n…
wildjames Apr 24, 2025
15ba4d2
Correctly grab request ID
wildjames Apr 24, 2025
501a5fd
Merge branch 'main' into aea-5199-setup-notifications-lambda
wildjames Apr 24, 2025
ba2d587
Merge branch 'aea-5199-setup-notifications-lambda' into aea-5274-dedu…
wildjames Apr 24, 2025
dd81780
Update log
wildjames Apr 24, 2025
0043ed4
Merge branch 'aea-5199-setup-notifications-lambda' into aea-5274-dedu…
wildjames Apr 24, 2025
00178b2
Remove log messages
wildjames Apr 24, 2025
67fb985
Use a FIFO queue, since it has deduplication IDs
wildjames Apr 24, 2025
989bb82
Minor adjustment to the failure catch logic to handle some elements o…
wildjames Apr 24, 2025
7fd8396
lengthen visibility timeout
wildjames Apr 24, 2025
1cf948a
Merge branch 'aea-5199-setup-notifications-lambda' into aea-5274-dedu…
wildjames Apr 24, 2025
178fc01
Update to deduplicate on both nhs number and ods code
wildjames Apr 25, 2025
9d9da72
Update test
wildjames Apr 25, 2025
21cf5f0
Resolve package lock conflict
wildjames Apr 28, 2025
5912e98
Merge branch 'aea-5199-setup-notifications-lambda' into aea-5274-dedu…
wildjames Apr 28, 2025
886c198
Rename fuinction. Comments
wildjames Apr 28, 2025
6b9dcbc
Resolve package lock conflict
wildjames Apr 28, 2025
d710874
Merge branch 'aea-5199-setup-notifications-lambda' into aea-5274-dedu…
wildjames Apr 28, 2025
f5a77bf
Create a whitelist checking function
wildjames Apr 28, 2025
c90555c
Update language usage
wildjames Apr 28, 2025
90e3e8e
Update language
wildjames Apr 28, 2025
21a1236
Update logging
wildjames Apr 28, 2025
de8033a
Update tests
wildjames Apr 28, 2025
839375f
Merge branch 'main' into aea-5274-deduplicate-notification-queue-by-n…
wildjames Apr 28, 2025
d950354
Move the deletion logic out to occur AFTER processing. Update tests t…
wildjames Apr 28, 2025
1c949b7
Update tests
wildjames Apr 28, 2025
0227196
Revert a line
wildjames Apr 28, 2025
7440946
Update mock import
wildjames Apr 28, 2025
73edbdc
Expand tests
wildjames Apr 28, 2025
2719d4f
Set the sqs salt value to some randomly generated string at deployment
wildjames Apr 29, 2025
8d10626
Merge branch 'main' into aea-5202-allowed-and-blocked-sites-and-systems
wildjames Apr 29, 2025
a22c919
Merge branch 'aea-5274-deduplicate-notification-queue-by-nhsnumber' i…
wildjames Apr 29, 2025
28adaa5
Define the enabled and disabled sites in a new Paramters template
wildjames Apr 29, 2025
bff40c5
Allow the block and enable lists to differ between prod and non-prod …
wildjames Apr 29, 2025
50e7fe5
Update tests
wildjames Apr 29, 2025
f08adba
Merge branch 'main' into aea-5202-allowed-and-blocked-sites-and-systems
wildjames Apr 29, 2025
888a1c8
Merge branch 'main' into aea-5202-allowed-and-blocked-sites-and-systems
wildjames Apr 29, 2025
b8b08a8
Fix typo
wildjames Apr 29, 2025
23c53d7
Merge branch 'aea-5202-allowed-and-blocked-sites-and-systems' of gith…
wildjames Apr 29, 2025
5939e0f
Refactor params a bit
wildjames Apr 29, 2025
e608771
Roll back a bit to find the source of the error
wildjames Apr 29, 2025
e3ef147
Comment out parameter
wildjames Apr 30, 2025
aa2a8d5
Make fallback salt a const
wildjames Apr 30, 2025
022e66f
Merge main into aea-5202-allowed-and-blocked-sites-and-systems
wildjames Apr 30, 2025
d015f13
last deployment worked. Try passing in parameters
wildjames Apr 30, 2025
b1574b1
Join array back into a single string
wildjames Apr 30, 2025
6bcd216
pass in the name and fetch the parameter values from ssm in the code
wildjames Apr 30, 2025
d9fcfce
Forgot to await
wildjames Apr 30, 2025
d0cea20
Revert change
wildjames Apr 30, 2025
17e46ea
Add logging message
wildjames Apr 30, 2025
ad32e9b
Remove await
wildjames Apr 30, 2025
055e4a0
Revert change to deploy workflow
wildjames Apr 30, 2025
d3d88f4
Merge branch 'main' into aea-5202-allowed-and-blocked-sites-and-systems
wildjames Apr 30, 2025
c0f0c50
Merge branch 'main' into aea-5202-allowed-and-blocked-sites-and-systems
wildjames Apr 30, 2025
358e203
Test fallback salt value
wildjames Apr 30, 2025
6663bac
Merge branch 'aea-5202-allowed-and-blocked-sites-and-systems' of gith…
wildjames Apr 30, 2025
3e5feb7
Minor tweak to tests
wildjames Apr 30, 2025
5c53015
Case insensitivity test!
wildjames Apr 30, 2025
2c97580
Exploratory work
wildjames May 1, 2025
73d8784
bypass quality checks
wildjames May 1, 2025
f982d2a
Checking that there's not data I think there is
wildjames May 1, 2025
f3bfcf6
Reintroduce code to push up data to dynamo
wildjames May 1, 2025
59c0977
use a string for the date instead of raw Date object
wildjames May 2, 2025
7f83dbd
Add a log message
wildjames May 2, 2025
4251aa8
Add log message
wildjames May 2, 2025
d2cffd1
Update test
wildjames May 2, 2025
d5bf6fb
re-enable PiTR
wildjames May 2, 2025
8e986e2
Fix me using the wrong table reference in the template
wildjames May 2, 2025
95f99fd
Fix expiry time calculation. Move delta to constant
wildjames May 2, 2025
d1bc62b
Batch the delete operation properly. Add request ID to the SQS messag…
wildjames May 2, 2025
f18d438
Add a log message
wildjames May 2, 2025
d5b1aa8
Update and expand tests
wildjames May 2, 2025
c1bd96c
Merge branch 'main' into aea-5280-push-notify-data-to-dynamo
wildjames May 2, 2025
430ec69
Add another unit test.
wildjames May 2, 2025
890bcdd
Reenable quality checks
wildjames May 2, 2025
f3eee15
Add another test
wildjames May 2, 2025
b07f849
Resolve merge conflict
wildjames May 2, 2025
bd895e8
Add a log message
wildjames May 2, 2025
eebc9c0
Add a log message
wildjames May 2, 2025
463348a
Alter comments
wildjames May 2, 2025
dfcc12c
Merge branch 'main' into aea-5280-push-notify-data-to-dynamo
wildjames May 6, 2025
e73b723
Change record key to be more explicit
wildjames May 6, 2025
8ce03dc
Try some explicit jest config to get coverage picked up
wildjames May 6, 2025
ba328eb
Revert last commit
wildjames May 6, 2025
a24c366
Merge branch 'main' into aea-5280-push-notify-data-to-dynamo
wildjames May 6, 2025
506fb14
Try updating sonar coverage defintion
wildjames May 6, 2025
04d90be
Address sonar issues
wildjames May 6, 2025
e7bbf5c
Remove invalid sonar config
wildjames May 6, 2025
e17395e
Update jest config
wildjames May 6, 2025
3194e5f
Write a function that checks the cooldown. Also filter incoming messa…
wildjames May 6, 2025
18564fc
Resolve sonar issue
wildjames May 6, 2025
686ee53
Merge branch 'aea-5280-push-notify-data-to-dynamo' into aea-5206-chec…
wildjames May 6, 2025
d047e98
Expand test coverage
wildjames May 6, 2025
7dadd02
Unit tests for new function
wildjames May 6, 2025
02e9717
Update logging
wildjames May 6, 2025
470d565
Merge branch 'aea-5280-push-notify-data-to-dynamo' into aea-5206-chec…
wildjames May 6, 2025
243dcb0
Update test
wildjames May 6, 2025
eea2c85
Update test
wildjames May 6, 2025
677f128
Merge branch 'aea-5280-push-notify-data-to-dynamo' into aea-5206-chec…
wildjames May 6, 2025
88b49f5
Merge branch 'main' into aea-5206-check-cooldown-when-sending
wildjames May 7, 2025
61a9a8d
Merge main
wildjames May 9, 2025
75f57a3
Merge branch 'main' into aea-5206-check-cooldown-when-sending
wildjames May 9, 2025
6c5e7da
Merge branch 'main' into aea-5206-check-cooldown-when-sending
wildjames May 9, 2025
cf226d0
Merge branch 'main' into aea-5206-check-cooldown-when-sending
wildjames May 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vscode/eps-prescription-status-update-api.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"Codeable",
"codeinline",
"codesystem",
"Cooldown",
"cpsu",
"dbaeumer",
"devcontainer",
Expand Down Expand Up @@ -128,6 +129,7 @@
"sourcetype",
"timonwong",
"Truststore",
"Upserted",
"URID",
"URPID",
"uuidv4",
Expand Down
77 changes: 7 additions & 70 deletions SAMtemplates/tables/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ Resources:
- kms:Encrypt
- kms:ReEncrypt*
- kms:Decrypt
Resource: !GetAtt PrescriptionStatusUpdatesKMSKey.Arn
Resource: !GetAtt PrescriptionNotificationStateKMSKey.Arn

PrescriptionNotificationStateTable:
Type: AWS::DynamoDB::Table
Expand All @@ -426,29 +426,19 @@ Resources:
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: true
AttributeDefinitions:
- AttributeName: PrescriptionID
AttributeType: S
- AttributeName: NHSNumber
AttributeType: S
- AttributeName: ODSCode
AttributeType: S
KeySchema:
- AttributeName: PrescriptionID
KeyType: HASH
- AttributeName: NHSNumber
KeyType: HASH # Partition key
- AttributeName: ODSCode
KeyType: RANGE # Sort key
BillingMode: !If
- EnableDynamoDBAutoScalingCondition
- PROVISIONED
- PAY_PER_REQUEST
GlobalSecondaryIndexes:
- IndexName: NotificationNHSNumberIndex
KeySchema:
- AttributeName: NHSNumber
KeyType: HASH
Projection:
ProjectionType: ALL
ProvisionedThroughput: !If
- EnableDynamoDBAutoScalingCondition
- ReadCapacityUnits: 1
WriteCapacityUnits: !Ref MinWritePrescriptionNotificationStateCapacity
- !Ref "AWS::NoValue"
ProvisionedThroughput: !If
- EnableDynamoDBAutoScalingCondition
- ReadCapacityUnits: 1
Expand Down Expand Up @@ -524,59 +514,6 @@ Resources:
PredefinedMetricSpecification:
PredefinedMetricType: DynamoDBReadCapacityUtilization

# Scaling for the indexes
NotificationNHSNumberIndexScalingWriteTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn: PrescriptionNotificationStateTable
Condition: EnableDynamoDBAutoScalingCondition
Properties:
MinCapacity: !Ref MinWritePrescriptionNotificationStateCapacity
MaxCapacity: !Ref MaxWritePrescriptionNotificationStateCapacity
ResourceId: !Sub table/${PrescriptionNotificationStateTable}/index/NotificationNHSNumberIndex
RoleARN: !GetAtt DynamoDbScalingRole.Arn
ScalableDimension: "dynamodb:index:WriteCapacityUnits"
ServiceNamespace: dynamodb

NotificationNHSNumberIndexScalingWritePolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Condition: EnableDynamoDBAutoScalingCondition
Properties:
PolicyName: NotificationNHSNumberIndexScalingWritePolicy
PolicyType: TargetTrackingScaling
ScalingTargetId: !Ref NotificationNHSNumberIndexScalingWriteTarget
TargetTrackingScalingPolicyConfiguration:
TargetValue: 50
ScaleInCooldown: 600
ScaleOutCooldown: 0
PredefinedMetricSpecification:
PredefinedMetricType: DynamoDBWriteCapacityUtilization

NotificationNHSNumberIndexScalingReadTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn: PrescriptionNotificationStateTable
Condition: EnableDynamoDBAutoScalingCondition
Properties:
MinCapacity: 1
MaxCapacity: 100
ResourceId: !Sub table/${PrescriptionNotificationStateTable}/index/NotificationNHSNumberIndex
RoleARN: !GetAtt DynamoDbScalingRole.Arn
ScalableDimension: "dynamodb:index:ReadCapacityUnits"
ServiceNamespace: dynamodb

NotificationNHSNumberIndexScalingReadPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Condition: EnableDynamoDBAutoScalingCondition
Properties:
PolicyName: NotificationNHSNumberIndexReadScalingPolicy
PolicyType: TargetTrackingScaling
ScalingTargetId: !Ref NotificationNHSNumberIndexScalingReadTarget
TargetTrackingScalingPolicyConfiguration:
TargetValue: 70
ScaleInCooldown: 60
ScaleOutCooldown: 60
PredefinedMetricSpecification:
PredefinedMetricType: DynamoDBReadCapacityUtilization

Outputs:
PrescriptionStatusUpdatesTableName:
Description: PrescriptionStatusUpdates table name
Expand Down
11 changes: 9 additions & 2 deletions packages/nhsNotifyLambda/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ import type {JestConfigWithTsJest} from "ts-jest"

const jestConfig: JestConfigWithTsJest = {
...defaultConfig,
"rootDir": "./",
setupFiles: ["<rootDir>/.jest/setEnvVars.js"]
rootDir: "./",
setupFiles: ["<rootDir>/.jest/setEnvVars.js"],
coveragePathIgnorePatterns: ["<rootDir>/tests/"],
coverageReporters: [
"clover",
"json",
"text",
["lcov", {projectRoot: "../../"}]
]
}

export default jestConfig
77 changes: 54 additions & 23 deletions packages/nhsNotifyLambda/src/nhsNotifyLambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ import middy from "@middy/core"
import inputOutputLogger from "@middy/input-output-logger"
import errorHandler from "@nhs/fhir-middy-error-handler"

import {PSUDataItem} from "@PrescriptionStatusUpdate_common/commonTypes"
import {clearCompletedSQSMessages, drainQueue} from "./utils"
import {
addPrescriptionMessagesToNotificationStateStore,
checkCooldownForUpdate,
clearCompletedSQSMessages,
drainQueue,
PSUDataItemMessage
} from "./utils"

const logger = new Logger({serviceName: "nhsNotify"})

Expand All @@ -21,7 +26,8 @@ export const lambdaHandler = async (event: EventBridgeEvent<string, string>): Pr

logger.info("NHS Notify lambda triggered by scheduler", {event})

let messages
let messages: Array<PSUDataItemMessage>
let processed: Array<PSUDataItemMessage>
try {
messages = await drainQueue(logger, 100)

Expand All @@ -30,38 +36,63 @@ export const lambdaHandler = async (event: EventBridgeEvent<string, string>): Pr
return
}

// parse & log each PSUDataItem as a placeholder for now.
const items = messages.map((m) => {
try {
return JSON.parse(m.Body!) as PSUDataItem
} catch (err) {
logger.error("Failed to parse message body", {body: m.Body, error: err})
return null
}
}).filter((i): i is PSUDataItem => i !== null)
// Filter messages by checkCooldownForUpdate. This is done in two stages so we can check in parallel
const eligibility = await Promise.all(
messages.map(async (m) => ({
message: m,
allowed: await checkCooldownForUpdate(logger, m.PSUDataItem)
}))
)
const toProcess = eligibility
.filter((e) => e.allowed)
.map((e) => e.message)

const toNotify = items.map((m) => ({
RequestID: m.RequestID,
TaskId: m.TaskID,
Message: "Notification Required"
}))
// Log the results of checking the cooldown
const suppressedCount = messages.length - toProcess.length
if (toProcess.length === 0) {
logger.info("All messages suppressed by cooldown; nothing to notify",
{
suppressedCount,
totalFetched: messages.length
})
return
} else if (suppressedCount > 0) {
logger.info(`Suppressed ${suppressedCount} messages due to cooldown`,
{
suppressedCount,
totalFetched: messages.length
}
)
}

// Just for diagnostics for now
const toNotify = toProcess
.map((m) => ({
RequestID: m.PSUDataItem.RequestID,
TaskId: m.PSUDataItem.TaskID,
Message: "Notification Required"
}))
logger.info("Fetched prescription notification messages", {count: toNotify.length, toNotify})

// TODO: Notifications logic will be done here.
// - query PrescriptionNotificationState
// - process prescriptions, build NHS notify payload
// - Make NHS notify request
// Don't forget to make appropriate logs!
// TODO: Notifications request will be done here.
processed = toProcess

} catch (err) {
logger.error("Error while draining SQS queue", {error: err})
throw err
}

try {
await addPrescriptionMessagesToNotificationStateStore(logger, processed)
} catch (err) {
logger.error("Error while pushing data to the PSU notification state data store", {err})
throw err
}

// By waiting until a message is successfully processed before deleting it from SQS,
// failed messages will eventually be retried by subsequent notify consumers.
try {
await clearCompletedSQSMessages(messages, logger)
await clearCompletedSQSMessages(logger, processed)
} catch (err) {
logger.error("Error while deleting successfully processed messages from SQS", {error: err})
throw err
Expand Down
Loading