Site icon Hay on FHIR

Transactions in DSTU-2

One of the many changes that occurred in DSTU-2 (at least in the candidate spec) was the way in which transactions are managed in REST. Not so much what a transaction is (that’s reasonably well defined) – but how it is implemented. For a start, a bundle (used for a number of purposes as well as a transaction) is now a resource in it’s own right (rather than an Atom feed).

But apart from this structural change, the transaction has become more closely aligned with the simpler REST interactions – it’s easier to see how a transaction can be thought of as a sequence of simple interactions that succeed or fail as a whole. Let’s start by taking a look at the Bundle from the perspective of Transactions, including some more tricky aspects to how IDs are managed when you want to create a resource that needs to be referenced by another within the same transaction.

The Bundle resource

A Bundle has a specific element (Bundle.type) that indicates what the bundle is being used for. The values that are applicable in this discsussion are ‘transaction’ and ‘transaction-response’- representing the transaction request and the response after the transaction has been processed by the server. Here’s a full list of the options.

Bundle.base gives the base Url for all resources in the bundle. In most scenarios this is the address of the server processing the transaction – though it’s certainly possible for resources to reference different servers. (this adds significantly to the complexity however).

Bundle.link has links – we’ll talk about them some other time.

The Bundle.entry element is where the actual resources are placed – along with quite a lot of other stuff that tidies up the overall transaction processing. There are a number of child elements to Bundle.entry, but there are 3 that we’ll focus on here:

The resource element contains the resource itself. Any FHIR resource. Not much more to say about this at the moment (though we’ll have a bit to think about when we discuss the resource ID).

The transaction element is rather more interesting. It is used in the request bundle (bundle.type=’transaction’) and has the following child elements:

The transactionResponse element is used in a response to a transaction (Bundle.type = ‘transaction-response’). It mirrors what the response would be if the interaction for that resource was being performed across the simple REST interface, and you can see the details on the REST API page

Resource IDs and referencing newly created resources

From the perspective of a resource ID, most of the time, a transaction is reasonably straightforward.

But what do you do when one resource refers to another resource that is being created as a result of that transaction? For example, when recording a Blood Pressure, it is common to have 3 resources: A ‘parent’ resource that states the observation is a Blood Pressure, and separate Systolic & Diastolic Observations to which it refers (using the related element).

The spec does state that the server must update any IDs it reassigns:

“If the server assigns a new id to any resource in the bundle as part of the processing rules above, it SHALL also update any references to that resource in the same bundle as they are processed.”

But doesn’t go into a lot of details about how & when that re-assignment occurs. And, according to the spec, a POST “SHALL be a FHIR Resource without an id element”. This probably needs to be clarified, but given that the test servers currently ignore any ID in a POSTed resource (rather than rejecting the operation), the following pattern seems reasonable:

If the resource being created is the target of a reference (the ‘Systolic’ & ‘Diastolic’ observations in the example above), then give it an ID (likely a UUID), and set the method to POST. Resources referencing it can then use that ID as the reference. The server will then assign a real ID and update the references accordingly, returning the updated resources in the response bundle (usually – see ‘prefer’ below).

One thing that a transaction no longer does, is to specifically return the original ID after it has been replaced – which was useful in DSTU-1 when the ‘cid:’ prefix was used to indicate a new resource, but is less so now. However, if the client does need to know what ID was assigned to a resource it has created, there are a couple of options to do this if you want to. Most of the time the client won’t care what the new ID is – so long as it has been saved this it is OK. If it does care, then there are a couple of options:

In order to allow the client to know the outcomes of processing the entry, and the identities assigned to the resources by the server, the server SHALL return a Bundle with type set to transaction-response that contains one entry for each entry in the transaction, in the same order, with the outcome of processing the entry. (Incidentally, I’m not sure how GETting a new resource fits here – presumably they are added at the end of the collection)

eTag

We’ve referred to eTags (Entity Tag) a couple of time. The eTag is like a ‘hash’ for the resource, and is used when performing updates to make sure that the no-one else has updated the resource since it was read. This is often called ‘optimistic’ locking and has the basic process:

  1. Read the resource
  2. Update it on the client
  3. Save it back to the server.

Obviously it will fall down in step 3 if some other client were to update the resource (their update would be replaced) so we can modify the process like this:

  1. Read the resource, with the server returning an eTag (eg in the HTTP header)
  2. Update it on the client
  3. Save it back to the server, including the eTag (in the header if simple REST or the ifMatch element if a transaction). The server compares the submitted eTag with the eTag of the current resource – rejecting the update if they don’t match.

So it’s up to the server to decide if eTags are required (which makes sense). Incidentally, the specification for eTags doesn’t define the algorithm for eTags – so a server can decide how ‘strong’ the creation of the eTag is. The client, of course, doesn’t need to know – from its perspective it’s just an opaque token being passed back and forth.

Conformance

We’ve referred to server behavior a few times (If the server supports…). The conformance resource is the place where this behavior is specified of course. Interestingly, there currently doesn’t seem to be a way for a server to require the use of eTags.

To return the resource (or not)

And wrapping up this post, one other thing of interest is that the client can specify whether it wishes to have the actual resources returned in the response bundle. The transactionResponse element will always be present, but if the client doesn’t want the full resource to be returned in the response then they can include the ‘Prefer’ http header in the request with a value of ‘return=minimal’ – and it’s up to the server to determine the behaviour if not specified.

 

Exit mobile version