test: Harden DST authored-state checks and workloads (#123)
This commit is contained in:
parent
16d15eebe5
commit
ad3e1a49e4
2 changed files with 10312 additions and 458 deletions
|
|
@ -68,8 +68,28 @@ independently of the database dialect.
|
|||
Create or update the row whenever the final domain value differs from the
|
||||
authored value. Remove it only when the domain value again equals the authored
|
||||
value and no projector still needs an override. At that point the domain column
|
||||
itself safely carries the authored value. No changes to the `CrdtDataField`
|
||||
existence policy, which is whenever its HLC is newer than the row HLC.
|
||||
itself safely carries the authored value. A `CrdtDataField` row is needed when
|
||||
its HLC is newer than the row HLC or it holds a preserved attempted value.
|
||||
Otherwise the field inherits the row's insertion HLC.
|
||||
|
||||
### Reinserting a deleted row
|
||||
|
||||
Inserting or upserting a deleted row keeps its identity and ownership and
|
||||
advances its delete/restore generation. The complete row is authored at a new
|
||||
insertion HLC, including preserved conflict claims, so unique claims receive
|
||||
a new age. This is a full-row write even when the upsert supplies an update
|
||||
column filter or predicate: those restrictions apply to visible existing rows.
|
||||
|
||||
Old field timestamps are removed. Only metadata needed to preserve a projected
|
||||
value remains, at that same insertion HLC; deleting that metadata would cascade
|
||||
to the only stored copy of its authored value. Projection uses the renewed
|
||||
claim ages before redundant field records are removed.
|
||||
|
||||
Outbound sync sends the full authored row without redundant field updates.
|
||||
Existing receivers still compare each field's HLC, so newer concurrent edits
|
||||
survive. The delete/restore generation is never reset, preventing an older
|
||||
deletion from hiding the restored row. These changes are atomic with the domain
|
||||
write and roll back together on failure.
|
||||
|
||||
### Diagnostic projection reason
|
||||
|
||||
|
|
@ -151,8 +171,9 @@ must be FK-safe; under the current policy the FK is nullable and releases to
|
|||
|
||||
Local insert, update, upsert, delete, and tombstone restoration need this plan
|
||||
before the underlying write can violate an immediate unique constraint. A
|
||||
full-row passthrough of an existing projected value remains non-authored;
|
||||
explicit/narrowed field writes author a new attempted value and field HLC.
|
||||
full-row passthrough translates an unchanged projected value back to its
|
||||
preserved authored value; explicit/narrowed field writes author the supplied
|
||||
value. Reinsertion follows the full-row reauthoring rule above.
|
||||
|
||||
## Outbound and rebuild behavior
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,20 @@ This is the `flag` policy. It is intentionally simple:
|
|||
This policy is the only unique-conflict policy in space for the current
|
||||
implementation.
|
||||
|
||||
## Local writes
|
||||
|
||||
Local inserts, updates, upserts, and restores obey the database's unique
|
||||
constraints. Two records cannot claim the same occupied value or non-null
|
||||
composite tuple in one local write. The database enforces this against stored
|
||||
rows and other rows in the batch; no additional domain reads are needed to
|
||||
pre-check uniqueness. A rejected write rolls back its domain changes and sync
|
||||
metadata together. Ordinary `ignoreConflicts` and upsert predicates still apply.
|
||||
|
||||
Claims accepted independently on disconnected replicas can still conflict when
|
||||
merged. The policy below preserves those accepted claims and chooses their
|
||||
visible values. Passing an unchanged displayed alternative through a full-row
|
||||
save preserves the underlying claim and follows the normal field-touch rules.
|
||||
|
||||
## Current Policy: Flag
|
||||
|
||||
Candidate construction, hidden-row release, canonical attempted-value lookup,
|
||||
|
|
@ -64,6 +78,34 @@ non-null constraint, the FK constraint, or the unique constraint itself.
|
|||
The rewritten value is a materialized data value, not a synced conflict class.
|
||||
The core CRDT protocol does not need to expose unique conflict objects to users.
|
||||
|
||||
### Reserved generated values
|
||||
|
||||
Authored values in unique text columns must not end in
|
||||
`__conflict__<UUID>`, `__hidden__<UUID>`, or `__park__<UUID>`, where the UUID uses
|
||||
the hexadecimal `8-4-4-4-12` shape. The marker is lowercase; hexadecimal letters
|
||||
can use either case. These names belong exclusively to projection, including
|
||||
hidden-row release and temporary writes. Non-unique text is unrestricted.
|
||||
|
||||
Non-nullable unique UUID columns that are not foreign keys reserve UUID version
|
||||
8 for generated alternatives (`xxxxxxxx-xxxx-8xxx-xxxx-xxxxxxxxxxxx`). Conflict,
|
||||
hidden-row, and temporary parking values use the same deterministic hash inputs
|
||||
as before, with the version marker set to 8. Authored version-8 values in these
|
||||
columns are rejected; ordinary UUID versions, including 4, 5, and 7, remain
|
||||
supported. Primary keys, foreign keys, nullable UUID columns, and non-unique UUID
|
||||
columns do not use synthetic UUID release and are not subject to this rule.
|
||||
|
||||
Local writes and incoming sync facts enforce this rule with
|
||||
`OfflineSyncReservedValueException`. Rejected transactions do not advance
|
||||
authored data or sync progress. A full-row update/upsert can echo its own
|
||||
unchanged materialized alternative: it keeps the original authored claim and
|
||||
uses the normal field-touch semantics. Explicitly authoring an alternative on
|
||||
another record is rejected, including exchanges of displayed alternatives.
|
||||
|
||||
This keeps the existing deterministic text suffix construction. The resolver does
|
||||
not search currently occupied values for a free alternative. The original claim
|
||||
is what gets exported, so ordinary conflict projection and bootstrap remain
|
||||
valid under the input rule.
|
||||
|
||||
## Why Flag Is The Current Default
|
||||
|
||||
The `flag` policy avoids the hard second-order effects caused by hiding or
|
||||
|
|
|
|||
Loading…
Reference in a new issue