-
Notifications
You must be signed in to change notification settings - Fork 699
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
Optimise Library page load time when channels have large Thumbnail #12530
Optimise Library page load time when channels have large Thumbnail #12530
Conversation
@@ -291,6 +294,14 @@ def filter_available(self, queryset, name, value): | |||
return queryset.filter(root__available=value) | |||
|
|||
|
|||
class ChannelThumbnailView(View): |
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.
For writing unit test for this is there any existing setUp
method that will set up a channel metadata model?
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.
If you look in the test_content_app.py
file in the content
app, you should see some examples.
computed: { | ||
thumbnailBackground() { | ||
return { | ||
backgroundColor: this.$themeTokens.surface, | ||
backgroundImage: this.thumbnail ? `url('${this.thumbnail}')` : '', | ||
backgroundImage: this.resolvedThumbnail ? `url('${this.resolvedThumbnail}')` : '', |
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 we can do a high-level fix here, where we just modify the channels
on the library page.
Now it is affecting all the cards on the library page. I don't know where to make changes for that.
Build Artifacts
|
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 should work without any frontend changes, so let's aim for that.
Changes to the channel metadata endpoint can be simplified, and avoid code duplication.
I suspect that the reason the frontend changes were needed is because the backend endpoint is not returning something that the browser interprets as an image file.
kolibri/core/content/api.py
Outdated
for item in items: | ||
item["included_languages"] = included_languages.get(item["id"], []) | ||
item["last_published"] = item["last_updated"] | ||
item["thumbnail"] = reverse( |
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 this might be doable using the field_map
class property which allows setting to a callable, that would allow the rest of the code not to be copy pasted here.
values = tuple( | ||
field for field in BaseChannelMetadataMixin.values if field != "thumbnail" | ||
) | ||
|
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.
So you would add here:
field_map = {
"thumbnail": _create_channel_thumbnail_url,
}
field_map.update(BaseChannelMetadataMixin.field_map)
Then in the module scope you can define this function:
def _create_channel_thumbnail_url(item):
return reverse("kolibri:core:channel-thumbnail", args=[item["id"]])
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.
Yes this works, can you share django/python docs covering field_map
?
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 is not a Django thing - so the documentation for it is in this code comment: https://github.com/learningequality/kolibri/blob/develop/kolibri/core/api.py#L139
@@ -19,6 +19,7 @@ | |||
<script> | |||
|
|||
import ContentIcon from 'kolibri.coreVue.components.ContentIcon'; | |||
import { ChannelResource } from 'kolibri.resources'; |
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.
If the ChannelThumbnail endpoint is working as intended, it should be returning a valid file if fetched - so you should just be able to use the URL directly as a file URL.
If this is not working, we need to make some tweaks, but when it is working correctly, this should require no frontend changes at all.
@@ -291,6 +294,14 @@ def filter_available(self, queryset, name, value): | |||
return queryset.filter(root__available=value) | |||
|
|||
|
|||
class ChannelThumbnailView(View): |
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.
If you look in the test_content_app.py
file in the content
app, you should see some examples.
kolibri/core/content/api.py
Outdated
def get(self, request, channel_id): | ||
channel = get_object_or_404(models.ChannelMetadata, id=channel_id) | ||
thumbnail = channel.thumbnail | ||
response = FileResponse(thumbnail) |
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 am not confident this will be sufficient - the file is base64 encoded, which has a prefix with the mimetype. I think it is likely you would need to use the base64 decode method before serving this as the contents of a file: https://docs.python.org/3/library/base64.html#base64.b64decode
@rtibbles can you take another look? |
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.
A couple of considerations, and a typo.
Have not yet manually tested!
I made the changes. |
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.
Looks good, after manual QA, this will be good to merge (after we've released 0.17.0).
cc @pcenov |
@radinamatic - no issues observed while manually testing, implemented as specified. Good to go! |
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.
Code changes look good, manual QA checks out, this is ready to go!
Summary
As mentioned in the issue this PR does the following changes:
channel_thumbnail
as a img fileChannelMetaData
endpoint to return a URL to thumbnail instead directly returning a base64 encoded URL. This will cause async loading for thumbnails in the frontendScreenCast
Screencast from 02-08-24 01:44:04 PM IST.webm
References
Fixes #12502
Reviewer guidance
Open the library page and observe the channels load immediately, but the corresponding thumbnails loads asynchronously
Testing checklist
PR process
Reviewer checklist
yarn
andpip
)