Guaranteeing consistency in FaunaDB when overwriting a document that was read in the past

91 Views Asked by At

I have a FaunaDB which I would like to interact with as a document store. I have a single api which:

  1. Reads an entire document from FaunaDB
  2. Mutates that data arbitrarily based on input to the api
  3. Writes the mutated back while guaranteeing the data has not been mutated
  4. Error or retry if the read was not current when attempting to write

In Postgres to guarantee consistency I would simply use a where clause. Since Fauna is distributed I assume the equivalent is more nuanced, for example my understanding is that CosmosDB writes idiomatically send the eTag of the read to check to guarantee consistency.

1

There are 1 best solutions below

0
On

In fauna all write transactions run through the transaction pipeline at strict serializable isolation. So all we need to maintain the desired invariant over our two transactions is to make sure we tie our write to a read that checks that the document hasn't been updated while we were futzing around in our own code. Let $ref be some ref that we have magical knowledge of. Let $ts be the result of Select("ts", Get($ref)) during our original read transaction. Let $expr be whatever we want to update our document to. Then:

If(Equals(Select("ts", Get($ref)), $ts), Update($ref, $expr), Abort("try again"))

Of course, you probably want to do something smarter: It's probably a better idea on failure to return the updated document. Exactly how you want to structure that is up to you but

{error: "ts out of date", updated: Get($ref)}

Would work well enough, you'd just need some case analysis in on the resulting object to see if you had the doc or a failure. You could even get all fancy and move the instance read into a Let but the runtime characteristics are much the same (the read is cached locally during eval, we won't do it twice).