ReactiveDag.Node.Transformers.AddMarkDirty (reactive_dag v0.17.0-rc.40)

Copy Markdown View Source

Wires dirties_on and augmented_by onto ReactiveDag.Node.Changes.MarkDirty, so ordinary Ash writes trigger the cascade with no host boilerplate.

Two wirings, because they answer two different questions

dirties_on names action TYPES and becomes ONE GLOBAL change. Global (rather than one per action) means actions declared later are covered too — the point of the feature is that no write site can be forgotten, and a per-action wiring would reintroduce exactly that risk. That is right for a source-fed LEAF, where every write is an observation.

augmented_by names specific ACTIONS and becomes one change added to EACH of those actions' own changes list. Per-action is not a weaker dirties_on here — it is the only wiring that works. On a COMPUTED node the library writes the rows itself through payload_action, which is an ordinary Ash write: a global change would make every recompute re-dirty the cell it just computed, and the drain would spin forever. Naming the human-facing actions excludes the payload upsert BY CONSTRUCTION rather than by a filter someone must maintain.

Marking exactly once

Ash concatenates an action's own changes with the resource's global changes and dedupes NEITHER (Ash.Changeset.run_action_changes/6). So an action named in augmented_by whose type is also in dirties_on would run MarkDirty twice. The frontier insert is ON CONFLICT DO NOTHING and would survive that, but schedule_drain would enqueue twice per write — so such actions are wired ONCE, by the global change, and skipped here.

The key derivation is resolved HERE, at compile time, and passed as options: the change then does no introspection per write.

Summary

Functions

after_compile?()

Callback implementation for Spark.Dsl.Transformer.after_compile?/0.

before?(_)

Callback implementation for Spark.Dsl.Transformer.before?/1.