-
Notifications
You must be signed in to change notification settings - Fork 280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Live suggestions for homepage package search #1080
Conversation
Hello, @DaniruKun! This is your first Pull Request that will be reviewed by SourceLevel, an automatic Code Review service. It will leave comments on this diff with potential issues and style violations found in the code as you push new commits. You can also see all the issues found on this Pull Request on its review page. Please check our documentation for more information. |
5d5d26c
to
6969e1b
Compare
There seems to be a mix of EEx and We don't want to make the whole front page a live view because it's resource intensive and a popular page. Can you make only the search component a live view instead? |
@ericmj To answer point 1. - technically we can, but it's now considered the "old" syntax that will be deprecated at some point in favour of the HEEx way of doing things, and I think the .heex extension makes it very clear where it can be used. About 2. - what do you mean? In my implementation, nothing changes in terms of page load times (or first contentful paint) - the request starts out as a regular HTTP GET and gets upgraded to a WS connection if the client supports it. Of course, you will see a slight increase in memory usage because of the stateful nature of LiveView, however as you'll see we never keep more than 5 package results in the LiveView socket state. All things considered, the benefit from the better UX and less page loads outweighs the extra cost of memory and CPU imho. |
4ee69f5
to
5968b05
Compare
Ah yes, we should use the HEEx syntax 👍 .
Isn't it possible to make section of the page a liveview instead of making the whole page a liveview? |
Maybe you are talking about Live Components? Even then, they still require a LiveView - you have to replace the default Phoenix Controller with it regardless. |
If using a small liveview component in a larger page means that the whole page needs to be changed, like here: https://github.com/hexpm/hexpm/pull/1080/files#diff-ae87547521f78e46f7a0c59f22cc2715f4af4e0b6fc213c3b68b45a08b6456c5R58 and here: https://github.com/hexpm/hexpm/pull/1080/files#diff-ae87547521f78e46f7a0c59f22cc2715f4af4e0b6fc213c3b68b45a08b6456c5R132, along with replacing the controller action with a liveview this does not seem feasible or maintainable. When looking at the data sent over the websocket after the page load it looks like almost the entire page is sent over the websocket again. I don't understand how render time and CPU usage can be unaffected when it's doing this? |
@DaniruKun you can do This way, you can convert only the search input to LiveView+HEEx, leaving the remaining of the page untouched. I believe this is what @ericmj's proposing.
To clarify, the concern is not the rendering time per se, but mostly doing the queries twice. It will most likely be fine but given this is the home page, which is likely the most accessed page, starting with only the widget style seems like a sane choice to assess the impact it will have on prod. |
Ah got it, now it's clear. I'll try out that helper then, thanks! |
5968b05
to
b219593
Compare
Implemented it using @josevalim 's suggestion, now the old controller and router should be untouched, and the search LiveView is much simpler. Feel free to test locally with the seeded data and propose adjustments to the event parameters 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lib/hexpm_web/live/search_live.ex
Outdated
|
||
@impl true | ||
def handle_event("search", %{"search" => query}, socket) | ||
when byte_size(query) <= @query_size_limit_bytes do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this check it's not possible to do large search queries at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we keep a guard for this? If so, what should be the limit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good overall but I think the search results should be moved to the dropdown. Now you will get both the browsers suggestions and our search suggestions.
I think the main issue I stumbled into is that the version of Bootstrap in Hex is very old, and does not properly support datalists, so it might need some ugly style hacks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we keep a guard for this? If so, what should be the limit?
No, a limit is not necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the main issue I stumbled into is that the version of Bootstrap in Hex is very old, and does not properly support datalists, so it might need some ugly style hacks.
I think a dropdown may look better. That way we can also add it to the search in the navigation bar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About the datalist - see comment #1080 (comment)
I adjusted the template to no longer have a dangling |
2704f75
to
e5faf30
Compare
e5faf30
to
3afa105
Compare
I like this improvement but cannot merge it in its current state because the browser's dropdown overlaps the datalist making it not usable. I think one solution could be to replace the browser's dropdown with our own instead of using a datalist. |
Ah you mean the browser's autocomplete. I think it can be disabled, then there shouldn't be any overlap anymore. The |
@ericmj I disabled any form of browser autocomplete/caching for the form, so now it should be clean. Please check that it is the desired behaviour. |
I still think that it should be a dropdown because we can add it to the search in the navbar and it's jarring when the content below the search results jumps around when the search results change. |
Closing because PR is stale. |
Rationale
At the moment, users that want to quickly get a reference about a certain package using the web UI, have to perform 2 separate requests:
These additional steps require user's time, and re-doing a query requires a separate request again using a new connection.
Solution
As a PoC, I replaced the homepage search form with a LiveView, with a suggestion box that gets updated with query results from the server.
hexpm-demo.mp4
For now, the Phoenix update trigger is configured so that initial typing start does not send an event (since there isn't much point in performing a search with 1-2 chars), but an event will be sent after 1500ms from the first interaction.
This throttling interval is chosen because the average person's typing speed is 40 WPM, so 60s / 40w = 1.5s / word. Most Elixir packages are composed of a single word, so as soon as the user finishes typing the query, it will be sent to the server and handled. Of course this interval is up for discussion, but in my opinion setting it any lower might introduce too much load on the server.
Potential optimisations and improvements
Caching
I briefly experimented with persisting the
package_top
assign, and make the server first perform a lookup on that, before falling back to a DB query, but quickly dropped the idea since I don't have enough data to back up that most users search for the top 10 packages (besides, direct links to them are available on the home page already anyway).One idea could be to keep a small denormalised Mnesia / ETS table in memory for the top N most searched packages, and periodically update it based on search ranking.
Private orgs
Since it is a bit difficult to pass assigns between
Conn
andSocket
, only public org repos will appear in the suggestion results.Other additions
Closes #1078