The library-owned DDL, callable from a host migration — the suspension table
ReactiveDag.Suspension reads and writes:
defmodule MyApp.Repo.Migrations.AddReactiveDag do
use Ecto.Migration
def up, do: ReactiveDag.Migration.up()
def down, do: ReactiveDag.Migration.down()
endThe table name resolves exactly as Suspension's reads do — an explicit
:suspension_table option, else config :reactive_dag, suspension_table:,
else "reactive_dag_suspension" — so a host that sets the config gets a
migration matching the table the runtime queries, with no second place to
keep in sync.
Options (both directions):
:suspension_table— override the resolved table name for this migration only (rare; the config is the normal home).
This is the ONLY table the library owns. Every node's results live in that node's own resource, with its own migration — there is no second table shadowing them.
Migrating from the dirty queue
There is no data migration from the old reactive_dag_dirty table, and this
is deliberate rather than an omission. A queue row recorded a CONCLUSION —
"this cell needs recomputing" — while a suspension records a CAUSE — "this
change stopped here". Translating one into the other would mean re-deriving,
at migration time, the graph walk that produced the conclusion, against a
graph that has since changed. The translation is not sound.
The correct sequence is: drain the old queue to empty on the old code, deploy
the new code, then drop_dirty/1. It is kept out of down/1 so a host
sequences it deliberately.
Summary
Functions
Drop the suspension table and its index.
Drop the old dirty-frontier table.
Create the suspension table and its point index.
Functions
Drop the suspension table and its index.
Drop the old dirty-frontier table.
Run this ONLY after the old queue has drained to empty on the old code and the new code is deployed. An undrained mark is outstanding WORK, and this destroys it with no way to recover what it named — the queue was the only record that the work was pending.
Kept out of down/1 on purpose, so a host sequences it as its own migration
rather than having it ride along with a rollback.
Create the suspension table and its point index.