Enabled and Disabled Nodes

In the old CR, this was called “hidden”, but we felt that enabled and disabled captured the intent better.

If a node is disabled, the system should behave as if this node would not exist. This means:

  • you are not able to query for this node
  • you are not able to query for any child node: If you removed the node, all children would be removed as well.
  • these rules must only apply in frontend, when viewing the site. In backend, you should still see the disabled nodes, so that you can e.g. enable them again.

Cross-Cutting Concerns

Because all API methods on the read side need to implement proper handling of enabled/disabled behavior, we call this a cross-cutting concern. The complexity of the CR appears to be that there are quite some distinct concerns which somehow all interleave with each other; making it hard to build a classical layered architecture which hides some of this complexity.

#Event Structure

Modelling events for enabling/disabling of nodes is rather easy, as you only say “node X should be disabled now”; but the projection has to recursively mark all nodes below as disabled as well.

#Projector Logic

Our basic assumption is that we want to build the transitive closure (of the start node and all sub nodes), and create a “disabling node X leads to node Y being unavailable” relationship.

To implement that, we implemented a new database table called TODO; which says “because node X was explicitly disabled, we disable node Y”.

We fill this database table by directly walking the tree structure in SQL (via a recursive Common Table Expression); so that way we can avoid numerous roundtrips from PHP to SQL and back again.

Then, at query time, we join the nodes with this TODO table; to filter out disabled nodes if we are in the frontend.

Disabling a node is more complex than O(1)

You might notice that disabling a node is the first operation we explained which is not having O(1) complexity - but we believe this is OK because often, the number of subnodes affected by a hide should be relatively minor compared to all the nodes in the system.

currently we build up this table for all content streams; we could theoretically only build it for the live content stream.