Skip to content

Commit

Permalink
Merge pull request #1058 from NHSDigital/SPINEDEM-3809-restrict-creat…
Browse files Browse the repository at this point in the history
…e-patient-tps

SPINEDEM-3809 Restrict Create Patient TPS
  • Loading branch information
davidhamill1-nhs authored Oct 28, 2024
2 parents d520af4 + a9a2c83 commit 5becf26
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Note the use of the Karate retry functionality in this feature:
- `* retry until responseStatus != 429 && responseStatus != 503`

We're using it because:
- the post patient functionality is subject to a spik arrest policy,
- the post patient functionality is subject to a spike arrest policy,
whereby requests can be rejected with a 429 response.
- the system may also throw a SERVICE_UNAVAILABLE error - "The downstream
domain processing has not completed within the configured timeout period.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
<SpikeArrest async="false" continueOnError="false" enabled="true" name="SpikeArrest.PatientCreate">
<DisplayName>SpikeArrest.PatientCreate</DisplayName>
<Properties/>
<Rate>5ps</Rate>
<Rate>3ps</Rate>
<UseEffectiveCount>true</UseEffectiveCount>
</SpikeArrest>
4 changes: 2 additions & 2 deletions tests/functional/features/post_patient.feature
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Feature: Post Patient Spike Arrest Policy

Scenario: The rate limit is tripped when POSTing new Patients (>5tps)
Scenario: The rate limit is tripped when POSTing new Patients (>3tps)
Given I am a healthcare worker user
When I post to the Patient endpoint more than 5 times per second
When I post to the Patient endpoint more than 3 times per second
Then I get a mix of 400 and 429 HTTP response codes
And the 429 response bodies alert me that there have been too many Create Patient requests
23 changes: 14 additions & 9 deletions tests/functional/test_patient_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
scenario = partial(pytest_bdd.scenario, './features/post_patient.feature')


@scenario('The rate limit is tripped when POSTing new Patients (>5tps)')
@scenario('The rate limit is tripped when POSTing new Patients (>3tps)')
def test_post_patient_rate_limit():
pass

Expand Down Expand Up @@ -114,12 +114,11 @@ async def _create_all_patients(headers, url, body, loop, num_patients):
# ---------------------------------------------------------------------------------------------------------------
# WHEN------------------------------------------------------------------------------------------------------------
@pytest.mark.asyncio
@when("I post to the Patient endpoint more than 5 times per second", target_fixture='post_results')
@when("I post to the Patient endpoint more than 3 times per second", target_fixture='post_results')
def post_patient_multiple_times(healthcare_worker_auth_headers: dict, pds_url: str) -> list:
# firing 30 requests in 5 seconds should trigger the spike arrest policy
# about 5 times...
patients_to_create = 30
target_request_time = 5
# firing 40 requests in 10 seconds should trigger the spike arrest policy
patients_to_create = 40
target_time_between_first_and_last_request = 10

url = f'{pds_url}/Patient'
body = json.dumps({"nhsNumberAllocation": "Done"})
Expand All @@ -135,10 +134,10 @@ def post_patient_multiple_times(healthcare_worker_auth_headers: dict, pds_url: s

response_times = [x['response_time'] for x in results]
response_times.sort()
elapsed_time_res = response_times[-1] - response_times[0]
actual_time_between_first_and_last_request = response_times[-1] - response_times[0]

# we fired requests at or faster than the expected rate
assert elapsed_time_res.seconds <= target_request_time
assert actual_time_between_first_and_last_request.seconds <= target_time_between_first_and_last_request

return results

Expand All @@ -148,7 +147,13 @@ def post_patient_multiple_times(healthcare_worker_auth_headers: dict, pds_url: s
def assert_expected_spike_arrest_response_codes(post_results):
successful_requests = [x for x in post_results if x['status'] == 400]
spike_arrests = [x for x in post_results if x['status'] == 429]
assert len(spike_arrests) >= 5
actual_number_of_spike_arrests = len(spike_arrests)

patients_to_create = 40
target_time_between_first_and_last_request = 10
expected_minimum_number_of_spike_arrests = int(patients_to_create / target_time_between_first_and_last_request)

assert actual_number_of_spike_arrests >= expected_minimum_number_of_spike_arrests
assert len(successful_requests) + len(spike_arrests) == len(post_results)


Expand Down

0 comments on commit 5becf26

Please sign in to comment.