An open API service indexing awesome lists of open source software.

https://github.com/miracum/fhir-gateway

A thin layer between FHIR REST clients and resource processing pipelines.
https://github.com/miracum/fhir-gateway

fhir fhir-api fhir-server kafka

Last synced: 5 months ago
JSON representation

A thin layer between FHIR REST clients and resource processing pipelines.

Awesome Lists containing this project

README

          

# FHIR Gateway

![License](https://img.shields.io/github/license/miracum/fhir-gateway)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/miracum/fhir-gateway/badge)](https://scorecard.dev/viewer/?uri=github.com/miracum/fhir-gateway)
[![SLSA 3](https://slsa.dev/images/gh-badge-level3.svg)](https://slsa.dev)

A thin layer between FHIR REST clients and resource processing pipelines.

## Overview

![Overview](docs/img/overview.png "Overview")

## Run it

The recommended deployment is on Kubernetes. See for
a Helm Chart.

An example for deploying using (Docker) Compose can be found in the [deploy folder](./deploy/README.md).

Also see the now archived for an example end-to-end deployment.

## Configuration

To configure your deployment, you can change the following environment variables:

| Variable | Description | Default |
|-----------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------|
| SPRING_DATASOURCE_URL | JDBC URL of the Postgres DB to store the received FHIR resources, needs to be set to an empty variable if no PSQL db is to be connected to | jdbc:postgresql://fhir-db:5432/fhir |
| SPRING_DATASOURCE_USERNAME | Username of the Postgres DB | postgres |
| SPRING_DATASOURCE_PASSWORD | Password for the Postgres DB | postgres |
| SERVICES_LOINC_CONVERSIONS_ENABLED | Wether LOINC harmonization should be enabled | false |
| SERVICES_LOINC_CONVERSIONS_URL | URL of the [LOINC conversion service](https://github.com/miracum/loinc-conversion) | |
| SERVICES_PSEUDONYMIZER_ENABLED | Whether pseudonymization should be enabled. | false |
| SERVICES_PSEUDONYMIZER_URL | URL of the [FHIR Pseudonymizer service](https://github.com/miracum/fhir-pseudonymizer) | |
| SERVICES_FHIRSERVER_ENABLED | Wether storing resources in a downstream FHIR Server should be enabled | false |
| SERVICES_FHIRSERVER_URL | URL of the FHIR server to send data to | |
| SERVICES_FHIRSERVER_AUTH_BASIC_ENABLED | Enable HTTP basic auth for sending data to FHIR server | false |
| SERVICES_FHIRSERVER_AUTH_BASIC_USERNAME | HTTP basic auth username of the FHIR server to send data to | `""` |
| SERVICES_FHIRSERVER_AUTH_BASIC_PASSWORD | HTTP basic auth password of the FHIR server to send data to | `""` |
| SERVICES_PSQL_ENABLED | Wether storing resources in a PostgreSQL database should be enabled | false |
| SERVICES_KAFKA_ENABLED | Wether Kafka should be enabled. Note Kafka options below | false |
| SERVICES_KAFKA_PROCESSOR_ENABLED | Enable reading FHIR resources from, and writing them back to a Kafka cluster | false |
| SERVICES_KAFKA_PROCESSOR_GENERATE_OUTPUT_TOPIC_MATCH_EXPRESSION | Allows for dynamically generating the Kafka output topic's name based on the input topic. Used to set a regular expression which is applied to the input topic and the first match is replaced with the value of `SERVICES_KAFKA_GENERATE_OUTPUT_TOPIC_REPLACE_WITH`. You can set this to `"^"` to add a prefix to the output topic. | `""` |
| SERVICES_KAFKA_PROCESSOR_CONSUME_ONLY | Only reads FHIR resources from a Kafka cluster without writing them back | false |
| SERVICES_KAFKA_STORE_FROM_API_ENABLED | Wether storing resources in a Kafka topic should be enabled (only applicable for resources received by the FHIR Gateway's FHIR REST API | false |
| SERVICES_KAFKA_STORE_FROM_API_OUTPUT_TOPIC | Name of the topic where resources received from API should be written to | fhir.gateway.ouput |

For the Kafka configuration and other configuration options,
see [application.yml](src/main/resources/application.yml).

### Running without database persistence

By default, the FHIR gateway persists any received FHIR resource in a PostgreSQL database.
To run without persistence, the following variables both need to be set:

- `SPRING_SERVICE_PSQL_ENABLED="false"`
- `SPRING_SQL_INIT_MODE="never"`

this allows the gateway to start without the database.

## Supported Operations

The FHIR Gateway is not a fully-fledged FHIR server and only supports a subset of the RESTful server
interactions.

### POST/PUT

The Gateway only supports persisting resources that are HTTP POSTed as FHIR Bundles using
the [update-as-create](https://www.hl7.org/fhir/http.html#upsert) semantics.
See [bundle.json](tests/e2e/data/bundle.json) for an example.

### DELETE

FHIR Bundles containing `DELETE` requests are also handled and will result in deleting the resource
specified in the request URL. Note that the resources are marked as `is_deleted` in the Gateway's
PostgreSQL DB instead of being physically deleted.

Note that neither conditional creates nor deletes are supported. While this works:

```json
{
"request": {
"method": "DELETE",
"url": "Patient/234"
}
}
```

This does not:

```json
{
"request": {
"method": "DELETE",
"url": "Patient?identifier=123456"
}
}
```

## Development

Start all fixtures to run the FHIR GW:

```sh
docker compose \
-f dev/docker-compose.dev.yml \
-f dev/docker-compose.gw-deps.yml \
-f dev/docker-compose.exposed.yml up
```

This contains a few optional services: Kafka, a FHIR server, FHIR Pseudonymizer, Vfps. You might simplify the
docker-compose.dev.yml and only include relevant components for development.

Run the FHIR Gateway from your terminal:

```sh
./gradlew :bootRun
```

By default, this runs using Kafka as a source of FHIR resources to process. You can view the generated Kafka topics
at .

## Database Tuning

### Partitioning

If the size of the `resources` table is expected to grow significantly, you can leverage
partitioning to split the stored resources by type. Run the following **before** starting the
FHIR-Gateway to create the `resources` table with partitions for the most common resource types:

```postgresql
CREATE TABLE resources (
id SERIAL,
fhir_id VARCHAR(64) NOT NULL,
type VARCHAR(64) NOT NULL,
data JSONB NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
last_updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
CONSTRAINT fhir_id_unique UNIQUE (fhir_id, type)
) PARTITION BY LIST (type);

CREATE TABLE resources_patient PARTITION OF resources FOR VALUES IN ('Patient');
CREATE TABLE resources_encounter PARTITION OF resources FOR VALUES IN ('Encounter');
CREATE TABLE resources_condition PARTITION OF resources FOR VALUES IN ('Condition');
CREATE TABLE resources_observation PARTITION OF resources FOR VALUES IN ('Observation');
CREATE TABLE resources_medication PARTITION OF resources FOR VALUES IN ('Medication');
CREATE TABLE resources_medication_statement PARTITION OF resources FOR VALUES IN ('MedicationStatement');
CREATE TABLE resources_medication_administration PARTITION OF resources FOR VALUES IN ('MedicationAdministration');
CREATE TABLE resources_procedure PARTITION OF resources FOR VALUES IN ('Procedure');
CREATE TABLE resources_others PARTITION OF resources DEFAULT;

CREATE INDEX resource_id_idx ON resources (id);
CREATE INDEX resource_type_idx ON resources (type);
CREATE INDEX last_updated_at_idx ON resources (last_updated_at DESC);
```

Be sure to set `SPRING_SQL_INIT_MODE=never` before starting the FHIR GW.

This isn't part of the default initialization schema, but may become the default as part of the next
major release.