Skip to content

Orphan stubs when removing mutually-referencing subjects in one save (cascade sweep) #1112

Description

@alistair3149

Problem

When a Subject is removed from its page (or its page is deleted) while still referenced by another Subject, the Neo4j projection reduces it to a stub rather than deleting it, keeping the incoming relation valid (#1080). But when two or more subjects that reference each other are removed in the same savePage/deletePage, the removals cascade: stubbing one drops the relation that made another "referenced", so a subject can end up as a stub with no remaining incoming reference — an orphan stub.

Example (A -[rel]-> B and B -[rel]-> A, both removed in one save):

  • Both are classified as referenced (each has an incoming relation from the other).
  • Reducing each to a stub deletes its outgoing relations, so after both are processed each has lost the relation that referenced it.
  • Result: two orphan stub nodes — :Subject nodes with only id + wiki_id, no name, no schema label, no HasSubject edge, and no incoming relation.

Path: Neo4jProjectionStore::removeSubjects() / reduceSubjectToStub().

Impact

Harmless in the supported readers, and self-healing:

  • Neo4jSubjectLabelLookup filters on name + schema label — a stub has neither, so it never surfaces.
  • Neo4jPageIdentifiersLookup traverses :HasSubject — a stub has none.
  • RebuildGraphDatabases.php rebuilds the projection from scratch and normalises them away.

But a raw MATCH (n:Subject) via nw.query (Lua), the Cypher REST API, or {{#cypher_raw}} does enumerate orphan stubs (they keep the :Subject label). No stale data leaks — a stub carries only id + wiki_id — so this is phantom-node / count-inflation, not data exposure.

Robust fix

Cascade-sweep newly-orphaned stubs at the end of the write transaction: after the removals, delete any :Subject node left with no HasSubject edge and no incoming non-HasSubject relation (i.e. unreachable).

Notes / history

Low priority: NeoWiki is not in production, the graph is a rebuildable projection, and the stubs are invisible to the structured readers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions