fix(plugin-manager): parallel, non-blocking Plugins page update check#2667
fix(plugin-manager): parallel, non-blocking Plugins page update check#2667elibosley wants to merge 5 commits into
Conversation
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 35 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughThe PR changes plugin checking to run one scoped request per installed plugin with bounded concurrency, updating each row independently. It also adjusts plugin download and validation handling to report zero-length downloads and use unique temporary files. ChangesPer-plugin parallel update check
Estimated code review effort: 3 (Moderate) | ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
🔧 PR Test Plugin AvailableA test plugin has been generated for this PR that includes the modified files. Version: 📥 Installation Instructions:Install via Unraid Web UI:
Alternative: Direct Download
|
…blocking The Installed Plugins page renders the list quickly from local .plg data, but the per-plugin update check ran as a single serial request: ShowPlugins.php looped every plugin and, for each, spawned the plugin script to wget that plugin's pluginURL. The request returned all-or-nothing, so one slow or unreachable plugin URL left every row stuck spinning 'checking...' — the page appears hung. Take the network check off the critical path and parallelize it: - ShowPlugins.php: add a single-plugin mode (?one=<name>) that restricts the glob to one plugin and returns just its vid-/sid- line. - Plugins.page: replace the batched loadlist() post-init sweep with a bounded-concurrency (6) fan-out, one ?one= request per installed plugin, each with a 20s AJAX timeout. Rows resolve independently; the 'Update All' count is aggregated client-side. - Fail-safe: on timeout/error a row resolves to 'cannot check' instead of spinning forever. The page is never gated on update checks. A slow/unreachable plugin now only affects its own row, bounded by one timeout, never the whole page. No new caching introduced. Ref: OS-457 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
class 'remove' is on both the checkbox and the button of each plugin row, so the fan-out queued every plugin twice. Dedupe by data attribute so each plugin is checked once. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
23b4b19 to
b3a1b4b
Compare
The Plugins page tablesorter sorts on the Status column first
(sortList [[4,0],[1,0]]). Each per-plugin check rewrites that cell's
data rank, and the post-check trigger('update') re-applied the sort,
so rows jumped around as results landed one by one.
Use trigger('updateCache') instead: it refreshes the parsed cache (so a
later header-click sort still uses current status) without re-sorting,
so rows fill in place and the list no longer reorders while checking.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
emhttp/plugins/dynamix.plugin.manager/scripts/plugin (1)
334-352: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winClear the stat cache before reusing the validation tempfile
download()reuses the same$nameacross loop iterations, and itsfilesize($name)zero-length check can read stale metadata afterwgetoverwrites that path. Addclearstatcache(true, $name)before that check (or right after each download) so a previous iteration doesn’t mask a fresh file state.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@emhttp/plugins/dynamix.plugin.manager/scripts/plugin` around lines 334 - 352, The validation flow in the plugin manager reuses the same temp file name across multiple download attempts, so stale stat metadata can make the filesize check in download() misread a freshly overwritten file. Update the validation path around the temp file reuse in the plugin validation loop and the download() zero-length check to clear the stat cache for that path before checking filesize, so each iteration sees the current file state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@emhttp/plugins/dynamix.plugin.manager/scripts/plugin`:
- Around line 334-352: The validation flow in the plugin manager reuses the same
temp file name across multiple download attempts, so stale stat metadata can
make the filesize check in download() misread a freshly overwritten file. Update
the validation path around the temp file reuse in the plugin validation loop and
the download() zero-length check to clear the stat cache for that path before
checking filesize, so each iteration sees the current file state.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: af951c46-743a-455d-82b0-a8af82a9d987
📒 Files selected for processing (3)
emhttp/plugins/dynamix.plugin.manager/Plugins.pageemhttp/plugins/dynamix.plugin.manager/include/ShowPlugins.phpemhttp/plugins/dynamix.plugin.manager/scripts/plugin
🚧 Files skipped from review as they are similar to previous changes (2)
- emhttp/plugins/dynamix.plugin.manager/include/ShowPlugins.php
- emhttp/plugins/dynamix.plugin.manager/Plugins.page
Problem
The Installed Plugins page (
Tools > Plugins) can sit with every row spinningchecking...indefinitely, which makes the page look hung.Root cause
The page loads in two passes:
ShowPlugins.php?init=truerenders the table from local.plgdata. Fast.pluginscript towgeteach plugin'spluginURL.One slow or unreachable plugin URL blocked the whole pass, so every row stayed at
checking...until the slowest plugin resolved.Fix
ShowPlugins.php: add single-plugin mode with?one=<name>so one request checks one plugin and returns just that row's update/status fragment.Plugins.page: replace the automatic post-init sweep with bounded concurrency fan-out, one?one=request per installed plugin, each with a 20s AJAX timeout.Plugins.page: route manual Check For Updates through the same row-check flow. It resets rows tochecking..., disables the button while active, and re-enables when all row checks complete.cannot check; the page is never gated on one plugin host.scripts/plugin: harden validation downloads by using a per-process temp file, reporting zero-length downloads as explicit errors, and clearing PHP's stat cache beforefilesize().A slow/unreachable plugin now affects only its own row, bounded by one timeout. Automatic and manual checks use the same visible row behavior.
Scope / follow-up
plugin_attributes()path to reduce remaining per-pluginexecspawns forchanges/alert, remains a follow-up.cannot check, not as false hash/blank temp-file races.Testing
php -lclean onPlugins.pageandscripts/plugin.devgen.localwith backups at/tmp/Plugins.page.before-manual-row-check.1783609619and/tmp/plugin.before-manual-row-check.1783609619.onclick='checkPlugins(true)'instead ofopenPlugin("checkall", ...).valid, rc=0, and leaves no/tmp/validate-plugin-*files behind.Ref: OS-457 · prior art: #2352 (closed), #2421 (merged)