Skip to content

Commit e33bc72

Browse files
Merge pull request #1112 from NHSDigital/NRL-1666-point-perftest-at-baseline-table
NRL-1866 Point the perftest environment at the baseline table to cond…
2 parents 2e72153 + c17feb2 commit e33bc72

File tree

11 files changed

+66
-94
lines changed

11 files changed

+66
-94
lines changed

scripts/seed_nft_tables.py

Lines changed: 6 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,20 @@
1111
# import json
1212
import numpy as np
1313

14-
from nrlf.consumer.fhir.r4.model import DocumentReference
1514
from nrlf.core.constants import (
1615
CATEGORY_ATTRIBUTES,
1716
SNOMED_SYSTEM_URL,
1817
TYPE_ATTRIBUTES,
1918
TYPE_CATEGORIES,
20-
Categories,
21-
PointerTypes,
2219
)
2320
from nrlf.core.dynamodb.model import DocumentPointer
2421
from nrlf.core.logger import logger
2522
from nrlf.tests.data import load_document_reference
23+
from tests.performance.seed_data_constants import ( # DEFAULT_COUNT_DISTRIBUTIONS,
24+
CHECKSUM_WEIGHTS,
25+
DEFAULT_CUSTODIAN_DISTRIBUTIONS,
26+
DEFAULT_TYPE_DISTRIBUTIONS,
27+
)
2628

2729
dynamodb = boto3.client("dynamodb")
2830
resource = boto3.resource("dynamodb")
@@ -31,69 +33,6 @@
3133

3234
DOC_REF_TEMPLATE = load_document_reference("NFT-template")
3335

34-
CHECKSUM_WEIGHTS = [i for i in range(10, 1, -1)]
35-
36-
# These are based on the Nov 7th 2025 pointer stats report
37-
DEFAULT_TYPE_DISTRIBUTIONS = {
38-
"736253002": 65, # mental health crisis plan
39-
"1382601000000107": 5, # respect form
40-
"887701000000100": 15, # emergency healthcare plan
41-
"861421000000109": 5, # eol care coordination summary
42-
"735324008": 5, # treatment escalation plan
43-
"824321000000109": 5, # summary record
44-
}
45-
46-
DEFAULT_CUSTODIAN_DISTRIBUTIONS = {
47-
"736253002": {
48-
"TRPG": 9,
49-
"TRHA": 1,
50-
"TRRE": 20,
51-
"TRAT": 10,
52-
"TWR4": 4,
53-
"TRKL": 9,
54-
"TRW1": 5,
55-
"TRH5": 1,
56-
"TRP7": 13,
57-
"TRWK": 8,
58-
"TRQY": 3,
59-
"TRV5": 3,
60-
"TRJ8": 2,
61-
"TRXA": 4,
62-
"T11X": 1,
63-
"TG6V": 2,
64-
},
65-
"1382601000000107": {"T8GX8": 3, "TQUY": 2}, # respect form
66-
"887701000000100": {
67-
"TV1": 1,
68-
"TV2": 2,
69-
"TV3": 1,
70-
"TV4": 1,
71-
"TV5": 3,
72-
"TV6": 1,
73-
}, # emergency healthcare plan
74-
"861421000000109": {
75-
"TV1": 2,
76-
"TV2": 2,
77-
"TV3": 1,
78-
"TV4": 1,
79-
"TV5": 3,
80-
"TV6": 1,
81-
}, # eol care coordination summary
82-
"735324008": {
83-
"TV1": 1,
84-
"TV2": 1,
85-
"TV3": 1,
86-
"TV4": 2,
87-
"TV5": 2,
88-
"TV6": 1,
89-
}, # treatment escalation plan
90-
"824321000000109": {
91-
"TRXT": 1,
92-
}, # summary record currently has only one supplier
93-
}
94-
95-
DEFAULT_COUNT_DISTRIBUTIONS = {"1": 91, "2": 8, "3": 1}
96-
9736

9837
class TestNhsNumbersIterator:
9938
def __iter__(self):
@@ -262,7 +201,7 @@ def _get_pointer_count_poisson_distributions(
262201

263202

264203
def _set_up_custodian_iterators(
265-
custodian_dists: dict[str, dict[str, int]]
204+
custodian_dists: dict[str, dict[str, int]],
266205
) -> dict[str, Iterator[str]]:
267206
custodian_iters: dict[str, Iterator[str]] = {}
268207
for pointer_type in custodian_dists:

terraform/account-wide-infrastructure/modules/pointers-table/vars.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ variable "kms_deletion_window_in_days" {
2323

2424
variable "enable_backups" {
2525
type = bool
26-
description = "Enable AwS cloud backup"
26+
description = "Enable AWS cloud backup"
2727
default = false
2828
}

terraform/account-wide-infrastructure/test/dynamodb__pointers-table.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ module "ref-pointers-table" {
3333

3434
module "perftest-pointers-table" {
3535
source = "../modules/pointers-table"
36-
name_prefix = "nhsd-nrlf--perftest"
36+
name_prefix = "nhsd-nrlf--perftest-baseline"
3737
}

terraform/infrastructure/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ replacing `{ENV_NAME}` with the environment name (e.g. `dev`, `qa`, `qa-sandbox`
116116

117117
To tear down the infrastructure, you need to use Terraform to destroy the resources in your Terraform workspace.
118118

119+
First `make build-artifacts`. Then assume management and run `make get-s3-perms ENV={ENV_NAME}` in the project root.
120+
119121
To teardown the infrastructure, do the following:
120122

121123
```

terraform/infrastructure/etc/perftest.tfvars

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
account_name = "perftest"
22
aws_account_name = "test"
33

4-
dynamodb_pointers_table_prefix = "nhsd-nrlf--perftest"
4+
dynamodb_pointers_table_prefix = "nhsd-nrlf--perftest-baseline"
55

66
domain = "perftest.record-locator.national.nhs.uk"
77
public_domain = "perftest.api.service.nhs.uk"

tests/performance/README.md

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,44 @@
11
# Performance Testing
22

3-
some high level context short
3+
We have performance tests which give us a benchmark of how NRLF performs under load for consumers and producers.
44

5-
## Run perf tests
5+
## Run performance tests
66

77
### Prep the environment
88

99
Perf tests are generally conducted in the perftest env. There's a selection of tables in the perftest env representing different pointer volume scenarios e.g. perftest-baseline vs perftest-1million (todo: update with real names!).
1010

11-
To reset this table to the expected state for perftests, restore the table from a backup.
11+
#### Point perftest at a different pointers table
1212

13-
In the steps below, make sure the table name is the table your environment is pointing at. You might need to redeploy NRLF lambdas to point at the desired table.
13+
We (will) have multiple tables representing different states of NRLF in the future e.g. all patients receiving an IPS (International Patient Summary), onboarding particular high-volume suppliers.
14+
15+
In order to run performance tests to get figures for these different states, we can point the perftest environment at one of these tables.
16+
17+
Currently, this requires tearing down the existing environment and restoring from scratch:
18+
19+
1. Follow instructions in terraform/infrastructure/readme.md to tear down the perf test environment.
20+
- Do **not** tear down shared account-wide infrastructure
21+
2. Update `perftest-pointers-table.name_prefix` in `terraform/account-wide-infrastructure/test/dynamodb__pointers-table.tf` to be the table name you want, minus "-pointers-table"
22+
- e.g. to use the baseline table `nhsd-nrlf--perftest-baseline-pointers-table`, set `name_prefix = "nhsd-nrlf--perftest-baseline"`
23+
3. Update `dynamodb_pointers_table_prefix` in `terraform/infrastructure/etc/perftest.tfvars` same as above.
24+
- e.g. to use the baseline table `dynamodb_pointers_table_prefix = "nhsd-nrlf--perftest-baseline"`
25+
4. Commit changes to a branch & push
26+
5. Run the [Deploy Account-wide infrastructure](https://github.com/NHSDigital/NRLF/actions/workflows/deploy-account-wide-infra.yml) workflow against your branch & `account-test`.
27+
- If you get a terraform failure like "tried to create table but it already exists", you will need to do some fanangaling:
28+
1. make sure there is a backup of your chosen table or create one if not. In the AWS console: dynamodb > tables > your perftest table > backups > create backup > Create on-demand backup > leave all settings as defaults > create backup. This might take up to an hour to complete.
29+
2. once backed up, delete your table. In the AWS console: dynamodb > tables > your perftest table > actions > delete table
30+
3. Rerun the Deploy Account-wide infrastructure action.
31+
4. Terraform will create an empty table with the correct name & (most importantly!) read/write IAM policies.
32+
5. Delete the empty table created by terraform and restore from the backup, specifying the same table name you've defined in code.
33+
6. Run the [Persistent Environment Deploy](https://github.com/NHSDigital/NRLF/actions/workflows/persistent-environment.yml) workflow against your branch & `perftest` to restore the environment with lambdas pointed at your chosen table.
34+
7. You can check this has been successful by checking the table name in the lambdas.
35+
- In the AWS console: Lambda > functions > pick any perftest-1 lambda > Configuration > Environment variables > `TABLE_NAME` should be your desired pointer table e.g. `nhsd-nrlf--perftest-baseline-pointers-table`
36+
37+
If you've followed these steps, you will also need to [generate permissions](#generate-permissions) as the organisation permissions will have been lost when the environment was torn down.
1438

1539
### Prepare to run tests
1640

17-
#### Pull certs for env
41+
#### Pull certs for perftest
1842

1943
```sh
2044
assume management
@@ -26,19 +50,21 @@ make truststore-pull-all ENV=perftest
2650
You will need to generate pointer permissions the first time performance tests are run in an environment e.g. if the perftest environment is destroyed & recreated.
2751

2852
```sh
29-
make generate permissions # makes a bunch of json permission files
53+
# In project root
54+
make generate permissions # makes a bunch of json permission files for test organisations
3055
make build # will take all permissions & create nrlf_permissions.zip file
3156

3257
# apply this new permissions zip file to your environment
3358
cd ./terraform/infrastructure
34-
assume test # needed?
59+
assume nhsd-nrlf-test
3560
make init TF_WORKSPACE_NAME=perftest-1 ENV=perftest
36-
tf apply
61+
make ENV=perftest USE_SHARED_RESOURCES=true apply
3762
```
3863

3964
#### Generate input files
4065

4166
```sh
67+
assume nhsd-nrlf-test
4268
# creates 2 csv files and a json file
4369
make perftest-prepare PERFTEST_TABLE_NAME=perftest-baseline
4470
```
@@ -49,3 +75,13 @@ make perftest-prepare PERFTEST_TABLE_NAME=perftest-baseline
4975
make perftest-consumer ENV_TYPE=perftest PERFTEST_HOST=perftest-1.perftest.record-locator.national.nhs.uk
5076
make perftest-producer ENV_TYPE=perftest PERFTEST_HOST=perftest-1.perftest.record-locator.national.nhs.uk
5177
```
78+
79+
## Assumptions / Caveats
80+
81+
- Run performance tests in the perftest environment only\*
82+
- Both producer & consumer tests are repeatable
83+
- These tests work on the assumption that all nhs numbers in the test data are serial and lie within a fixed range i.e. picking any number between NHS_NUMBER_MINIMUM & NHS_NUMBER_MAXIMUM will yield a patient with pointer(s).
84+
- Configure scenarios in the `consumer/perftest.config.json` & `producer/perftest.config.json` files. This does not alter the number of stages per scenario, that's fixed in `perftest.js`.
85+
- Consider running these tests multiple times to get figures for a warm environment - perftest, unlike prod, is not well-used so you will get cold-start figures on your first run
86+
87+
\*These performance tests are tightly coupled to the seed scripts that populate test data. This means these tests can only be run in an environment containing solely test data created by the seed data scripts. `perftest` is a dedicated environment to do this in, but in theory any environment could be populated with the seed data and used.

tests/performance/perftest_environment.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import re
66

77
import boto3
8+
from seed_data_constants import CHECKSUM_WEIGHTS
89

910
DYNAMODB = boto3.resource("dynamodb", region_name="eu-west-2")
1011

@@ -55,10 +56,6 @@ def extract_consumer_data(output_dir="."):
5556
print(f"Consumer data written to {out}") # noqa: T201
5657

5758

58-
# Semi-deterministic NHS number generator (duplicated from seed_nft_tables.py)
59-
CHECKSUM_WEIGHTS = [i for i in range(10, 1, -1)]
60-
61-
6259
class TestNhsNumbersIterator:
6360
def __iter__(self):
6461
self.first9 = 900000000

tests/performance/producer/delete_permissions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from pathlib import Path
22

33
import fire
4-
from seed_nft_tables import DEFAULT_CUSTODIAN_DISTRIBUTIONS
4+
5+
from tests.performance.seed_data_constants import DEFAULT_CUSTODIAN_DISTRIBUTIONS
56

67

78
def main(permissions_dir="../../dist/nrlf_permissions/K6PerformanceTest"):

tests/performance/producer/generate_distributions.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import json
22
from pathlib import Path
33

4-
# Import the constants from your seed_nft_tables.py
5-
from seed_nft_tables import DEFAULT_CUSTODIAN_DISTRIBUTIONS, DEFAULT_TYPE_DISTRIBUTIONS
4+
from tests.performance.seed_data_constants import (
5+
DEFAULT_CUSTODIAN_DISTRIBUTIONS,
6+
DEFAULT_TYPE_DISTRIBUTIONS,
7+
)
68

79

810
def expand_distribution(dist):

tests/performance/producer/generate_permissions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
from pathlib import Path
33

44
import fire
5-
from seed_nft_tables import DEFAULT_CUSTODIAN_DISTRIBUTIONS
5+
6+
from tests.performance.seed_data_constants import DEFAULT_CUSTODIAN_DISTRIBUTIONS
67

78

89
def main(output_dir="../../dist/nrlf_permissions/K6PerformanceTest"):

0 commit comments

Comments
 (0)