Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

interface.yaml: an interface

An interface is a folder under interfaces/: its interface.yaml, its code, its tests and sample messages. The YAML says where messages come from, what they are, where they go, and how they're delivered, kept and watched; the code says what happens to each one on the way.

Only three things are required: a name, a source, and a destination (or several, destinations). Everything else has a default that's safe to start with:

# interfaces/adt-relay/interface.yaml
name: adt-relay
source: { mllp: { port: 6662 } }
destination: { mllp: { host: ${LAB_HOST}, port: ${LAB_PORT} } }

That relays HL7 from whoever connects on port 6662 to the lab, as received: no code, every message stored before its ACK, delivered in arrival order, retried for as long as the lab is down or answers AE (an AR, a refusal for good, is quarantined for a person), kept seven weeks.

A fuller one, with each part explained on the pages below:

# interfaces/adt-to-lab/interface.yaml
name: adt-to-lab
about:
  description: ADT from Epic to the Sunquest lab
  owner: lab-it@hospital.org
  from: { application: Epic, vendor: Epic Systems, hosts: [10.20.30.0/24] }
  to: { application: Sunquest Lab, vendor: Sunquest }
source:
  mllp:
    port: ${EPIC_PORT}
    allow: [10.20.30.0/24]
script: transform.ts
timeout: 500ms
ordering: { key: PID-3.1 }
destinations:
  lab:
    mllp: { host: ${LAB_HOST}, port: ${LAB_PORT}, tls: true }
  billing:
    http: { api: billing, path: /charges }
    transform: toBilling
    output: json
retention: 3w
monitor:
  active_within: 30m
  between: "06:00-22:00"
  behind: { messages: 500, age: 10m }
alert: { to: [lab-team] }
PartSettingsPage
Where messages come from, what they are, who may sendsource, format, output, allowSources and formats
Where they godestination, destinationsDestinations
How they're deliveredordering, retry, dedupe, rate_limit, durability, isolation, workers, dedicated_poolsDelivery
How long they're kept, what's expected, who hearsretention, quarantined, monitor, alertKeeping and watching
What it is and who owns itabout, customAbout and owners

The name

name is how the database, the web UI, logs, alerts and routes from other interfaces know it. Use the folder's name (as ductus new interface does), short and stable: lower-case words joined by -, saying what flows and between whom (adt-epic-to-lab). Don't rename an interface with messages waiting: messages are stored under the name, so a renamed interface is a new one; the old name's history stays under the old name, and anything still waiting there is sent by nobody.

The code

script is the TypeScript file, relative to the interface's folder, that exports transform(msg, meta) (and any function a destination names with transform:). ductus validate type-checks it, and the engine loads it at start.

  • Without a script, messages go to their destinations as they came. That's right for a relay; most interfaces have one.
  • A schedule source, and an HTTP source in respond mode, need one: there, the code makes the message or the answer.
  • What the code returns decides: a message to send, null to filter it (kept, with the reason), or a thrown error to quarantine it for a person (nuance).

timeout is the longest the code may run for one message without pausing (time waiting on db(), fetch() or api() doesn't count), from 10ms to 10m; default 5s. It's the guard against code that never ends, such as a loop an unusual message never lets finish: past it, the code is stopped, its message quarantined, and the interface carries on; three in a row stop the interface until the engine restarts (nuance). Set it close to what the code needs: 500ms is plenty for most HL7 transforms. Interfaces in the shared pool wait while code on their thread runs, so a generous limit lets one runaway hold them all up that long; code that computes for seconds on purpose belongs in isolation: dedicated (delivery).

Your own fields

custom holds your company's documentation fields for the interface (a BAA reference, a change ticket, a runbook link), declared in docs-schema.yaml: Documentation fields. The engine ignores them; ductus validate checks them, and the web UI shows them.