Implementation ticket: #13
I am yet unsure which approach to use for showing/hiding nodes.
The problem
- When you hide a node, all sub nodes should automatically be unreachable as well; so hiding/showing is recursive.
- Regarding working at hiding/showing nodes with dimension fallbacks - I think the rule must always be: When an anchestor node (in a particular CS/DSP) is hidden, the node itself is not reachable.
- thus, we can either store the hidden/non-hidden information on the Node itself (i.e. the row in the DB); or we store it differently).
- Problem when storing it on the Node itself: you effectively hide only the node in the Visible Dimension Space Points; i.e. if you hide "german" and another node exists for "swiss german", this is not affected by the hiding operation. Maybe this is what the user expects?? Unsure still about this!
Solution 1: introducing Restriction Edges
(as suggested by Bernhard)
The idea is to capture the relationship between the user's intention (i.e. hiding a certain node); and the effects of that operation (i.e. all nodes which are now hidden because of this intention).
This would mean we have a separate DB table restrictionEdge
looking as follows:
- ContentStreamIdentifier
- DimensionSpacePoint
- OriginNodeAggregateIdentifier: the node which was hidden by the user
- AffectedNodeAggregateIdentifier: the node which should actually be hidden by the user's action
i.e. for a tree of three nodes:
If I hide "a", I would get the edges "a->a" (to hide a itself), and the edges "a->b", "a->c"; all in their respective CS Identifiers / DSPs.
On forking a ContentStream, all these edges would need to be copied (similar to HierarchyEdges)
Enforcing these constraints
- on the query level, we would add a join with
restrictionEdge
on CS, DSP and AffectedNodeAggregateIdentifier
- if we find a match, we know this node is hidden (because some node above it was hidden)
Benefits of this solution
- pretty straightforward implementation
- can be easily extended to roles / starttime / endtime by adding properties on the
hierarchyEdge
Drawbacks of this solution
- when e.g. having 100.000 nodes in 3 dimensions, when hiding the root node, we actually add 300.000 rows to the DB table.
Open Questions
- still unsure how much the additional join will performance-wise impact the already-quite-complex DB queries
- How to model this in Events? I think we have two "camps" here:
- I (Sebastian) would only capture the infos in the event that a certain node was hidden, and create all the connections in the DB itself (similar as I implemented it for deletion). However, this somehow limits the usefulness of the event stream (e.g. you cannot answer the question "is node X currently visible" by looking at the event stream only)
- Bernhard/Bastian would either have a huuuge event (e.g. in the example above with 300.000 affectedNodeAggregateIdentifiers); or 300.000 events; which I (sebastian) see as a big problem performance wise.
- This discussion is IMHO a specialization of #21
Alternative: Check access at Query time
Alternatively to materializing the restrictions at the write side, we could also check the access of nodes at query time.
While this may sound prohibitively expensive at first (if things are checked for every node), we
can probably spend things up a lot because the Nodes needed to render a single page are very
often highly-connected trees -- e.g. when rendering a menu, you need a certain subtree of Document Nodes; and when rendering content, you need a certain
subtree of content.
The idea now is that we only need to do this recursive checking when fetching the root of the
tree; and not when fetching leaves (as we then have all information readily consumable).
Hopefully, we can create a Cache in ContentSubgraph which allows to speed this up tremendously.
The idea is still pretty rough; but I'd like to discuss it to see if it is relevant.
Benefits of this solution
- hiding/showing nodes does not depend on the number of subnodes below
Drawbacks of this solution
- by looking at the event stream, we cannot know whether a node is currently visible or not.
Alternative: Application Layer
We could also decide that the recursive checking is NOT done at all; but you are responsible
yourself to handle this in the application when fetching roots. This is actually pretty much
the (undefined) behavior of the old CR when checking this in detail.