Thanks for the reply. Maybe I can use a very similar approach. Please let me know your thoughts on the following.
Currently the sentinel key-value has the following form.
TenantRoot/(TENANT_METADATA,
IDEMPOTENCY_DATA,
incarnation: int,
read_version: i64,
idempotency_uuid: uuid,) = (commit_vs: versionstamp,)
I could also introduce a “conflict” key range of the following form. There would be a one-to-one correspondence between a given sentinel-key and its associated “conflict” range.
(No data would be written in the “conflict” range).
TenantRoot/(TENANT_METADATA,
IDEMPOTENCY_CONFLICT_RANGE,
incarnation: int,
read_version: i64,
idempotency_uuid: uuid,)
When a transaction first attempts to write the sentinel key, I would include a read conflict range on the sentinel key’s “conflict” range. Lets name this transaction T1 and the conflict range T1_Conflict_Range.
In the event T1 fails with transaction_timed_out
or cluster_version_changed
, before attempting a retry, I would create a new transaction T2.
Transaction T2 would be very simple transaction that would attempt to do a write conflict range on T1_Conflict_Range, and commit.
After T2 successfully commits, I can attempt the retry logic. A successful T2 commit would indicate
- Either T1 successfully committed (for which we did not get an acknowledgement), followed by a successful T2 commit
- Or T2 successfully committed, and T1 will no longer be able to commit.
In either of the cases after T2 commits successfully, I should be able to rely on the presence or absence of the sentinel-key for subsequent decisions.
Do you see any potential issues here?