From section *2.4.2 Write* of the
# spicedb
t
From section 2.4.2 Write of the zanzibar paper: > Clients may modify a single relation tuple to add or remove an ACL. They may also modify all tuples related to an object via a read-modify-write process with optimistic concurrency control [21] that uses a read RPC followed by a write RPC: > > 1. Read all relation tuples of an object, including a per-object “lock” tuple. > 2. Generate the tuples to write or delete. Send the writes, along with a touch on the lock tuple, to Zanzibar, with the condition that the writes will be committed only if the lock tuple has not been modified since the read. > 3. If the write condition is not met, go back to step 1. > > The lock tuple is just a regular relation tuple used by clients to detect write races. Does SpiceDB have an equivalent lock mechanism? Or is the onus on us to prevent race conditions outside SpiceDB?
v
Yes. You can achieve this by writing a tuple that your application treats as the lock tuple, and then use the
Preconditions
block in
WriteRelationships
to make sure no other tuple except from the one of the lease holder exists.
t
Ah okay, so very similar to Zanzibar's description! I appreciate how true Authzed stayed to the original vision of the paper
Thank you!
v
yup! If something has proven to work, why change it? 😄
a
❤️ preconditions
b
> and then use the Preconditions block in WriteRelationships to make sure no other tuple except from the one of the lease holder exists @vroldanbet Is there a way of doing this check as-is using Preconditions? In my understanding you specify a certain filter and specify whether you want the precondition to pass if there are matches (
Precondition_OPERATION_MUST_MATCH
) or if no matches were found (
Precondition_OPERATION_MUST_NOT_MATCH
), but I don't see a way to check for "no other tuple except for the one of the lease holder exists", am I correct? In this case, I imagine the scenario to look something like: - Get the tuples for your object (either all of them of just the lock one) - Optionally perform some client-side logic based on the results - Send a
WriteRelationships
request with: - The operations you want to perform - A delete operation on the previous lock tuple - A create operation on a new lock tuple - A precondition requiring the previous lock tuple to still exist Is this how you would typically do it?
v
Yes, that's how you'd do it. You could also use other tuples that are no lock tuples, I wrote an example to another discord user earlier, but has the downside that you need to provide the full state of the relation as precondition as a way to reflect "no mutation has happened", and this may be many relationships, so the lock tuple has the benefit it's only one tuple to read. I don't see how the "no other tuple except the one of the lease holder" would work without doing two writes. The read + write approach seems more light weight on the system.
20 Views