Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The HL7 v2 face

FerroPIX answers the HL7 v2 PIX and PDQ transactions on one MLLP listener, beside the FHIR face and on the same cross-reference: ITI-8 Patient Identity Feed, ITI-9 PIX Query and ITI-21 Patient Demographics Query, as the IHE ITI Technical Framework Volume 2 texts prescribe them. A v2 feed and a FHIR feed of the same patient land in one person, and a v2 query and a FHIR query answer the same cross-reference. The face reads messages with FerroBRIDGE’s HL7 v2 parser and MLLP codec, so the family has one parser.

Turn it on with [hl7v2] enabled = true and list every sender (Configuration):

[hl7v2]
enabled = true
listen = "0.0.0.0:2575"

[[hl7v2.senders]]
application = "ADT"
facility = "EAST"
domain = "urn:oid:2.999.1.1"

[[hl7v2.senders]]
application = "PORTAL"
facility = "NORTH"

[hl7v2.namespaces]
"urn:oid:2.999.1.1" = "HOSP"

The listener

  • Framing: MLLP Release 1, one message per frame. A frame that does not open with the start block, holds a start block inside it, runs past frame_limit_bytes or does not complete within frame_timeout_ms is answered AR when its header can be read, and the connection closes. A connection idle past idle_timeout_ms closes.
  • Character sets: MSH-18 names the set a message is read in; a message with an empty MSH-18 is read in default_charset. The answer is written in the set the message came in.
  • Senders: each [[hl7v2.senders]] entry names a sending application (MSH-3) and facility (MSH-4), matched by namespace id or universal id. A message from a sender not listed is answered AR and not applied. A sender with a domain is that domain’s one Patient Identity Source and may feed it; a sender without one may only query.
  • Assigning authorities: a domain is the system of a FHIR identifier. An assigning authority with a universal id of type ISO names the domain urn:oid:<oid>, one of type URI names the domain by that URI, and a namespace id names the domain [hl7v2.namespaces] gives it. Every identifier in an answer carries all three subcomponents; the namespace id is empty for a domain the configuration names none for.
  • The drain: on SIGTERM the listener stops accepting, finishes the messages it is answering within [server] shutdown_timeout_ms, and closes. Readiness carries the hl7v2_listener indicator, down once the listener stops accepting.

No byte of a message reaches a log line: the server logs each message by MSH-10, its type and the acknowledgment code.

ITI-8, the identity feed

ADT^A01, A04, A05 and A08 add or revise a patient, and ADT^A40 merges the MRG-1 identifier into the PID-3 identifier. The identifier fed is the PID-3 repetition in the sender’s domain; a repetition with no assigning authority takes the sender’s domain. The other repetitions in domains FerroPIX holds, a BSN among them, are carried as a FHIR feed carries them.

The face reads PID as the Patient a FHIR Source would send for the same patient (name, birth date, gender, address, telecom and the mother’s maiden name, after the HL7 v2-to-FHIR maps) and applies it through the same feed transaction as ITI-104, so the version written, the deterministic match and the merge are the same. An A40 is the Resolve Duplicate message: the subsumed record is replaced by the survivor, its person merged into the survivor’s.

The acknowledgment is in original mode:

AnswerWhen
AAThe message is applied.
AE, ERR PID^1^3^1^4 code 204PID-3 carries no identifier in the sender’s domain.
AE, ERR code 101PID-3 or MRG-1 is missing.
AE, ERR MRG^1^1^1^4 code 204MRG-1 is not in the sender’s domain.
AE, ERR code 204An A40 names a survivor FerroPIX does not hold.
AR, ERR code 200Any other message type or trigger event.
AR, ERR code 207The store or the audit spool cannot take the message; send it again.

A message sent again with the same MSH-10 from the same sender is acknowledged with the code it got the first time and is not applied again.

ITI-9, the PIX query

QBP^Q23 names one identifier in QPD-3 and, in QPD-4, the domains whose identifiers it wants. The answer, RSP^K23, holds what ITI-83 answers for the same identifier: one PID whose PID-3 lists every identifier of the person except the one asked, filtered to the QPD-4 domains, with a pseudo-name in PID-5. A merged identifier answers the survivor’s identifiers and a removed one is not found, as on the FHIR face.

MSA-1, QAK-2When
AA, OKIdentifiers are found.
AA, NFThe person holds no identifier in the requested domains.
AE, AE, ERR QPD^1^3^1^1 code 204The identifier is not known.
AE, AE, ERR QPD^1^3^1^4 code 204The identifier’s domain is not known.
AE, AE, ERR QPD^1^4^n code 204The domain of QPD-4 repetition n is not known.

ITI-21, the demographics query

QBP^Q22 names its criteria as QPD-3 parameters and the domains whose identifiers it wants in QPD-8. Each parameter is searched as its ITI-78 parameter, so the persons found are the ones a PDQm search finds:

QPD-3 fieldITI-78 parameter
@PID.3.1 with @PID.3.4identifier
@PID.5.1.1family
@PID.5.2given
@PID.6.1.1mothersMaidenName
@PID.7birthdate
@PID.8gender
@PID.11.1 to @PID.11.6address, address-city, address-state, address-postalcode, address-country
@PID.13.1telecom
@PID.18.1 with @PID.18.4identifier

The answer, RSP^K22, holds one PID per person with its identifiers and demographics. A QPD-8 domain FerroPIX does not know answers AE with an ERR at QPD^1^8^n, and a field FerroPIX does not search on answers AE.

RCP-2 (2^RD) asks for increments of that many records. An answer that holds fewer than match ends with a DSC whose pointer you send back in a DSC segment for the next increment. A pointer lives ten minutes, is used once, and is given up by QCN^J01; a pointer unknown or past its lifetime answers AE with an ERR at DSC^1^1.

ITI-22, the demographics and visit query

FerroPIX keeps no visit data, so it does not answer ITI-22 (QBP^ZV1): the transaction returns a PV1 segment for every patient and searches visit fields. A QBP^ZV1 is acknowledged AR with ERR code 200. Query with ITI-21, which searches the same demographics.

Audit

Every message writes its audit record before the answer leaves: the Patient Record event of ITI-8 (C, U, and for an A40 U for the survivor and D for the subsumed identifier) and the Query event of ITI-9 and ITI-21 with the whole query message, each with the sender as its source at the connection’s own network address (Security and audit). An audit spool without room refuses the message with AR.

ITI-10, the PIX update notification

After every change to the cross-reference (a feed that creates or links a record, a merge, a revert, a removal), FerroPIX notifies each consumer [[hl7v2.consumers]] names whose domains of interest the changed patient holds an identifier in; a consumer with no domains is interested in every domain. Each notification is an ADT^A31 in HL7 v2.5: MSH-9 ADT^A31^ADT_A05, an EVN, one PID whose PID-3 lists the patient’s identifiers in the consumer’s domains with all three subcomponents of each assigning authority and whose PID-5 is a single space, and a PV1 with PV1-2 N (ITI TF-2 3.10.4.1.2). A merge sends the survivor’s identifiers; a patient whose last record was removed holds none, so it sends nothing.

The notification is written to the outbox in the transaction that made the change, and the outbox sender delivers each consumer’s notifications in order, one at a time, over MLLP. An acknowledgment AA whose MSA-2 names the notification is a delivery; another code, a reply to another message, a refused connection or a timeout is retried within [hl7v2.notification], after which the notification is abandoned and the next one goes. Each notification that reaches the consumer writes the Manager’s audit record of ITI TF-2 3.10.5.1.1: a Patient Record read with the consumer as the destination, a patient per identifier of PID-3 and MSH-10 as a detail. The dependency report shows each consumer’s latest outcome (Operations).