Oracle REST Data Services (ORDS) has always had strong support for generating Entity Tag (
ETag) HTTP Headers. Entity Tags are an important aspect of the HTTP protocol, they help reduce needlessly re-transmitting unchanged resources (aka Conditional GET) and they can also be leveraged to provide optimistic locking and thus prevent lost updates.
I recommend reading this post by Joe Gregorio for a detailed explanation of the benefits of generating and using ETags properly.
How ORDS generates ETag Headers
ORDS supports three ways to generate
- Secure Hash – The bytes of the resource’s headers and body are hashed using a secure digest algorithm, which guarantee’s that anytime a header or the content of the resource changes, it’s
ETagheader value also changes. This is the default strategy
- Query – The RESTful Service developer enters an SQL query. Every time a resource changes then the results of this query must also change
- None – No
ETagheader is generated for the resource
Each of these options has different strengths.
Secure Hash is the most reliable means for generating an ETag, if the resource or it’s headers change, the ETag is guaranteed to also change.
Generating the Hash requires examining every byte of the resource’s headers and every byte of it’s body, before the
ETagheader can be generated. Since HTTP requires that HTTP Headers are sent before the body, this means that the entire contents of the resource must be temporarily buffered while the
ETagis computed. For large resources this buffering may noticeably increase latency and increase the amount of RAM required.
Note that for typical resources, whose size is in the order of hundreds of KBs, this buffering overhead is not significant, and thus using a secure Hash is the sensible default.
Sometimes it is possible to design a database table to know exactly when a row in the table changes, for example the table may have a version column or the table may be configured to use row level dependencies.
In these cases it may be beneficial to use a custom query to generate the
ETag. Instead of hashing the entire representation of the resource, ORDS will just hash the results returned from this custom query. ORDS will not need to buffer the entire representation in memory.
However ORDS will need to perform the additional query to generate the
ETag, as well as the query to generate the resource representation.
For typical resources, the overhead of the network round trip for the additional query is far greater than the overhead for the secure hash. Only for very large resources will the custom query out-perform the secure hash strategy.
There is also the risk that the custom query does not capture all of the data that may affect the representation of a resource. For example if a resource is composed from multiple rows in a table or rows from multiple tables, then the query must be designed to check the version state of each of those tables and rows. As the design of a resource evolves over time and the query used to generate the resource changes, it is easy to forget to keep the custom
ETagquery in sync. If this is not done then the
ETagvalue may no longer change everytime the resource changes, and clients will miss updates to the resource, so this strategy may not be as robust as the secure hash strategy.
ETagis generated, then no buffering is required, but all the benefits of Entity Tags will also be lost.
The entire resource will be regenerated and retransmitted for each and every request and there will be no means to perform concurrency control on the resource.