Size / Priority
Rationale
#392 bundled two independent durable-state stores. Its SQLite half is being implemented now (a SqliteClient SqlPool adapter plus SqliteDurableStateStore on RelationalDurableStateStore), which closes the visible gap in the backend matrix. The Cassandra half does not share that path and should not hold the issue open.
Cassandra has no UPDATE … WHERE revision = ? returning an affected-row count in the relational sense, so optimistic concurrency has to go through lightweight transactions (IF NOT EXISTS / IF revision = ?) — a Paxos round-trip per write, with the latency cost that implies.
Prior art in this repo
CassandraJournal already made this move: its append claims its sequence range with an LWT on the metadata row before writing events (#475). Before that it was a plain read-modify-write, and because a CQL INSERT is an upsert, two racing writers both "succeeded" while one event silently vanished. A durable-state store must not repeat that shape — the CAS has to be conditional server-side, not checked in the client.
Acceptance criteria
Size / Priority
Rationale
#392 bundled two independent durable-state stores. Its SQLite half is being implemented now (a
SqliteClientSqlPooladapter plusSqliteDurableStateStoreonRelationalDurableStateStore), which closes the visible gap in the backend matrix. The Cassandra half does not share that path and should not hold the issue open.Cassandra has no
UPDATE … WHERE revision = ?returning an affected-row count in the relational sense, so optimistic concurrency has to go through lightweight transactions (IF NOT EXISTS/IF revision = ?) — a Paxos round-trip per write, with the latency cost that implies.Prior art in this repo
CassandraJournalalready made this move: its append claims its sequence range with an LWT on themetadatarow before writing events (#475). Before that it was a plain read-modify-write, and because a CQLINSERTis an upsert, two racing writers both "succeeded" while one event silently vanished. A durable-state store must not repeat that shape — the CAS has to be conditional server-side, not checked in the client.Acceptance criteria
CassandraDurableStateStoreimplementingupsert/load/delete.docs/…/persistence/overview.mdx.