Skip to content

Commit 15f102e

Browse files
NRL-1841 Producer perf tests run in public mode, same as the consumer ones
1 parent 2f052be commit 15f102e

File tree

4 files changed

+99
-59
lines changed

4 files changed

+99
-59
lines changed

Makefile

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,22 @@ perftest-prepare: ## Prepare input files for producer & consumer perf tests
311311
# cp "${DIST_PATH}/nft/seed-pointers-extract-${PERFTEST_TABLE_NAME}.csv" "${DIST_PATH}/seed-pointers-extract.csv"
312312
PYTHONPATH=. poetry run python ./tests/performance/generate_producer_distributions.py
313313

314-
perftest-producer: ## Run producer perf tests
314+
perftest-producer-internal: ## Run producer perf tests
315315
@echo "Running producer performance tests with HOST=$(PERFTEST_HOST) and ENV_TYPE=$(ENV_TYPE) and DIST_PATH=$(DIST_PATH)"
316316
k6 run tests/performance/producer/perftest.js -e HOST=$(PERFTEST_HOST) -e ENV_TYPE=$(ENV_TYPE) -e DIST_PATH=$(DIST_PATH)
317317

318+
perftest-producer-public: check-warn ## Run the producer perftests for the external access points
319+
@echo "Fetching public mode configuration and bearer token..."
320+
@CONFIG_FILE=$$(mktemp /tmp/perf_config_XXXXXX); \
321+
trap "rm -f $$CONFIG_FILE" EXIT; \
322+
PYTHONPATH=. poetry run python tests/performance/get_test_config.py $(ENV_TYPE) 2>&1 | tail -n 1 > $$CONFIG_FILE; \
323+
PUBLIC_BASE_URL=$$(jq -r '.public_base_url' $$CONFIG_FILE); \
324+
echo "Running public producer perftests with ENV_TYPE=$(ENV_TYPE) and DIST_PATH=$(DIST_PATH)"; \
325+
TEST_CONNECT_MODE=public \
326+
TEST_PUBLIC_BASE_URL=$$PUBLIC_BASE_URL \
327+
TEST_CONFIG_FILE=$$CONFIG_FILE \
328+
k6 run tests/performance/producer/perftest.js -e ENV_TYPE=$(ENV_TYPE) -e DIST_PATH=$(DIST_PATH)
329+
318330
perftest-consumer-internal:
319331
@echo "Running consumer performance tests with HOST=$(PERFTEST_HOST) and ENV_TYPE=$(ENV_TYPE) and DIST_PATH=$(DIST_PATH)"
320332
k6 run tests/performance/consumer/perftest.js -e HOST=$(PERFTEST_HOST) -e ENV_TYPE=$(ENV_TYPE) -e DIST_PATH=$(DIST_PATH)

tests/performance/README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,20 @@ make perftest-prepare PERFTEST_TABLE_NAME=nhsd-nrlf--perftest-baseline-pointers-
7272

7373
### Run tests
7474

75+
#### Internal mode
76+
77+
```sh
78+
make perftest-consumer-internal ENV_TYPE=perftest PERFTEST_HOST=perftest-1.perftest.record-locator.national.nhs.uk
79+
make perftest-producer-internal ENV_TYPE=perftest PERFTEST_HOST=perftest-1.perftest.record-locator.national.nhs.uk
80+
```
81+
82+
#### Public mode
83+
84+
Via apigee proxies - most similar to a supplier
85+
7586
```sh
76-
make perftest-consumer ENV_TYPE=perftest PERFTEST_HOST=perftest-1.perftest.record-locator.national.nhs.uk
77-
make perftest-producer ENV_TYPE=perftest PERFTEST_HOST=perftest-1.perftest.record-locator.national.nhs.uk
87+
make perftest-consumer-public ENV=perftest
88+
make perftest-producer-public ENV=perftest
7889
```
7990

8091
## Seed data

tests/performance/producer/client_perftest.js

Lines changed: 72 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { check } from "k6";
44
import { randomItem } from "https://jslib.k6.io/k6-utils/1.2.0/index.js";
55
import { crypto } from "k6/experimental/webcrypto";
66
import { createRecord } from "../setup.js";
7+
import { getHeaders, getFullUrl } from "../test-config.js";
78
import exec from "k6/execution";
89

910
const distPath = __ENV.DIST_PATH || "./dist";
@@ -38,7 +39,7 @@ function getNextPointer() {
3839
const iter = exec.vu.iterationInScenario;
3940
const index = iter % dataLines.length;
4041
const line = dataLines[index];
41-
// Adjust field names as per CSV columns: count,pointer_id,pointer_type,custodian,nhs_number
42+
4243
const [pointer_id, pointer_type, custodian, nhs_number] = line
4344
.split(",")
4445
.map((field) => field.trim());
@@ -115,25 +116,6 @@ pickCustodian = function (typeCode) {
115116
return randomItem(arr);
116117
};
117118

118-
function getBaseURL() {
119-
return `https://${__ENV.HOST}/producer/DocumentReference`;
120-
}
121-
122-
function getHeaders(odsCode = ODS_CODE) {
123-
return {
124-
"Content-Type": "application/fhir+json",
125-
"X-Request-Id": `K6perftest-producer-${exec.scenario.name}-${exec.vu.idInTest}-${exec.vu.iterationInScenario}`,
126-
"NHSD-Correlation-Id": `K6perftest-producer-${exec.scenario.name}-${exec.vu.idInTest}-${exec.vu.iterationInScenario}`,
127-
"NHSD-Connection-Metadata": JSON.stringify({
128-
"nrl.ods-code": odsCode,
129-
"nrl.app-id": "K6PerformanceTest",
130-
}),
131-
"NHSD-Client-RP-Details": JSON.stringify({
132-
"developer.app.name": "K6PerformanceTest",
133-
"developer.app.id": "K6PerformanceTest",
134-
}),
135-
};
136-
}
137119
function checkResponse(res) {
138120
const is_success = check(res, { "status is 200": (r) => r.status === 200 });
139121
if (!is_success) {
@@ -146,9 +128,12 @@ export function createDocumentReference() {
146128
const pointerType = pickPointerType();
147129
const custodian = pickCustodian(pointerType);
148130
const record = createRecord(nhsNumber, pointerType, custodian);
149-
const res = http.post(getBaseURL(), JSON.stringify(record), {
150-
headers: getHeaders(custodian),
131+
const path = "/DocumentReference";
132+
133+
const res = http.post(getFullUrl(path, "producer"), JSON.stringify(record), {
134+
headers: getHeaders(custodian, "producer"),
151135
});
136+
152137
check(res, { "create status is 201": (r) => r.status === 201 });
153138
if (res.status !== 201) {
154139
console.warn(
@@ -161,9 +146,12 @@ export function createDocumentReference() {
161146

162147
export function readDocumentReference() {
163148
const { pointer_id, custodian } = getNextPointer();
164-
const res = http.get(`${getBaseURL()}/${pointer_id}`, {
165-
headers: getHeaders(custodian),
149+
const path = `/DocumentReference/${pointer_id}`;
150+
151+
const res = http.get(getFullUrl(path, "producer"), {
152+
headers: getHeaders(custodian, "producer"),
166153
});
154+
167155
checkResponse(res);
168156
}
169157

@@ -172,9 +160,14 @@ export function createThenReadDocumentReference() {
172160
const pointerType = pickPointerType();
173161
const custodian = pickCustodian(pointerType);
174162
const record = createRecord(nhsNumber, pointerType, custodian);
175-
const createRes = http.post(getBaseURL(), JSON.stringify(record), {
176-
headers: getHeaders(custodian),
177-
});
163+
const createPath = "/DocumentReference";
164+
165+
const createRes = http.post(
166+
getFullUrl(createPath, "producer"),
167+
JSON.stringify(record),
168+
{ headers: getHeaders(custodian, "producer") }
169+
);
170+
178171
check(createRes, { "create status is 201": (r) => r.status === 201 });
179172
if (createRes.status !== 201) {
180173
console.warn(
@@ -190,9 +183,10 @@ export function createThenReadDocumentReference() {
190183
const createdId = locationHeader
191184
? locationHeader.split("/").pop()
192185
: record.id;
186+
const path = `/DocumentReference/${createdId}`;
193187

194-
const readRes = http.get(`${getBaseURL()}/${createdId}`, {
195-
headers: getHeaders(custodian),
188+
const readRes = http.get(getFullUrl(path, "producer"), {
189+
headers: getHeaders(custodian, "producer"),
196190
});
197191

198192
check(readRes, { "create and read status is 200": (r) => r.status === 200 });
@@ -211,9 +205,14 @@ export function upsertThenReadDocumentReference() {
211205
const custodian = pickCustodian(pointerType);
212206
const record = createRecord(nhsNumber, pointerType, custodian);
213207
record.id = `${custodian}-${crypto.randomUUID()}`;
214-
const upsertRes = http.put(getBaseURL(), JSON.stringify(record), {
215-
headers: getHeaders(custodian),
216-
});
208+
const upsertPath = "/DocumentReference";
209+
210+
const upsertRes = http.put(
211+
getFullUrl(upsertPath, "producer"),
212+
JSON.stringify(record),
213+
{ headers: getHeaders(custodian, "producer") }
214+
);
215+
217216
check(upsertRes, { "upsert status is 201": (r) => r.status === 201 });
218217
if (upsertRes.status !== 201) {
219218
console.warn(
@@ -225,9 +224,10 @@ export function upsertThenReadDocumentReference() {
225224
}
226225

227226
const upsertedId = record.id;
227+
const path = `/DocumentReference/${upsertedId}`;
228228

229-
const readRes = http.get(`${getBaseURL()}/${upsertedId}`, {
230-
headers: getHeaders(custodian),
229+
const readRes = http.get(getFullUrl(path, "producer"), {
230+
headers: getHeaders(custodian, "producer"),
231231
});
232232

233233
check(readRes, { "upsert and read status is 200": (r) => r.status === 200 });
@@ -245,9 +245,14 @@ export function createThenUpdateDocumentReference() {
245245
const pointerType = pickPointerType();
246246
const custodian = pickCustodian(pointerType);
247247
const record = createRecord(nhsNumber, pointerType, custodian);
248-
const createRes = http.post(getBaseURL(), JSON.stringify(record), {
249-
headers: getHeaders(custodian),
250-
});
248+
const path = `/DocumentReference/${upsertedId}`;
249+
250+
const createRes = http.post(
251+
getFullUrl(path, "producer"),
252+
JSON.stringify(record),
253+
{ headers: getHeaders(custodian, "producer") }
254+
);
255+
251256
check(createRes, {
252257
"createThenUpdateDocumentReference: create status is 201": (r) =>
253258
r.status === 201,
@@ -271,13 +276,12 @@ export function createThenUpdateDocumentReference() {
271276

272277
// Now update the record
273278
record.content[0].attachment.url = "https://example.com/k6-updated-url.pdf";
279+
const updatePath = `/DocumentReference/${createdId}`;
274280

275281
const updateRes = http.put(
276-
`${getBaseURL()}/${createdId}`,
282+
getFullUrl(updatePath, "producer"),
277283
JSON.stringify(record),
278-
{
279-
headers: getHeaders(custodian),
280-
}
284+
{ headers: getHeaders(custodian, "producer") }
281285
);
282286

283287
check(updateRes, {
@@ -299,9 +303,14 @@ export function upsertThenUpdateDocumentReference() {
299303
const custodian = pickCustodian(pointerType);
300304
const record = createRecord(nhsNumber, pointerType, custodian);
301305
record.id = `${custodian}-${crypto.randomUUID()}`;
302-
const upsertRes = http.put(getBaseURL(), JSON.stringify(record), {
303-
headers: getHeaders(custodian),
304-
});
306+
const path = "/DocumentReference";
307+
308+
const upsertRes = http.put(
309+
getFullUrl(path, "producer"),
310+
JSON.stringify(record),
311+
{ headers: getHeaders(custodian, "producer") }
312+
);
313+
305314
check(upsertRes, { "upsert status is 201": (r) => r.status === 201 });
306315
if (upsertRes.status !== 201) {
307316
console.warn(
@@ -317,12 +326,12 @@ export function upsertThenUpdateDocumentReference() {
317326
// Now update the record
318327
record.content[0].attachment.url = "https://example.com/k6-updated-url.pdf";
319328

329+
const updatePath = `/DocumentReference/${upsertedId}`;
330+
320331
const updateRes = http.put(
321-
`${getBaseURL()}/${upsertedId}`,
332+
getFullUrl(updatePath, "producer"),
322333
JSON.stringify(record),
323-
{
324-
headers: getHeaders(custodian),
325-
}
334+
{ headers: getHeaders(custodian, "producer") }
326335
);
327336

328337
check(updateRes, {
@@ -344,9 +353,12 @@ export function upsertDocumentReference() {
344353
const custodian = pickCustodian(pointerType);
345354
const record = createRecord(nhsNumber, pointerType, custodian);
346355
record.id = `${custodian}-k6perf-${crypto.randomUUID()}`;
347-
const res = http.put(getBaseURL(), JSON.stringify(record), {
348-
headers: getHeaders(custodian),
356+
const path = "/DocumentReference";
357+
358+
const res = http.put(getFullUrl(path, "producer"), JSON.stringify(record), {
359+
headers: getHeaders(custodian, "producer"),
349360
});
361+
350362
check(res, { "create status is 201": (r) => r.status === 201 });
351363
if (res.status !== 201) {
352364
console.warn(
@@ -363,10 +375,12 @@ export function searchDocumentReference() {
363375
`https://fhir.nhs.uk/Id/nhs-number|${nhs_number}`
364376
);
365377
const type = encodeURIComponent(`http://snomed.info/sct|${pointer_type}`);
366-
const url = `${getBaseURL()}?subject:identifier=${identifier}&type=${type}`;
367-
const res = http.get(url, {
368-
headers: getHeaders(custodian),
378+
const path = `/DocumentReference?subject:identifier=${identifier}&type=${type}`;
379+
380+
const res = http.get(getFullUrl(path, "producer"), {
381+
headers: getHeaders(custodian, "producer"),
369382
});
383+
370384
check(res, {
371385
"searchDocumentReference status is 200": (r) => r.status === 200,
372386
});
@@ -383,9 +397,12 @@ export function searchPostDocumentReference() {
383397
"subject:identifier": `https://fhir.nhs.uk/Id/nhs-number|${nhs_number}`,
384398
type: `http://snomed.info/sct|${pointer_type}`,
385399
});
386-
const res = http.post(`${getBaseURL()}/_search`, body, {
387-
headers: getHeaders(custodian),
400+
const path = `/DocumentReference/_search`;
401+
402+
const res = http.post(getFullUrl(path, "producer"), body, {
403+
headers: getHeaders(custodian, "producer"),
388404
});
405+
389406
check(res, {
390407
"searchPostDocumentReference status is 200": (r) => r.status === 200,
391408
});

tests/utilities/get_access_token.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def generate_client_assertion(app_secrets: dict):
109109
"sub": app_secrets["api_key"],
110110
"aud": app_secrets["oauth_url"],
111111
"jti": str(uuid4()),
112-
"exp": time() + 300,
112+
"exp": time() + 300, # max:312, still times out at just < 10 mins :(
113113
},
114114
app_secrets["private_key"],
115115
algorithm="RS512",

0 commit comments

Comments
 (0)