[XWI-133] add queries to fetch page hierachy information#24048
[XWI-133] add queries to fetch page hierachy information#24048Kharonus wants to merge 3 commits into
Conversation
- https://community.openproject.org/wp/XWI-133 - add two internal queries - add contracts, input and result model - HINT: this PR is a first step of https://community.openproject.org/wp/XWI-107 - next step is amending the search service
|
Caution The provided work package version does not match the core version Details:
Please make sure that:
|
| module Providers | ||
| module Internal | ||
| module Queries | ||
| module Internal |
There was a problem hiding this comment.
I hate it. And here I give the 🎤 to @NobodysNightmare and he can tell me: "Told you so."
What is happening? I voted to use a namespace called "internal" for queries and commands, that are not exposed via the registry. But I completely overlooked, that we already have an internal namespace for the provider type.
So, I'm ready to revisit that decision. WDYT? Shall I move all (2) queries out of this namespace and basically we rely that not exposing those query via the registry is the only indicator, that those are considered for "internal" use only?
There was a problem hiding this comment.
I'd be fine to move internal queries out of the Internal namespace to avoid confusion.
There was a problem hiding this comment.
Mh. Wait a minute. This PR exposes a problem with PRs that are too small: I can't see how those queries are intended to be used, there are no callers to them.
And this is kinda crucial here, because I am starting to get confused. Apparently you are planning for the PageHierarchy query to be internal. That would mean they are only used "inside" the provider. On the other hand, I know that they will be used for a feature that works across providers.
To me those two things don't line up yet. Either an outside caller wants to call those queries (making them non-internal) or another query wants to use them.
Do you have a preview of the PR that intends to use the queries somewhere already?
There was a problem hiding this comment.
No, those are indeed internal. They will be used from the search_pages query. When searching, we no longer return a list of page infos, but a list of page hierarchies then.
There was a problem hiding this comment.
Moved out of internal namespace
|
Missing tests ... |
|
Warning Flaky specs
🤖 Ask Copilot to investigateCopy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer. |
| ) | ||
| end | ||
|
|
||
| def wiki_result_from_wiki(wiki, provider:) |
There was a problem hiding this comment.
🟡 This method name is ambiguous, though I understand why you chose it.
The thing is that in other places we talk about a "page info result", when we don't return a PageInfo, but a Dry::Result(PageInfo). It is a hint at the fact that you don't get the thing directly, but there is a result to unpack first.
This is not the case here. Here we wanted to clarify that you don't get a Wiki (the AR model), but a ...::Results::Wiki`. Short: a wiki result.
It would also sound weird to call this method wiki_from_wiki.
Another thing I notice is that the other methods are called *_to_*, but this one is called *_from_*.
So yeah. I don't have good ideas, but take these bad ones:
ar_wiki_to_wikiactiverecord_wiki_to_wikiwiki_model_to_wikiwiki_to_adapter_wiki
There was a problem hiding this comment.
Yes, I agree. Let me choose a better name
There was a problem hiding this comment.
Hell, I chose one of the bad ones :D
| identifier: wiki.id.to_s, | ||
| provider:, | ||
| name: wiki.project.name, | ||
| # FIXME: internal wiki currently has no notion of a single root page, nor an official "entrypoint" |
There was a problem hiding this comment.
Alternatively we could link to the project's overview page. We take its name as well, so why not also taking its href?
In many cases the "first main page" will already be linked in the hierarchy anyways (one level deeper).
There was a problem hiding this comment.
I agree, in fact, the URL is not used yet anywhere. And we did say, that we want to encourage the understanding of "the project is the wiki".
will change
|
|
||
| def call(input_data:, auth_strategy:) | ||
| Adapters::Authentication[auth_strategy].call do |user| | ||
| wiki_page = WikiPage.visible(user).find_by(id: input_data.identifier) |
There was a problem hiding this comment.
🟡 Mh. Do we have any chance to include(:ancestors) or will this not fly, because that's a recursive relation?
There was a problem hiding this comment.
it's recursive, if you execute that relation you see multiple SQL statements in the logs, all the same fetching the next parent.
| json_hash.fetch(key) { throw :xwiki_error, Failure(Results::Error.new(source: self, code: :invalid_response)) } | ||
| end | ||
|
|
||
| def dig_json(json_hash, *keys) |
There was a problem hiding this comment.
❗ Uh this is interesting. In a very recent PR of mine (#24049) I decided against the usage of dig, because it didn't behave the way I wanted it to.
I am leaving this here for you to decide, but hear me out :D
Essentially dig looks nice to go into unknown data at first, because it works well with the expected data as well as with unexpected data and it even mixes arrays and hashes:
{ a: [{ c: 42 }] }.dig(:a, 0, :c)
=> 42
{ a: [{ c: 42 }] }.dig(:a, 100, :c)
=> nil
{ a: [{ c: 42 }] }.dig(:a, 0, :d)
=> nilHowever, as soon as the structure mismatches in unexpected ways, you start receiving weird errors:
{ a: [{ c: 42 }] }.dig(:a, :b, :c)
(irb):1:in 'Hash#dig': no implicit conversion of Symbol into Integer (TypeError)This means error handling gets weird. You have to react to both nil responses and exceptions. That of course combines with the usual weakness of not being able to distinguish a "real" nil and a missing value.
There was a problem hiding this comment.
I agree, I can make a more sophisticated implementation of the base class method.
There was a problem hiding this comment.
took your approach and ported it to xwiki requests concern.
| def json_to_ancestors(data, provider:) | ||
| page_title = fetch_json(data, "title") | ||
|
|
||
| invalid_hierarchy_types = %w[document wiki] |
There was a problem hiding this comment.
What are the valid hierarchy types? Should we maybe use an allow list here?
Since we only expect pages/spaces, I can't imagine that it's an open list of valid types.
There was a problem hiding this comment.
hmm, I'm only interested in type == space here, so I can swap the expectation. This grew from slightly different code.
| ancestors = dig_json(data, "hierarchy", "items").filter do |item| | ||
| next false if invalid_hierarchy_types.include?(fetch_json(item, "type")) | ||
|
|
||
| fetch_json(item, "label") != page_title |
There was a problem hiding this comment.
🔴 Is that a valid condition?
What if I have a hierarchy like
- Overview
- Rooms
- Storage Room
- Overview
- Storage Room
- Rooms
This hierarchy now contains "Overview" twice. Of course that's not great, but I also wouldn't know why we should prevent it.
Is this to filter the reference to the page itself? Couldn't this be solved by dropping the first/last element of the hierarchy? (probably both, because we filter wikis as well ^^)
There was a problem hiding this comment.
Ah, crap.... this is bad, because right now I only have the name. Yeah, I need the identifier here, too.
But no, the reason why I exclude ancestors with the same title as the page, is that the WebHome appears in the ancestors, too, and it has the same label as the "leaf".
There was a problem hiding this comment.
All WebHome? I am still wondering whether we can (safely and reliably) do things like "skip last element" or "skip first element".
But probably not, because a "Leaf Space" would have a WebHome and a "Leaf Final Page" would not, right?
There was a problem hiding this comment.
exactly, I found both examples. :/
|
Warning Flaky specs
🤖 Ask Copilot to investigateCopy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer. |
Ticket
XWI-133
What approach did you choose and why?