Replies: 1 comment
-
@theronic the paper describes the use of a lock tuple to address this type of races, so it's not "abusing" the design at all: https://zanzibar.tech/264hNtCdb3:0.BsRr6SyQa:1M We've also discussed the notion of idempotency keys, which could help the adoption in event-driven architectures, feel free to chime in if it helps with your application: #1503
Ideally, you treat data migration like you do with relational databases, by running multiple phases. With the use of preconditions, data races should be accounted for:
|
Beta Was this translation helpful? Give feedback.
-
"Last write wins" conditions during concurrent writes can result in stale Spice relationship that lead to persistent unwanted access — this is not a bug in Spice, just a reality of distributed systems with concurrent writers, even when the source of truth is consistent.
Our application is written in Clojure and uses Datomic as a source of truth. Datomic transactions cannot be wrapped around Spice writes, so without per-entity write locks or Spice Write Preconditions, this can lead to "last write wins" conditions. This affects daily operation but is most pronounced during long-running migrations.
I simulated concurrent writes to Datomic & Spice and can easily produce inconsistent state due to these scenarios. I was able to resolve all inconsistencies by adding an optimistic locking mechanism for each domain entity: I added a
:spice/version
counter to Datomic entities, which is incremented via CAS (compare-and-swap) after writing relationships to Spice. The compare-and-swap detects any concurrent writes and then retries syncing, resulting in very short-lived inconsistent state. Our workload is read-intensive, so this seems fine.How do others deal with this? Write Preconditions are complicated for the caller to manage, because which preconditions do you check, especially during bulk updates? I have considered abusing a Spice relation as a lock (e.g.
version
relation that gets incremented).Concrete example:
During concurrent execution, these commands can and do execute out-of-order and result in persistent unwanted user access:
Without write Preconditions, this can happen even if you compute the current relationships and issue bulk relationship updates (
:delete
&:touch
), or if you delete relationships usingRelationshipFilter
.Things get a bit more complicated during Spice schema & data migrations, where a migration could be long-running and span multiple Spice Commands. Even though Spice Commands are atomic, without write coordination, mid-migration writes can result in inconsistent Spice state. But at least we can query any entities that were written to during a migration and re-sync them when a migration completes.
Any advice on this would be appreciated.
Beta Was this translation helpful? Give feedback.
All reactions