The GitHub Actions job "CI" on 
grails-core.git/fix/dirty-checking-collection-tracking-8.0.x has failed.
Run started by GitHub user codeconsole (triggered by codeconsole).

Head commit for run:
f11e85549baad054bd6b7be59777578602ad40ba / Scott Murphy Heiberg 
<[email protected]>
Re-bind a collection borrowed from another entity to the entity it is assigned 
to

rewrap early-returned any value that was already a DirtyCheckableCollection,
so 'a.shares = b.shares' stored B's wrapper on A. Its parent still pointed
at B, so 'a.shares.add(x)' marked B dirty and left A clean, and the value
kept assigned=false, so a persister diffed a wholesale replacement element
by element.

The worst shape is silent: when the two collections are equal in content
the assignment is equality-suppressed, so A is never flagged at all, the
save finds only lastUpdated to write, and the addition is lost while B
absorbs it. That is what the new Mongo spec pins.

A wrapper from another entity is now re-bound - its raw target re-wrapped
against this parent, with assigned=true. Three things this must not do,
each covered by a spec:

- replace a store-specific wrapper (Neo4jList and friends) or a
  PersistentCollection with a generic one, which would reintroduce the
  Neo4j relationship-delete regression: those fail the exact-class check
  and are returned untouched;
- mistake another entity's wrapper for this property's own when the two
  entities are equal by business key: the owner is compared by identity,
  never equals, which on an association can initialise a proxy;
- re-bind onto an inner wrapper when an encoder has left one nested
  inside another, which would mark both entities dirty on every mutation.

The re-binding runs whatever the property held before, including null -
'new Entity(shares: other.shares)' has the same defect and does not
self-heal on insert, because the write-back assigns the field directly
and never reaches this method. Tracking is still never introduced for a
plain collection replacing an untracked value.

Docs: describe the re-binding, and scope it to the properties GORM
actually wraps. A one-to-many is held in a PersistentCollection, so the
previous hasMany example was a case this does not cover.

Report URL: https://github.com/apache/grails-core/actions/runs/34456754281

With regards,
GitHub Actions via GitBox

Reply via email to