State configuration

Note

FHIR Connect State comprises of 2 main files: context and model mappers. Read more on the official FHIR Connect specification.

State required by the engine are mapping files according to FHIR Connect specification and are split to context.yaml files and model.yaml files. Additionally, state required by the engine are also openEHR Operational Templates (.opt), which can either be part of the openFHIR Engine’s state or it can come from an integrated openEHR repository (see more: Integrations).

As an example, for a mapping of a blood pressure template, you’d need the following files (state) configured:

  • Blood Pressure.opt

  • simple-blood-pressure.context.yaml

  • blood-pressure.model.yaml

Bootstrapping

State configuration can be achieved by POSTing OPT and YAML files to the designated /opt and /fc/(context, model) endpoints. Alternatively, these files can be placed in a bootstrapping directory where they are picked from during the engine’s startup, as well as on demand through POST /$bootstrap. This approach minimizes the need for repetitive API calls, allowing for faster and more efficient configuration of pre-existing mappings.

Bootstrapping location is configured with environment variable OPENFHIR_BOOTSTRAP_DIR, default being /app/bootstrap/.

For example, setting -e OPENFHIR_BOOTSTRAP_DIR=/etc/bootstrapping-dir and placing files in this folder (/etc/bootstrapping-dir) will make the engine pick them up at startup and process them. The same directory is re-scanned whenever POST /$bootstrap is called.

If you have files to be bootstrapped separated in sub-folders, you may also add OPENFHIR_BOOTSTRAP_RECURSIVELY_OPEN_DIRECTORIES=true, which will make openFHIR Bootstrapper open all sub-folders as well and look inside for any matching files to be bootstrapped.

Files are picked according to their suffixes:

  • model files need to be suffixed with *.yaml or *.yml, i.e. blood.pressure.model.yaml

  • context files need to be suffixed with *.context.yaml or *.context.yml, i.e. simple-blood-pressure.context.yaml

  • operation template files need to be suffixed with *.opt, i.e. BloodPressure.opt

  • terminology concept maps (read more in Terminology) need to be suffixed with *.json, i.e. concept-map.json

Note

Concept maps are only bootstrapped when your license includes the terminology option. Without it, *.json files are left alone and the rest of the scan proceeds as usual.

Note

When the engine is integrated with an openEHR CDR (OPENFHIR_CDR_ENABLED=true, see Integrations), *.opt files are not bootstrapped: operational templates are owned by the CDR and must be loaded there instead. Such files are skipped with a warning in the log and reported with the outcome UNCHANGED and a message explaining why. Model mappers, context mappers and concept maps in the same directory are bootstrapped as usual, and the overall scan does not fail.

Every bootstrapped file is recorded in a ledger (bootstrap collection) together with the path it was bootstrapped from, a hash of the content that was applied, and the id of the entity it created. On every scan, openFHIR compares each file on disk against this ledger and:

  • creates an entity for a file it has not seen before,

  • updates a file whose content changed since it was last bootstrapped, in place and under the same entity id, so no duplicates are created,

  • skips a file whose content is unchanged.

Files that were bootstrapped before but are no longer on disk are reported with a warning in the log; their entities are left untouched and are not removed from the engine.

Mirror mode

With OPENFHIR_BOOTSTRAP_MODE=mirror (default upsert, the behaviour above) the engine makes its state match the directory exactly: the whole directory is imported in one atomic step, like POST /$import?mode=mirror, and model mappers, context mappers, operational templates and concept maps that are not in the directory are deleted. Files are recognised by their content rather than their names, files that are not engine state are ignored, and with OPENFHIR_BOOTSTRAP_ALLOW_ERRORS=false a directory with any invalid file changes nothing (see below). A directory without any engine state is refused as well, so an unmounted volume cannot wipe the engine. POST /$bootstrap?mode=mirror runs a mirror scan on demand.

OPENFHIR_BOOTSTRAP_ALLOW_ERRORS decides what a directory with errors does, in both modes:

  • true (default): everything the engine can store goes in, references that don’t resolve included (a model whose extends parent is missing, say). A file the engine can’t read or store (invalid content, a context whose sub-context isn’t there) is reported as FAILED and the engine keeps its own version of it; mirror mode doesn’t delete it. An upsert scan writes file by file; a mirror scan imports the way connecting the engine to a git repository that wins does (see Versioning (git)) and logs the remaining errors as warnings.

  • false: the directory is checked as a whole first, like POST /$import (content, references between files, sub-contexts; in upsert mode a file taken by its name that isn’t engine state counts too). Any error and nothing is written: every error is a FAILED entry of the summary.

This is the way to run a state kept in git (GitOps): mount a checkout of the repository as the bootstrap directory. See Versioning (git).

Note

Ledger entries are keyed by the file’s path relative to the bootstrap directory, so identically named files in different sub-folders no longer collide.

Re-running the bootstrap

The bootstrap directory scan is no longer limited to startup. POST /$bootstrap re-runs it on demand, without requiring a restart, and returns a JSON summary of what happened:

  • created, updated, unchanged and failed counts

  • files, a per-file breakdown with each file’s path, outcome (CREATED, UPDATED, UNCHANGED or FAILED), entityType, entityId and, where the file failed, a message

If a scan is already in progress, the endpoint returns 409 Conflict instead of starting a second one.

GET /bootstrap returns the bootstrap ledger of the logged-in user: which files have been bootstrapped, from which path, and which entity each one created.

Note

The web server accepts requests before the startup scan has finished. GET /health returns 503 STARTING until the startup scan completes and 200 UP afterwards, so it can be used as a “safe to send traffic” gate by orchestrators and test harnesses. Calling POST /$bootstrap before the startup scan completes will return 409 Conflict.

The bootstrap ledger is tenant-scoped. GET /$purge therefore clears the bootstrap entries of the logged-in user’s tenant along with the rest of its state, meaning that tenant’s bootstrapped files will be created again on the next scan.

Through REST

State configuration can be achieved by POSTing OPT and YAML files to the designated /opt and /fc/(context, model) endpoints. See RESTful APIs for more information.