{"action":"closed","issue":{"url":"https://api.github.com/repos/neos/contentrepository-development-collection/issues/12","repository_url":"https://api.github.com/repos/neos/contentrepository-development-collection","labels_url":"https://api.github.com/repos/neos/contentrepository-development-collection/issues/12/labels{/name}","comments_url":"https://api.github.com/repos/neos/contentrepository-development-collection/issues/12/comments","events_url":"https://api.github.com/repos/neos/contentrepository-development-collection/issues/12/events","html_url":"https://github.com/neos/contentrepository-development-collection/issues/12","id":372185093,"node_id":"MDU6SXNzdWUzNzIxODUwOTM=","number":12,"title":"Discussion of Show/Hiding Nodes","user":{"login":"skurfuerst","id":190777,"node_id":"MDQ6VXNlcjE5MDc3Nw==","avatar_url":"https://avatars0.githubusercontent.com/u/190777?v=4","gravatar_id":"","url":"https://api.github.com/users/skurfuerst","html_url":"https://github.com/skurfuerst","followers_url":"https://api.github.com/users/skurfuerst/followers","following_url":"https://api.github.com/users/skurfuerst/following{/other_user}","gists_url":"https://api.github.com/users/skurfuerst/gists{/gist_id}","starred_url":"https://api.github.com/users/skurfuerst/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/skurfuerst/subscriptions","organizations_url":"https://api.github.com/users/skurfuerst/orgs","repos_url":"https://api.github.com/users/skurfuerst/repos","events_url":"https://api.github.com/users/skurfuerst/events{/privacy}","received_events_url":"https://api.github.com/users/skurfuerst/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2018-10-20T07:43:22Z","updated_at":"2018-12-02T08:16:51Z","closed_at":"2018-12-02T08:16:50Z","author_association":"MEMBER","body":"Implementation ticket: #13 \r\n\r\nI am yet unsure which approach to use for showing/hiding nodes.\r\n\r\n## The problem\r\n\r\n- When you hide a node, all sub nodes should automatically be unreachable as well; so hiding/showing is *recursive*.\r\n- 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.*\r\n  - 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).\r\n  - 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!*\r\n\r\n## Solution 1: introducing Restriction Edges\r\n\r\n(as suggested by Bernhard)\r\n\r\nThe 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).\r\n\r\nThis would mean we have a separate DB table `restrictionEdge` looking as follows:\r\n\r\n- ContentStreamIdentifier\r\n- DimensionSpacePoint\r\n- OriginNodeAggregateIdentifier: the node which was hidden by the user\r\n- AffectedNodeAggregateIdentifier: the node which should actually be hidden by the user's action\r\n\r\ni.e. for a tree of three nodes:\r\n\r\n- a\r\n  - b\r\n  - c\r\n\r\nIf 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.\r\n\r\nOn forking a ContentStream, all these edges would need to be copied (similar to HierarchyEdges)\r\n\r\n### Enforcing these constraints\r\n\r\n- on the query level, we would add a join with `restrictionEdge` on CS, DSP and AffectedNodeAggregateIdentifier\r\n- if we find a match, we know this node is hidden (because some node above it was hidden)\r\n\r\n### Benefits of this solution\r\n\r\n- pretty straightforward implementation\r\n- can be easily extended to roles / starttime / endtime by adding properties on the `hierarchyEdge`\r\n\r\n### Drawbacks of this solution\r\n\r\n- 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.\r\n\r\n### Open Questions\r\n\r\n- still unsure how much the additional join will performance-wise impact the already-quite-complex DB queries\r\n- How to model this in Events? I think we have two \"camps\" here: \r\n  - 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)\r\n  - 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.\r\n  - This discussion is IMHO a specialization of #21\r\n\r\n\r\n## Alternative: Check access at Query time\r\n\r\nAlternatively to materializing the restrictions at the write side, we could also check the access of nodes at query time.\r\n\r\nWhile this may sound prohibitively expensive at first (if things are checked for every node), we\r\ncan probably spend things up a lot because *the Nodes needed to render a single page* are very\r\noften *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\r\nsubtree of content.\r\n\r\nThe idea now is that we only need to do this recursive checking when fetching the root of the\r\ntree; and not when fetching leaves (as we then have all information readily consumable).\r\nHopefully, we can create a Cache in ContentSubgraph which allows to speed this up tremendously.\r\n\r\nThe idea is still pretty rough; but I'd like to discuss it to see if it is relevant.\r\n\r\n### Benefits of this solution\r\n\r\n- hiding/showing nodes does not depend on the number of subnodes below\r\n\r\n### Drawbacks of this solution\r\n\r\n- by looking at the event stream, we cannot know whether a node is currently visible or not.\r\n\r\n\r\n## Alternative: Application Layer \r\n\r\nWe could also decide that the recursive checking is NOT done at all; but you are responsible\r\nyourself to handle this in the application when fetching roots. This is actually pretty much\r\nthe (undefined) behavior of the old CR when checking this in detail."}}
{"actor":{"display_login":"skurfuerst"}}