Skip to content

lib: one cascade graph for every store - #68

Draft
aberoham wants to merge 1 commit into
NicTool:mainfrom
aberoham:references
Draft

lib: one cascade graph for every store#68
aberoham wants to merge 1 commit into
NicTool:mainfrom
aberoham:references

Conversation

@aberoham

@aberoham aberoham commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Destroy a group on json or toml and its nameservers stay behind. Same for a
user's sessions and a zone's records. mysql removes all three, because it has a
constraint and the file stores have nothing.

Measured on 96f4799 through lib/<entity>/index.js, one fixture per pair:

destroy child constraint mysql json toml
group nameserver nt_nameserver_ibfk_1 gone stays stays
user session nt_user_session_ibfk_1 gone stays stays
zone zone_record nt_zone_record_ibfk_1 gone stays stays

Each backend decided this on its own: mysql reads it off a FOREIGN KEY, the file
stores never implemented it. Their destroy() is the whole story — filter own
array, save, return; group, user and zone are the same method over a different
array.

references.js says the rule once and both sides follow it: the file stores call
cascade() from destroy(), mysql goes on using its constraints.
references.test.js holds whichever store is configured to that one
declaration, and doubles as the repro. Every case seeds a second parent whose
child has to survive, so taking too much fails as loudly as taking too little,
and via builds the fixture, so a wrong field name fails too.

Watch how you check this. mysql reads a session through its user
(session/store/mysql.js joins nt_user on u.deleted=0), so a session that
survived still reads as absent once the user is gone. Each doomed child is
deleted a second time and has to report there was nothing left.

Verified on mysql, json and toml — targeted green, ./test/run.sh green, no
skips or todos. Three negative checks, each run: drop a cascade() call and that
edge fails; drop the soft-deleted pass and nameserver and zone_record fail; save
the parent before cascading and the retry case fails.

Draft until #61 lands: it edits three files #61 rewrites, and #61 adds a fourth
edge. Measured there at e4bd365 — after destroying the group,
Delegation.delete({gid, oid, type}) returns true on json, meaning the row was
still there, and null on mysql. Its delete() takes the whole triple, so the
no-destroy branch in cascade() needs work rather than one more line in the
declaration.

Which children a hard delete takes with it was decided separately in each
backend. mysql has each of them from a FOREIGN KEY; the file stores have no
constraints and never implemented them, so destroying a group left its
nameservers behind, destroying a user left its sessions, and destroying a
zone left its records.

references.js names those three edges once. The file stores call cascade()
from destroy(), mysql goes on getting it from the constraints, and
references.test.js holds whichever store is configured to the same graph.
Each case seeds a second parent whose child must survive, so a store that
takes too much fails as loudly as one that takes too little.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014AUjj218gbhUHLi7kvDPtd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant