{"id":23421177,"url":"https://github.com/nhsdigital/integration-adaptor-gp2gp-requesting","last_synced_at":"2025-04-12T14:06:13.444Z","repository":{"id":37488244,"uuid":"420983957","full_name":"NHSDigital/integration-adaptor-gp2gp-requesting","owner":"NHSDigital","description":null,"archived":false,"fork":false,"pushed_at":"2024-12-04T16:14:00.000Z","size":40303,"stargazers_count":4,"open_issues_count":22,"forks_count":3,"subscribers_count":10,"default_branch":"main","last_synced_at":"2024-12-04T16:41:08.539Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NHSDigital.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-25T10:49:23.000Z","updated_at":"2024-12-04T15:28:04.000Z","dependencies_parsed_at":"2023-10-04T19:55:46.616Z","dependency_job_id":"211b87f6-3630-4635-8e4a-e631d5b0e540","html_url":"https://github.com/NHSDigital/integration-adaptor-gp2gp-requesting","commit_stats":null,"previous_names":["nhsdigital/integration-adaptor-gp2gp-requesting"],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NHSDigital%2Fintegration-adaptor-gp2gp-requesting","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NHSDigital%2Fintegration-adaptor-gp2gp-requesting/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NHSDigital%2Fintegration-adaptor-gp2gp-requesting/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NHSDigital%2Fintegration-adaptor-gp2gp-requesting/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NHSDigital","download_url":"https://codeload.github.com/NHSDigital/integration-adaptor-gp2gp-requesting/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248578864,"owners_count":21127713,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-23T02:14:18.790Z","updated_at":"2025-04-12T14:06:13.419Z","avatar_url":"https://github.com/NHSDigital.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GP2GP FHIR Request Adaptor\nNational Integration Adaptor - [GP2GP Requesting Adaptor](https://digital.nhs.uk/developer/api-catalogue/gp2gp/gp2gp-requesting-adaptor)\n\nIncumbent providers (e.g. TPP, EMIS, SystemOne) would have to make changes to their GP Connect interface implementations\nin order to deploy GP2GP Adaptor in their infrastructure to support the losing practice scenario - i.e. whereby a \ndifferent practice transfers patient data from the incumbent. In particular, they would need to implement 1.6.0 version\nthat is required by the GPC Consumer and GP2GP adaptors.\n\nThis business case is not always easy to be accepted by the incumbent providers, as they would have to invest time to\nmake those changes.\n\nThe motivation for the GP2GP FHIR Request   Adaptor is to remove the dependency from incumbent providers to do that work.\nThe idea is to build an adaptor that could be installed and configured in a New Market Entrant (NME) infrastructure,\nand could work with the incumbent’s GPC \u003c 1.6.0.\n\nAdaptor consists of two main components:\n- GPC API Facade\n- GP2GP Translator\n\nBoth are Java Spring Boot applications, released as separate docker images.\n\n\n## Table of contents\n\n1. [Guidance for setting up the GP2GP adaptors in INT](/getting-started-instructions.md)\n1. [Guidance for operating the adaptor as a New Market Entrant](/OPERATING.md)\n1. [Guidance on integrating with the adaptors APIs](#endpoints)\n1. [Guidance for developing the adaptor](/developer-information.md)\n1. [Documentation on how this adaptor maps GP2GP concepts to GPConnect concepts](https://github.com/NHSDigital/patient-switching-adaptors-mapping-documentation)\n\n## Endpoints\n\nThe Adaptor's facade provides two main endpoints for interacting with patient records.\n\n### POST /Patient/$gpc.migratestructuredrecord\n\nThe migratestructuredrecord endpoint is the primary endpoint for the adaptor.\nThis endpoint initiates the electronic health record (EHR) transfer process. \nTo use this endpoint, you need to provide the following headers:\n\n- TO-ASID : ASID identifier of the losing incumbent\n- FROM-ASID : ASID identifier of the winning New Market Entrant (NME)\n- TO-ODS : ODS identifier of the losing incumbent\n- FROM-ODS : ODS identifier of the winning New Market Entrant (NME)\n- ConversationId : A unique UUID for the request. If not provided, the adaptor will generate one and include it in the response headers.\n  It must be used for all further calls for the patient's NHS number.\n\nIf a `ConversationId` header is provided where the value is populated but does not contain a valid UUID, then the \nfollowing response will be returned:\n\n```json\n{\n\t\"resourceType\": \"OperationOutcome\",\n\t\"meta\": {\n\t\t\"profile\": [\"https://fhir.nhs.uk/STU3/StructureDefinition/GPConnect-OperationOutcome-1\"]\n\t},\n\t\"issue\": [{\n\t\t\"severity\": \"error\",\n\t\t\"code\": \"invalid\",\n\t\t\"details\": {\n\t\t\t\"coding\": [{\n\t\t\t\t\"system\": \"https://fhir.nhs.uk/STU3/ValueSet/Spine-ErrorOrWarningCode-1\",\n\t\t\t\t\"code\": \"BAD_REQUEST\",\n\t\t\t\t\"display\": \"Bad request\"\n\t\t\t}]\n\t\t},\n\t\t\"diagnostics\": \"ConversationId header must be either be empty or a valid UUID\"\n\t}]\n}\n```\n\nFor more details on how to query the losing practice details, see the [requesting site requirements].\n\n[requesting site requirements]: https://nhse-dsic.atlassian.net/wiki/spaces/DCSDCS/pages/12512034968/GP2GP+Requesting+Adaptor#Registration-Process-\u0026-EHR-Request\n\nThe endpoint also requires a JSON body that includes the needed patient NHS number.\nRequest Body Example:\n\n   ```json\n   {\n      \"resourceType\": \"Parameters\",\n      \"parameter\": [\n         {\n            \"name\": \"patientNHSNumber\",\n            \"valueIdentifier\": {\n               \"system\": \"https://fhir.nhs.uk/Id/nhs-number\",\n               \"value\": \"{{nhs-number-test-group-8}}\"\n            }\n         },\n         {\n            \"name\": \"includeFullRecord\",\n            \"part\": [\n               {\n                  \"name\": \"includeSensitiveInformation\",\n                  \"valueBoolean\": true\n               }\n            ]\n         }\n      ]\n   }\n   ```\n\nResponds with one of:\n\n1. Initial request: If you successfully configure the endpoint described above and call it, you should receive a 202-accepted response. This means the adaptor has received the request and is making the relevant requests.\n2. Polling the request: after receiving a 202 response, we recommend polling the endpoint at regular intervals using an\n   increasing call gap strategy until you get a 200 response.\n   Each poll can return one of the following responses:\n    - 204 No content: this response indicates that we are still processing the requests / waiting for the EHR message response.\n    - 200 Success: this response indicates we have successfully received and converted the EHR to JSON; you will also receive the FHIR bundle in the response's body.\n      An example of this response can be found within [expectedBundle.json](gp2gp-translator/src/integrationTest/resources/json/expectedBundle.json).\n    - 400,404,500,501: The endpoint can return all these possible error codes. These will all provide a detailed error with an operationOutcome JSON model response in the body. This looks like...\n\n      ```json\n      {\n         \"resourceType\": \"OperationOutcome\",\n         \"meta\": {\n            \"profile\": [\n               \"https://fhir.nhs.uk/STU3/StructureDefinition/GPConnect-OperationOutcome-1\"\n            ]\n         },\n         \"issue\": [\n            {\n               \"severity\": \"error\",\n               \"code\": \"exception\",\n               \"details\": {\n                  \"coding\": [\n                     {\n                        \"system\": \"https://fhir.nhs.uk/STU3/ValueSet/Spine-ErrorOrWarningCode-1\",\n                        \"code\": \"PATIENT_NOT_FOUND\",\n                        \"display\": \"GP2GP - Patient is not registered at the practice\"\n                     },\n                     {\n                       \"system\": \"urn:oid:2.16.840.1.113883.2.1.3.2.4.17.101\",\n                       \"code\": \"06\",\n                       \"display\": \"Patient not at surgery\"\n                     }\n                  ]\n               }\n            }\n         ]\n      }\n      ```\n\n### POST /$gpc.ack\n\nThis endpoint finalizes the EHR transfer process.\nIf you do not call this endpoint after receiving an EHR from the migratestructuredrecord enpoint, then you risk the losing practise triggering off the manual postal transfer.\n\nTo use this endpoint, you need to provide the following headers:\n\n- CONVERSATIONID: ID from the initial request.\n- CONFIRMATIONRESPONSE: Status of the EHR integration.\n    - ACCEPTED: EHR integration successful.\n    - FAILED_TO_INTEGRATE: Error encountered; triggers postal process.\n\nEndpoint calling:\n\nThis endpoint is a fire-and-forget endpoint.\n- If your request is successful, you will get a 200: Success response.\n- If your request is unsuccessful, you will get a 500: Server error response.\n- If you receive a 500 response, you can retry again at any point, however, it should be noted that you must receive a 200: Success response from the migratestructuredrecord for the given conversation ID to receive a 200: Success from this endpoint.\n\n## Licensing\nThis code is dual licensed under the MIT license and the OGL (Open Government License).\nAny new work added to this repository must conform to the conditions of these licenses.\nIn particular this means that this project may not depend on GPL-licensed or AGPL-licensed libraries,\nas these would violate the terms of those libraries' licenses.\n\nThe contents of this repository are protected by Crown Copyright (C).\n\n## Performance\n\nCase 1: Performance Testing with JMeter\n\nWe conducted a performance test of the Adaptor using the JMeter tool. \nThe use case focused on simulating a patient transfer request, \nwhere Electronic Health Record (EHR) requests were sent to the Adaptor, expecting a bundle in return. \nThis test involved two text attachments with sizes of 2.44 MB and 0.7 MB, respectively. \nThe primary goal was to evaluate how the Adaptor manages a heavy workload and to monitor CPU and memory usage \nduring the process.\n\nTest Setup and Parameters:\n\n - GP2GP FHIR Request Adaptor: Deployed in an ECS AWS environment with 4 CPUs and 16 GB of memory (shared between the PS Translator and Facade).\n - MHS Adaptor: Deployed in an ECS AWS environment with 4 CPUs and 16 GB of memory (shared between inbound and outbound).\n - Message Queue: Utilized the mq.m5.xlarge instance type.\n - RDS Database: Hosted on a db.t3.xlarge instance.\n\nThe test involved 2000 patient transfers, divided into 5 batches of 400 transfers each. \nThe total test duration was measured from the start of the initial request until the completion of all transfers. \nA random pause time between 100 ms and 1100 ms was introduced between transfers, with a socket timeout set to 2 minutes.\n\nResults:\n\nThe test load of 2000 transactions was successfully completed in 14 minutes, averaging 420-435 ms per transfer.\nCPU utilization during the test was around 50-60%, and memory usage was approximately 70%, \nindicating sufficient capacity for additional load.\n\n-----------------------------------------------------------------\n\nCase 2: Performance Testing via TPP/EMIS and Medicus\n\nIn a separate series of tests, up to 10 concurrent patient transfers were completed, \ninvolving varying attachment types (100, 500, 1000) and file sizes (1 KB, 100 KB, 500 KB, 3.5 MB, 5 MB). \nThese tests were conducted with TPP/EMIS as the sending systems and Medicus as the receiving system.\n\nResource Allocation:\n\nGP2GP FHIR Request Adaptor:\n    Facade: 2 vCPUs, 4 GB RAM\n    Translator: 2 vCPUs, 4 GB RAM\nMHS Adaptor:\n    Inbound: 2 vCPUs, 4 GB RAM\n    Outbound: 0.25 vCPUs, 0.5 GB RAM\nMessage Queue: \n    Instance Type: mq.m5.large\n\nResults:\n\nA single patient record of 10 MB was processed in approximately 20 seconds.\nOn average, the transfer of up to 10 patients was completed within 1 to 1 minute and 40 seconds.\n\n\n![report1.jpg](test-suite%2Fnon-functional-tests%2Ftest-scenario%2Fperf_report%2Freport1.jpg)\n\nOverall performance statistics:\n![report2.png](test-suite%2Fnon-functional-tests%2Ftest-scenario%2Fperf_report%2Freport2.png)\n\nActive transfers per one iteration was 400:\n![report4.png](test-suite%2Fnon-functional-tests%2Ftest-scenario%2Fperf_report%2Freport4.png)\n\nResponse time:\n![report5.png](test-suite%2Fnon-functional-tests%2Ftest-scenario%2Fperf_report%2Freport5.png)\n\nResults can be seen in using graphs by importing results8.jtl into Jmeter.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnhsdigital%2Fintegration-adaptor-gp2gp-requesting","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnhsdigital%2Fintegration-adaptor-gp2gp-requesting","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnhsdigital%2Fintegration-adaptor-gp2gp-requesting/lists"}