Hacker News new | ask | show | jobs
by jchrisa 3402 days ago
Calvin is a generalized consistency protocol, that we use in FaunaDB to support relational semantics (but not SQL) in our database.

Multi-query transactions can be useful, but the FaunaDB query language is functional, rather than declarative like SQL, so composing queries that can do everything you want is usually easier than SQL.

1 comments

How would you perform the classic "transfer money from one account to another" operation?

Would you create a single operation that reads one record, checks that it's enough, then adds the amount to another record?

Or maybe you'd first read both accounts, then issue a conditional write operation that makes sure the data hasn't changed before doing the write?

FaunaDB's query language makes it straightforward to do it the first way. All queries are serializable, so any preconditions checked would gate transaction commit as you would expect, and read-modify-write style transactions work.

edit: here's an example in our Scala DSL:

  Let {
    val amount = 50
    val balanceA = Select("data" / "balance", Get(Ref("accountA"))
    val balanceB = Select("data" / "balance", Get(Ref("accountB"))
    If(Gteq(balanceA, amount),
      Do(
        Update(Ref("accountA"), Obj("data" -> Obj("balance" -> Subtract(balanceA, amount)))),
        Update(Ref("accountB"), Obj("data" -> Obj("balance" -> Add(balanceB, amount)))),
        "Transfer Success"
      ),
      "Insufficient Funds"
    )
  }
Is the wire format roughly isomorphic to the structure above? Or does the Scala library convert this code-like structure into something simpler/flatter?

(BTW, would be nice if I could read your API docs without signing up for an account.)

It is isomorphic; right now it's layered onto JSON, but eventually we will support CBOR on the wire as well. Internally everything is CBOR with LZ4 block compression.

The docs will eventually be available without an account.