#FHIR: Subscribing to a server

Apr 16, 2014

This question has come up several times lately, so I thought I’d show how to subscribe to a server. Below is pseudo code for subscribing to a server. It assumes that you have [base] - the address of the server, and a local store for settings (could be an ini file or a database), a client that can do http, and a bundle class that matches the semantics of a Bundle (e.g. an atom feed or it’s JSON equivalent), and load from the http outcome. The logic is pretty simple:

  • get the latest _history from the server
  • follow the next links till they run out, aggregating the content
  • store the feed.updated from the first response to use for next time you do it
procedure Subscribe(base)
  client = connectToServer(base) // and maybe get the conformance statement
  loop
    sleep(however long you want)
    feed = downloadUpdates(client)
    foreach entry in feed.entries *working backwards* // see note below
      process entry however you want
  until it's time to stop
procedure downloadUpdates(client)
  lasttime = store.getProp('LastTime')
  master = new Bundle()
  next = null
  i = 1
  do
    log('Downloading Updates (page('+i+')')
    if (next != null)
      feed = new Bundle(client.fetch(next))
    else if (lasttime != null)
      feed = new Bundle(client.fetch(base+'_history?_since='+lasttime))
    else
      feed = new Bundle(client.fetch(base+'_history')
    master.entries.addAll(feed.entries)
    if (next == null)
      store.setProp('lastTime', feed.updated)
    next = feed.link['next']
    i++
  until next == null
  return master

Notes:

  • for bonus marks, you could add a _count parameter and ask for as many resources per page from the server as you can get - that reduces the load on the network a little, and the lag time some
  • The outcome of the fetching loop is a single bundle that lists all the updates on the server since the last time in reverse chronological order. Whether you have to process in the correct order depends on what you are doing
  • If you want to see a real implementation of this, look at the class org.hl7.fhir.sentinel.SentinelWorker in the FHIR SVN (see under build/implementations/java)