Skip to content
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

Add ConfigLoader with deduplicated logging and try_examples config caching #249

Conversation

agriyakhetarpal
Copy link
Member

@agriyakhetarpal agriyakhetarpal commented Jan 10, 2025

Description

  • This PR introduces a caching mechanism where the requests to load the try_examples.json configuration file are deduplicated, and the tryExamplesConfigLoaded flag is preserved but managed more carefully.
  • A configLoadPromise has been introduced to handle concurrent requests with a basic cache that prevents console noise.
  • The change does not, however, address the issue of multiple attempts to load the config file at the moment.

Resolves (partially) #240

Additional context

In light of scikit-image/scikit-image#7644 where this problem was first noticed.

@agriyakhetarpal agriyakhetarpal added the enhancement New feature or request label Jan 10, 2025
@agriyakhetarpal agriyakhetarpal changed the title Add ConfigLoader with throttled logging and try_examples.json config caching Add ConfigLoader with throttled logging and try_examples config caching Jan 10, 2025
@agriyakhetarpal agriyakhetarpal marked this pull request as ready for review January 10, 2025 02:08
@agriyakhetarpal
Copy link
Member Author

I hope this is in line with what you had in mind, @Carreau! :)

I used a local scikit-image docs build to test it out on a page with thirty TryExamples buttons; here's a screen recording:

Screen.Recording.2025-01-10.at.7.45.16.AM.mp4

To compare with the previous functionality, this deployment: https://output.circle-artifacts.com/output/job/048f37f1-2a97-4826-b310-3c66a77deb9c/artifacts/0/doc/build/html/api/skimage.feature.html generates thirty errors, one per button.

@agriyakhetarpal agriyakhetarpal mentioned this pull request Jan 10, 2025
3 tasks
@agriyakhetarpal agriyakhetarpal added this to the 0.18.0 milestone Jan 10, 2025
@agriyakhetarpal agriyakhetarpal added bug Something isn't working and removed enhancement New feature or request labels Jan 10, 2025
@agriyakhetarpal agriyakhetarpal force-pushed the feat/throttle-try-examples-config branch from f1bb4ea to af7f8cd Compare January 10, 2025 19:07
@agriyakhetarpal
Copy link
Member Author

Thanks, @Carreau, yes, it makes sense to just remove the throttling. I did it based only on your suggestion, but it feels redundant, especially since we have just one configuration file per iframe/component.

I'll remove the configLoadPromise = null to keep the promise cached.

@agriyakhetarpal agriyakhetarpal modified the milestones: 0.18.0, 0.19.0 Jan 13, 2025
@agriyakhetarpal agriyakhetarpal mentioned this pull request Jan 14, 2025
3 tasks
Copy link
Collaborator

@Carreau Carreau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me – but again I'm not a JS expert.

@agriyakhetarpal agriyakhetarpal changed the title Add ConfigLoader with throttled logging and try_examples config caching Add ConfigLoader with deduplicated logging and try_examples config caching Jan 15, 2025
Copy link

@gabalafou gabalafou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was asked to review this pull request last week.

It's nice to see the inefficiency of making several concurrent network requests for the same data being addressed here, so thank you!

The changes introduced in this pull request look good to me, however I do have a couple questions and one concern.

I wasn't able to dive deep into issue #240, but one thing that immediately jumped out at me in that issue's description was:

I assume this happens because we run the JavaScript file per iframe

I just want to be clear that if this JavaScript file is getting loaded into multiple iframes on the same page, this PR will not prevent multiple network requests.

Another thing that caught my attention was the use of the word "retry" in the PR description and in the linked issue. As far as I can tell, there is no retry happening anywhere. To me the word retry means an intentional re-request when you know that the first request failed. I see no logic anywhere in this codebase that does that. I suspect that the word was meant in a different way, but because I'm not super familiar with the issue at hand, I'm bringing it up because I want to make sure I'm not missing something.

These questions bring me to my one big concern which is the lack of tests. In my mind, this is quite a bit of logic to leave untested. Furthermore, tests could go a long way to clarifying intent. For example, if these changes were intended to work across iframes, a good test case would show it working across multiple iframes.

Since the code has already been approved, I am not going to request changes, but lack of tests really worries me for long-term maintainability.

@agriyakhetarpal
Copy link
Member Author

Thanks, @gabalafou, for your detailed response and review! We did discuss this in our chat earlier in the month/late last month, and I feel your concerns about the lack of testing are in the right place – I'll be starting some work on adding a test suite soon enough, and test as much as can be tested without adding convoluted snapshot testing. I shall merge this PR for now as @Carreau has approved it, but here are my thoughts on your review:

I assume this happens because we run the JavaScript file per iframe

I just want to be clear that if this JavaScript file is getting loaded into multiple iframes on the same page, this PR will not prevent multiple network requests.

Another thing that caught my attention was the use of the word "retry" in the PR description and in the linked issue. As far as I can tell, there is no retry happening anywhere. To me the word retry means an intentional re-request when you know that the first request failed. I see no logic anywhere in this codebase that does that. I suspect that the word was meant in a different way, but because I'm not super familiar with the issue at hand, I'm bringing it up because I want to make sure I'm not missing something.

Oh, yes, you are right. I did mean the word "retry" in a different sense indeed – I think my intention was to reduce the noise within the console, wherein "attempt" is a better word. This PR is an attempt to cache the number of tries so that we don't log the next tries (and subsequent failures in the console if the config file doesn't exist), and not reduce the number of retries and not to reduce the number of attempts. I'll reword the PR description in accordance with the change. We currently load the config file with each iframe here:

# Search config file allowing for config changes without rebuilding docs.
config_path = os.path.join(relative_path_to_root, "try_examples.json")
script_html = (
"<script>"
'document.addEventListener("DOMContentLoaded", function() {'
f'window.loadTryExamplesConfig("{config_path}");'
"});"
"</script>"
)
script_node = nodes.raw("", script_html, format="html")

I would like to change this, but I would also like to do so iteratively in a new PR which would remain more fresh in my memory. We could try probably loading it globally and just once at the top of the HTML and making the event listener check for the return value from there (and probably pre-loading the script as well, so that it can help with #173).

This would also allow us to proceed with your suggestion for testing: "if these changes were intended to work across iframes, a good test case would show it working across multiple iframes" wherein we won't need to launch a headless browser to load the HTML, we could just use a regex pattern over the HTML sources (or use an HTML parser) to see that the JS file is being loaded only once (we can move the config file loading to a separate file, away from jupyterlite_sphinx.js, to distinguish the various machinery differences better). That would also allow reverting most of this caching functionality or perhaps removing it fully, as multiple attempts would no longer be made.

I'll remove this PR from closing the issue, as it resolves the problem only partially.

@agriyakhetarpal agriyakhetarpal merged commit 4059e7a into jupyterlite:main Feb 12, 2025
10 checks passed
@agriyakhetarpal agriyakhetarpal deleted the feat/throttle-try-examples-config branch February 12, 2025 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants