Skip to content

Refactor: Allow nchan scripts to exit if no listeners#2333

Merged
limetech merged 10 commits into
unraid:masterfrom
Squidly271:patch-8
Aug 14, 2025
Merged

Refactor: Allow nchan scripts to exit if no listeners#2333
limetech merged 10 commits into
unraid:masterfrom
Squidly271:patch-8

Conversation

@Squidly271

@Squidly271 Squidly271 commented Aug 12, 2025

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added a background probe to detect active live-listeners.
  • Enhancements

    • Switched to per-endpoint no-duplicate publishing to reduce redundant realtime notifications.
    • Standardized publish invocation and adjusted publish cadence to sleep longer when no data is present.
    • Many realtime channels now start continuously (monitor removed), simplifying subscriptions.
  • UX Changes

    • Removed automatic pausing/resuming of live updates and the realtime setting; dashboards stream continuously.
  • Chores

    • Updated copyright years.

@coderabbitai

coderabbitai Bot commented Aug 12, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Refactors the Nchan publish API (new publish signature and publish_noDupe replacing publish_md5), updates many callers to the new API and explicit args, removes monitor()/focus-based live-update pause behavior and related UI/config, adds a dummy client-side Nchan listener, and changes docker_load sleep cadence.

Changes

Cohort / File(s) Summary
Publish API core
emhttp/plugins/dynamix/include/publish.php
publish() signature changed to ($endpoint,$message,$len=1,$abort=true,$abortTime=30); legacy opt mapping removed; publish_md5() removed and replaced by publish_noDupe() with per-endpoint state and direct-message dedupe; explicit false set when no subscribers.
Publish callers (md5 → publish / noDupe)
emhttp/plugins/dynamix/nchan/update_1, emhttp/plugins/dynamix/nchan/update_2, emhttp/plugins/dynamix/nchan/update_3, emhttp/plugins/dynamix/nchan/ups_status, emhttp/plugins/dynamix/nchan/wlan0, emhttp/plugins/dynamix/nchan/vm_dashusage, emhttp/plugins/dynamix.docker.manager/nchan/docker_load, emhttp/plugins/dynamix.vm.manager/nchan/vm_usage, emhttp/plugins/dynamix/nchan/wg_poller
Replaced publish_md5(..., true) calls with publish(...) (or use publish_noDupe() where appropriate). docker_load removed a Helpers require and now sleeps 1s when output present, 10s when absent.
Explicit publish args & listener probing
emhttp/plugins/dynamix/nchan/file_manager, emhttp/plugins/dynamix/nchan/device_list, emhttp/plugins/dynamix/nchan/parity_list
Added explicit len/abort args to many publish() calls (e.g., ,1,false); removed MD5 gating and JSON-encoding in device/parity loops; added mainPingListener probe publishes ("ping") to detect subscribers.
Client-side subscriber & monitor changes
emhttp/plugins/dynamix/ArrayOperation.page, emhttp/plugins/dynamix/DockerContainers.page, emhttp/plugins/dynamix.vm.manager/VMUsageStats.page, emhttp/plugins/dynamix/DashStats.page, emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php, emhttp/plugins/dynamix/include/DefaultPageLayout/BodyInlineJS.php
Replaced .monitor() chaining with .start(), made NchanSubscriber.prototype.monitor() a no-op (compatibility), removed focus/visibility-based pausing/resuming logic and related UI (pageFocusFunction, nchan pause banner), and added a no-op mainPingListener subscriber started on DOM-ready.
Client UI / config removal
emhttp/plugins/dynamix/DisplaySettings.page, emhttp/plugins/dynamix/default.cfg
Removed the "Allow realtime updates on inactive browsers" UI block and deleted liveUpdate="yes" from default config.
Misc scripts - publish arg additions
emhttp/plugins/dynamix.docker.manager/scripts/container_size, .../scripts/update_container, emhttp/plugins/dynamix.plugin.manager/scripts/*, emhttp/plugins/dynamix/scripts/diagnostics, emhttp/plugins/dynamix/scripts/install_key, emhttp/plugins/dynamix/scripts/newperms, emhttp/plugins/dynamix/scripts/ssd_trim
Many scripts changed publish calls to include explicit len/abort args (e.g., publish('plugins', $msg, 1, false) or publish('diagnostics', $msg, 1, false)).
Helper rename
emhttp/plugins/dynamix/nchan/wg_poller
Renamed my_scale($value,&$unit)wg_scale($value,&$unit) and updated usages; removed unused $md5_old = -1.
Header year updates / minor non-API edits
emhttp/plugins/dynamix/nchan/session_check, emhttp/plugins/dynamix/nchan/vm_dashusage, emhttp/plugins/dynamix/nchan/wg_poller, emhttp/plugins/dynamix/nchan/ups_status, ...
Updated copyright/header years and minor metadata changes only.

Sequence Diagram(s)

sequenceDiagram
  participant Caller as Nchan Script
  participant NoDupe as publish_noDupe()
  participant Pub as publish()
  participant NChan as Nchan Server
  participant Clients as Subscribers

  Caller->>NoDupe: publish_noDupe(endpoint,message)
  alt message changed or no known listener
    NoDupe->>Pub: publish(endpoint,message,len,abort,abortTime)
    Pub->>NChan: POST message
    NChan-->>Pub: ack / no-subscriber
    Pub-->>NoDupe: true/false
    NoDupe-->>Caller: true/false
  else duplicate and listener known
    NoDupe-->>Caller: skip publish (no-op)
  end
Loading
sequenceDiagram
  participant DL as docker_load
  loop periodic
    DL->>DL: check output
    alt output present
      DL->>DL: publish("dockerload", output)
      DL->>DL: sleep(1)
    else no output
      DL->>DL: sleep(10)
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~35 minutes

Possibly related PRs

Suggested reviewers

  • ljm42
  • elibosley

Poem

I hop through channels, nose in the wire,
Swapped old crumbs for a cleaner publish choir.
I ping to see whether someone is near,
I sleep a beat when the air is clear.
🥕🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Squidly271 Squidly271 marked this pull request as draft August 12, 2025 17:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (2)
emhttp/plugins/dynamix.docker.manager/nchan/docker_load (1)

22-28: Logic bug: docker stats “no containers” case won’t hit the slow path.

shell_exec() returns an empty string when there’s no output; it’s rarely null. As written, you’ll almost always sleep(1), not sleep(10). Fix by checking for empty/whitespace output (and optionally common docker error strings you redirected to stdout with 2>&1).

Apply:

-  publish_noDupe("dockerload", $output);
-  if ( $output === null ) {
-    // slow down publishing if no containers are running
-    sleep(10);
-  } else {    
-    sleep(1);
-  }
+  publish_noDupe("dockerload", $output);
+  // Slow down if there's no meaningful output (no running containers or daemon not reachable)
+  if (!is_string($output) || trim($output) === '' ||
+      stripos($output, 'error response from daemon') !== false ||
+      stripos($output, 'cannot connect to the docker daemon') !== false) {
+    sleep(10);
+  } else {
+    sleep(1);
+  }

This preserves the intent, reduces needless loop iterations, and still leverages publish_noDupe()’s default abort=true to exit when no listeners.

emhttp/plugins/dynamix/nchan/wg_poller (1)

18-28: Fix out-of-range unit index and overflow in scale()

When $value is very large, $base can equal count($units), causing an out-of-bounds index. Also, the 1000-rounding bump can overflow $base without re-clamping. Clamp against the last valid index and guard the post-rounding increment.

Apply this diff:

-function scale($value, &$unit) {
-  $units = ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi','Yi'];
-  $size = count($units);
-  $base = $value ? floor(log($value, 1024)) : 0;
-  if ($base>$size) $base = $size-1;
-  $value /= pow(1024, $base);
-  $decimals = $value>=100 ? 0 : ($value>=10 ? 1 : (round($value*100)%100===0 ? 0 : 2));
-  if (round($value,-1)==1000) {$value = 1; $base++;}
-  $unit = $units[$base].'B';
-  return number_format($value, $decimals, '.', $value>9999 ? ',':'');
-}
+function scale($value, &$unit) {
+  $units = ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi','Yi'];
+  $last  = count($units) - 1;            // last valid index
+  $base  = $value ? (int)floor(log($value, 1024)) : 0;
+  if ($base > $last) $base = $last;
+  $value /= pow(1024, $base);
+  $decimals = $value>=100 ? 0 : ($value>=10 ? 1 : (round($value*100)%100===0 ? 0 : 2));
+  if (round($value,-1) == 1000 && $base < $last) {
+    $value = 1;
+    $base++;
+  }
+  $unit = $units[$base].'B';
+  return number_format($value, $decimals, '.', $value>9999 ? ',':'');
+}
🧹 Nitpick comments (8)
emhttp/plugins/dynamix/include/publish.php (1)

123-133: Make the “no-op” path explicit: return false when not publishing.

Right now the function falls through and returns null when the message is unchanged and a listener is present. Returning false explicitly keeps a consistent boolean interface with publish() and simplifies consumers.

Apply this diff:

-  if ( ($message !== ($msg_old[$endpoint]??null)) || !$listener[$endpoint]) {
+  if ( ($message !== ($msg_old[$endpoint]??null)) || !$listener[$endpoint]) {
     $msg_old[$endpoint] = $message;
     $msg_time[$endpoint] = time();

     $return = publish($endpoint, $message, $len, $abort, $abortTime);

     // if no listener, keep publishing whether or not its the same message.
     $listener[$endpoint] = $return ? true : false;

     return $return;
-  }
+  } else {
+    return false;
+  }
emhttp/plugins/dynamix/nchan/update_1 (1)

126-126: Switch to publish_noDupe() aligns with dedupe + “exit if no listeners” objective — confirm semantics.

  • With publish_noDupe('update1', $echo) defaulting to abort=true, this script will exit when there are no subscribers (after the abort window). Verify this is intended for update_1.
  • Minor: $md5_old defined earlier is now unused after moving away from MD5-based publishing. Consider removing it as cleanup.
emhttp/plugins/dynamix/nchan/ups_status (1)

135-135: publish_noDupe(): behavior change to exit if no listeners — validate intent and do small cleanup.

  • This call uses defaults (len=1, abort=true), so the script will terminate when there are no subscribers. Confirm this matches the desired behavior for ups_status.
  • Nit: $md5_old is still declared above but unused; safe to remove.
  • Nit: You cast OVERRIDE_UPS_CAPACITY after htmlspecialchars(). Since you cast to (int) anyway, htmlspecialchars() is redundant here.
emhttp/plugins/dynamix/nchan/file_manager (2)

255-255: Prefer publish()’s internal param overloading to avoid hard-coding len=1.

Per team convention, publish() sorts out overloads. You can pass only the abort flag and let len default to 1.

Apply:

-    publish('filemonitor', file_exists($active) ? 1 : 0,1,false);
+    publish('filemonitor', file_exists($active) ? 1 : 0, false);

258-258: Same here: rely on publish()’s overloads; pass only abort=false.

Apply:

-  publish('filemanager', json_encode($reply),1,false);
+  publish('filemanager', json_encode($reply), false);
emhttp/plugins/dynamix/nchan/wg_poller (2)

38-38: Prevent unit cross-talk; use distinct vars for RX/TX units

Reusing $unit by reference for both values is easy to misread and brittle. Using separate variables improves clarity.

Apply this diff:

-    if (count($row)>5) $echo[] = [$row[0], $row[5]?$now-$row[5]:0, scale($row[6],$unit)." $unit", scale($row[7],$unit)." $unit"];
+    if (count($row)>5) {
+      $rx = scale($row[6], $unit_rx)." $unit_rx";
+      $tx = scale($row[7], $unit_tx)." $unit_tx";
+      $echo[] = [$row[0], $row[5] ? $now - $row[5] : 0, $rx, $tx];
+    }

30-30: Remove unused legacy variable $md5_old

Leftover from publish_md5 path; it’s now unused.

Apply this diff:

-$md5_old = -1;
emhttp/plugins/dynamix/nchan/vm_dashusage (1)

24-24: Remove unused legacy variable $md5_old

This isn’t used anymore after migrating away from publish_md5.

Apply this diff:

-$md5_old = -1;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce9b3ab and 22abfc6.

📒 Files selected for processing (12)
  • emhttp/plugins/dynamix.docker.manager/nchan/docker_load (1 hunks)
  • emhttp/plugins/dynamix.vm.manager/nchan/vm_usage (2 hunks)
  • emhttp/plugins/dynamix/include/publish.php (5 hunks)
  • emhttp/plugins/dynamix/nchan/file_manager (1 hunks)
  • emhttp/plugins/dynamix/nchan/session_check (1 hunks)
  • emhttp/plugins/dynamix/nchan/update_1 (2 hunks)
  • emhttp/plugins/dynamix/nchan/update_2 (1 hunks)
  • emhttp/plugins/dynamix/nchan/update_3 (1 hunks)
  • emhttp/plugins/dynamix/nchan/ups_status (2 hunks)
  • emhttp/plugins/dynamix/nchan/vm_dashusage (2 hunks)
  • emhttp/plugins/dynamix/nchan/wg_poller (3 hunks)
  • emhttp/plugins/dynamix/nchan/wlan0 (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: Squidly271
PR: unraid/webgui#0
File: :0-0
Timestamp: 2025-05-31T05:10:13.120Z
Learning: Squidly271 prefers not to receive CodeRabbit reviews or feedback while PRs are in draft status. Only provide reviews after PRs are moved out of draft.
📚 Learning: 2025-08-10T20:48:52.086Z
Learnt from: Squidly271
PR: unraid/webgui#2326
File: emhttp/plugins/dynamix.vm.manager/nchan/vm_usage:93-93
Timestamp: 2025-08-10T20:48:52.086Z
Learning: In the unraid/webgui codebase, Squidly271 prefers the publish() function to internally handle parameter type overloading (e.g., accepting boolean true in place of buffer length 1) to avoid repetitive parameter specifications and maintain backwards compatibility. The publish() function in emhttp/plugins/dynamix/include/publish.php is designed to sort out these parameters internally rather than requiring explicit values at every call site.

Applied to files:

  • emhttp/plugins/dynamix/nchan/file_manager
  • emhttp/plugins/dynamix/nchan/update_2
  • emhttp/plugins/dynamix/nchan/vm_dashusage
  • emhttp/plugins/dynamix.docker.manager/nchan/docker_load
  • emhttp/plugins/dynamix/include/publish.php
📚 Learning: 2025-08-10T23:33:40.338Z
Learnt from: Squidly271
PR: unraid/webgui#2326
File: emhttp/plugins/dynamix/include/publish.php:46-55
Timestamp: 2025-08-10T23:33:40.338Z
Learning: In the unraid/webgui codebase, the publish() and publish_md5() functions in emhttp/plugins/dynamix/include/publish.php deliberately do not support 0-second timeouts for the abort mechanism. The use of the elvis operator (?:) for timeout parameters is intentional, as timeout values of 0 are not relevant and not supported. The minimum valid timeout should be greater than 0 seconds.

Applied to files:

  • emhttp/plugins/dynamix.docker.manager/nchan/docker_load
🔇 Additional comments (14)
emhttp/plugins/dynamix/nchan/session_check (1)

3-3: Header year bump only — LGTM

No functional changes. Safe and consistent with PR-wide copyright updates.

emhttp/plugins/dynamix/include/publish.php (3)

82-99: Abort-on-no-subscribers behavior is clear and robust — LGTM

Forcing $reply=false when no subscribers and gating exit on elapsed $abortTime meets the PR objective and simplifies upstream logic that checks publish() return values.


103-110: Per-endpoint dedupe state — LGTM

Static endpoint-scoped msg_old/msg_time/listener is a clean replacement for MD5-based dedupe and reduces CPU work on hot loops.


33-41: No legacy publish() calls detected—please verify external usage

Our search didn’t find any internal calls to publish() with a boolean as the third argument, so there’s no immediate breakage within this repo. However, per team preference for backwards compatibility, you can reintroduce minimal overload-handling in emhttp/plugins/dynamix/include/publish.php:

 function publish($endpoint, $message, $len=1, $abort=true, $abortTime=30) {
   static $abortStart = [], $com = [], $lens = [];

+  // Back-compat: treat a boolean third arg as the legacy “abort” flag
+  if (func_num_args() === 3 && is_bool($len)) {
+    $abort = $len;
+    $len   = 1;
+  }

Please confirm whether any external plugins or scripts call publish() with only three arguments and a boolean third parameter. If they do, keep the shim; otherwise it can safely be omitted.

emhttp/plugins/dynamix/nchan/update_3 (1)

162-162: Switch to publish_noDupe — LGTM

Migration away from publish_md5 aligns with the new dedupe approach and default abort-on-no-listeners behavior.

emhttp/plugins/dynamix.vm.manager/nchan/vm_usage (2)

3-4: Header year updates — LGTM


90-90: Switch to publish_noDupe — LGTM

Matches the new API and desired “exit when no listeners” semantics.

emhttp/plugins/dynamix/nchan/wlan0 (1)

69-69: Switch to publish_noDupe — LGTM

Consistent with the refactor across nchan scripts.

emhttp/plugins/dynamix/nchan/update_1 (1)

3-3: LGTM: header year update is correct.

emhttp/plugins/dynamix/nchan/ups_status (1)

3-3: LGTM: header year update is correct.

emhttp/plugins/dynamix/nchan/update_2 (1)

502-502: Migration to publish_noDupe() looks good; dedupe + abort-on-no-listeners achieved.

This change matches the refactor goal and should reduce redundant messages while letting the script exit when no subscribers.

emhttp/plugins/dynamix/nchan/wg_poller (1)

40-40: Verified: publish_noDupe() Defaults Ensure Dedupe and Abort Semantics

I’ve confirmed in emhttp/plugins/dynamix/include/publish.php (lines 103–108) that the signature is:

function publish_noDupe($endpoint, $message, $len = 1, $abort = true, $abortTime = 30) {
    …
}

$abort defaults to true, and $len to 1, matching the PR’s goal to dedupe messages and abort when there are no listeners.
Everything looks correct—approving these changes.

emhttp/plugins/dynamix/nchan/vm_dashusage (2)

3-4: LGTM: Updated copyright

Year ranges updated correctly.


112-112: publish_noDupe defaults confirmed

The signature in emhttp/plugins/dynamix/include/publish.php is:

function publish_noDupe($endpoint, $message, $len=1, $abort=true, $abortTime=30) {
    …
}

$len=1 ensures single‐byte length
$abort=true enforces “exit if no listeners”
$abortTime=30 seconds for the abort timeout

No changes needed—this call already uses the correct defaults.

Comment thread emhttp/plugins/dynamix/include/publish.php Outdated
Comment thread emhttp/plugins/dynamix/nchan/wg_poller Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
emhttp/plugins/dynamix/nchan/parity_list (1)

156-157: Typo in comment.

Minor readability nit: “timeoutto” should be “timeout to”.

Apply this diff:

-	//publish to the dummy listener with the timeoutto see if there are any subscribers
+	// publish to the dummy listener with the timeout to see if there are any subscribers
emhttp/plugins/dynamix/ArrayOperation.page (1)

509-513: Optional: Stop the dummy listener on page unload (symmetry with other subscribers).

For consistency with mymonitor/devices/paritymonitor cleanup and to prevent dangling sockets during navigation, stop mainPingListener on unload.

Add this inside window.onunload alongside the others:

try { mainPingListener.stop(); } catch(e) {}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22abfc6 and 4e733f9.

📒 Files selected for processing (3)
  • emhttp/plugins/dynamix/ArrayOperation.page (1 hunks)
  • emhttp/plugins/dynamix/nchan/device_list (1 hunks)
  • emhttp/plugins/dynamix/nchan/parity_list (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Squidly271
PR: unraid/webgui#0
File: :0-0
Timestamp: 2025-05-31T05:10:13.120Z
Learning: Squidly271 prefers not to receive CodeRabbit reviews or feedback while PRs are in draft status. Only provide reviews after PRs are moved out of draft.
📚 Learning: 2025-08-10T20:48:52.086Z
Learnt from: Squidly271
PR: unraid/webgui#2326
File: emhttp/plugins/dynamix.vm.manager/nchan/vm_usage:93-93
Timestamp: 2025-08-10T20:48:52.086Z
Learning: In the unraid/webgui codebase, Squidly271 prefers the publish() function to internally handle parameter type overloading (e.g., accepting boolean true in place of buffer length 1) to avoid repetitive parameter specifications and maintain backwards compatibility. The publish() function in emhttp/plugins/dynamix/include/publish.php is designed to sort out these parameters internally rather than requiring explicit values at every call site.

Applied to files:

  • emhttp/plugins/dynamix/nchan/device_list
🔇 Additional comments (2)
emhttp/plugins/dynamix/nchan/device_list (1)

569-576: Ignore JSON-encoding change – publish_noDupe already encodes arrays
The publish_noDupe() implementation (include/publish.php lines 112–114) checks is_array($message) and applies json_encode() before sending. Since $echo is a PHP array, it will automatically be serialized to JSON by publish_noDupe, matching the frontend’s use of JSON.parse. No update to the call site in device_list is required.

Likely an incorrect or invalid review comment.

emhttp/plugins/dynamix/ArrayOperation.page (1)

509-513: LGTM: Dummy ping listener initialization is correct.

The added no-op WebSocket subscriber is straightforward and aligns with the “exit if no listeners” design.

Comment thread emhttp/plugins/dynamix/nchan/parity_list
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
emhttp/plugins/dynamix/include/publish.php (1)

103-134: Enforce JSON‐encode error handling and consistent boolean return in publish_noDupe

The proposed changes can be applied safely—none of the ~20 call sites branch on a null return—so we should:

• Add JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE to json_encode()
• Log and return false on JSON failures for symmetry with publish()
• Always return a bool:
true when a listener is known or the publish succeeded
false otherwise (including skipped publishes)

Apply:

--- a/emhttp/plugins/dynamix/include/publish.php
+++ b/emhttp/plugins/dynamix/include/publish.php
@@ -103,11 +103,22 @@ function publish_noDupe($endpoint, $message, $len=1, $abort=true, $abortTime=30) {
   static $listener = [];

   if (!isset($listener[$endpoint])) {
     $listener[$endpoint] = false;
   }

-  if (is_array($message)) {
-    $message = json_encode($message);
-  }
+  if (is_array($message)) {
+    $json = json_encode(
+      $message,
+      JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
+    );
+    if ($json === false) {
+      my_logger(
+        'publish_noDupe: json_encode() failed: '.json_last_error_msg(),
+        'publish_noDupe'
+      );
+      return false;
+    }
+    $message = $json;
+  }

   // if abort is set, republish the message even if it hasn't changed
   // after $timeout seconds to check for subscribers and exit accordingly
@@ -133,6 +144,8 @@ function publish_noDupe($endpoint, $message, $len=1, $abort=true, $abortTime=30) {
     $listener[$endpoint] = $return ? true : false;
     return $return;
   }
+
+  return (bool)$listener[$endpoint];
 }

No callers rely on null vs. false—this makes the API predictable.

♻️ Duplicate comments (1)
emhttp/plugins/dynamix/include/publish.php (1)

13-15: Resolved: Avoid undefined-index on DOCUMENT_ROOT.

Thanks for addressing the earlier feedback by using the null-coalescing operator. This prevents CLI notices and keeps logs clean.

🧹 Nitpick comments (5)
emhttp/plugins/dynamix/include/publish.php (5)

39-41: Handle json_encode failures explicitly (invalid UTF-8).

json_encode can return false; logging and short-circuiting avoids posting "false" or empty bodies.

Apply:

-  if ( is_array($message) ) {
-    $message = json_encode($message);
-  }
+  if ( is_array($message) ) {
+    $json = json_encode($message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+    if ($json === false) {
+      my_logger('json_encode() failed: '.json_last_error_msg(), 'publish');
+      return false;
+    }
+    $message = $json;
+  }

51-57: Use a standard JSON Accept header.

'Accept: application/json' is the conventional media type; improves interoperability with proxies/middleware.

Apply:

-      CURLOPT_HTTPHEADER       => ['Accept:text/json'],
+      CURLOPT_HTTPHEADER       => ['Accept: application/json'],

61-78: Derive HTTP status via curl_getinfo instead of regex; capture before closing handle.

Parsing curl error text is brittle and locale-dependent. Use CURLINFO_RESPONSE_CODE and only then close/unset the handle.

Apply:

-  $reply = curl_exec($com[$endpoint]);
-  $err   = curl_error($com[$endpoint]);
+  $reply = curl_exec($com[$endpoint]);
+  // Must get HTTP code before closing the handle
+  $http  = curl_getinfo($com[$endpoint], CURLINFO_RESPONSE_CODE);
+  $err   = curl_error($com[$endpoint]);
   if ($err) {
     my_logger("curl error: $err endpoint: $endpoint");
-    curl_close($com[$endpoint]);
-    unset($com[$endpoint]);
-
-    preg_match_all("/[0-9]+/",$err,$matches);
-    // 500: out of shared memory when creating a channel
-    // 507: out of shared memory publishing a message
-
-    if ( ($matches[0][0] ?? "") == 507 || ($matches[0][0] ?? "") == 500 ) {
+    curl_close($com[$endpoint]);
+    unset($com[$endpoint]);
+    // 500: out of shared memory when creating a channel
+    // 507: out of shared memory publishing a message
+    if (in_array((int)$http, [500, 507], true)) {
       my_logger("Nchan out of shared memory.  Reloading nginx");
       // prevent multiple attempts at restarting from other scripts using publish.php
       touch("/tmp/publishPaused");
       exec("/etc/rc.d/rc.nginx restart");
       @unlink("/tmp/publishPaused");
     }
   }

82-99: Minor: prefer unset over assigning null for timers to avoid stale keys.

This keeps the per-endpoint state arrays a bit cleaner over long runtimes.

Apply:

-      // a subscriber is present.  Reset the abort timer if it's set
-      $abortStart[$endpoint] = null;
+      // a subscriber is present. Reset the abort timer if it's set
+      unset($abortStart[$endpoint]);

18-22: Edge case: allow "0" payloads in curl_socket().

The current truthiness check drops numeric zero or empty JSON strings. Use a length check to permit valid zero-ish payloads.

Apply:

-  if ($message) curl_setopt_array($com, [CURLOPT_POSTFIELDS => $message, CURLOPT_POST => 1]);
+  if ($message !== '') curl_setopt_array($com, [CURLOPT_POSTFIELDS => $message, CURLOPT_POST => 1]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e733f9 and 0b57133.

📒 Files selected for processing (1)
  • emhttp/plugins/dynamix/include/publish.php (4 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Squidly271
PR: unraid/webgui#0
File: :0-0
Timestamp: 2025-05-31T05:10:13.120Z
Learning: Squidly271 prefers not to receive CodeRabbit reviews or feedback while PRs are in draft status. Only provide reviews after PRs are moved out of draft.
📚 Learning: 2025-08-10T20:48:52.086Z
Learnt from: Squidly271
PR: unraid/webgui#2326
File: emhttp/plugins/dynamix.vm.manager/nchan/vm_usage:93-93
Timestamp: 2025-08-10T20:48:52.086Z
Learning: In the unraid/webgui codebase, Squidly271 prefers the publish() function to internally handle parameter type overloading (e.g., accepting boolean true in place of buffer length 1) to avoid repetitive parameter specifications and maintain backwards compatibility. The publish() function in emhttp/plugins/dynamix/include/publish.php is designed to sort out these parameters internally rather than requiring explicit values at every call site.

Applied to files:

  • emhttp/plugins/dynamix/include/publish.php

Comment thread emhttp/plugins/dynamix/include/publish.php

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
emhttp/plugins/dynamix/DashStats.page (1)

2423-2423: Switch to start() only is fine; optional visibility-based gating can reduce background load

Dropping monitor() removes focus/visibility throttling, so streams will continue while the tab is hidden. If that’s intentional per the refactor, no action needed. If you want to keep backend and client load down when the tab isn’t visible, consider gating subscribers with document.visibilityState (start on visible, stop on hidden) as a small enhancement.

Example approach (outside the shown ranges):

// Once at init:
function startStreams() {
  dashboard.start();
  <?if ($vmusage == "Y"):?> vmdashusage.start(); <?endif;?>
  <?if ($apcupsd):?> apcups.start(); <?endif;?>
}
function stopStreams() {
  if (dashboard.stop) dashboard.stop();
  <?if ($vmusage == "Y"):?> if (vmdashusage.stop) vmdashusage.stop(); <?endif;?>
  <?if ($apcupsd):?> if (apcups.stop) apcups.stop(); <?endif;?>
}
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'visible') startStreams();
  else stopStreams();
});
// On load:
startStreams();

Also applies to: 2425-2425, 2428-2428

emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php (2)

550-563: Auto-reload should also respect Shadowbox modals (and similar overlays)

With the nchanPaused guard removed, an active Shadowbox modal (used by openBox) won’t be detected by dialogOpen(), so the page may reload mid-operation. Expand the gate to include Shadowbox (or its container) visibility.

Apply this minimal diff to avoid reload while a Shadowbox is open:

-        if (! dialogOpen() ) {
+        if (!dialogOpen() && !$('#sb-container').is(':visible')) {
           location.reload();
         }

Alternatively (preferred for cohesion), broaden dialogOpen() itself to centralize the logic:

function dialogOpen() {
  return (
    $('.sweet-alert').is(':visible') ||
    $('.swal-overlay--show-modal').is(':visible') ||
    ($('#sb-container').length && $('#sb-container').is(':visible')) ||     // Shadowbox
    (window.Shadowbox && Shadowbox.isOpen === true)                          // extra safety
  );
}

Verification request:

  • Please verify that Shadowbox renders with #sb-container (or update the selector accordingly) in current builds.

15-17: Harden legacy Nchan monitor shim and verify load order

The inline snippet in HeadInlineJS.php runs before we’ve seen any evidence that the NchanSubscriber library (dynamix.js) is loaded. As a result, wrapping the prototype assignment in a one-time guard and deferring installation via window.load is the safest approach to avoid a ReferenceError.

Please verify that your page includes dynamix.js (which defines window.NchanSubscriber) either before this inline block or via your deferred install listener. If it does, the immediate attach() call will take effect; otherwise the load-event listener ensures compatibility.

Locations to check:

  • emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php (the inline shim)
  • The <script src=".../dynamix.js"> include in your DefaultPageLayout templates

Applied diff:

-// Legacy code.  No longer used in webGUI, and its purpose is removed, but plugins might still reference this prototype and its a fatal error to remove it.
-var subscribers = [];
-NchanSubscriber.prototype.monitor = function(){subscribers.push(this);}

+// Legacy shim. No longer used in webGUI. Kept for compatibility because plugins might still reference this prototype and it's a fatal error to remove it.
+// Preserve/initialize the global subscribers array for legacy consumers.
+var subscribers = window.subscribers || [];
+window.subscribers = subscribers;
+
+// Safely install the legacy monitor method only if/when NchanSubscriber is available.
+(function installLegacyNchanMonitor() {
+  function attach() {
+    if (window.NchanSubscriber && window.NchanSubscriber.prototype && !window.NchanSubscriber.prototype.monitor) {
+      window.NchanSubscriber.prototype.monitor = function(){ subscribers.push(this); };
+      try {
+        console.warn(
+          'Deprecated: NchanSubscriber.prototype.monitor is a no-op shim for compatibility and may be removed in a future release.'
+        );
+      } catch(e) {}
+    }
+  }
+  // Attempt now, and also once on window load in case NchanSubscriber loads later.
+  attach();
+  window.addEventListener('load', function lateAttach() {
+    attach();
+    window.removeEventListener('load', lateAttach);
+  });
+}());
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b57133 and c5d984d.

📒 Files selected for processing (8)
  • emhttp/plugins/dynamix.docker.manager/DockerContainers.page (2 hunks)
  • emhttp/plugins/dynamix.vm.manager/VMUsageStats.page (2 hunks)
  • emhttp/plugins/dynamix/ArrayOperation.page (3 hunks)
  • emhttp/plugins/dynamix/DashStats.page (2 hunks)
  • emhttp/plugins/dynamix/DisplaySettings.page (0 hunks)
  • emhttp/plugins/dynamix/default.cfg (0 hunks)
  • emhttp/plugins/dynamix/include/DefaultPageLayout/BodyInlineJS.php (0 hunks)
  • emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php (2 hunks)
💤 Files with no reviewable changes (3)
  • emhttp/plugins/dynamix/DisplaySettings.page
  • emhttp/plugins/dynamix/default.cfg
  • emhttp/plugins/dynamix/include/DefaultPageLayout/BodyInlineJS.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • emhttp/plugins/dynamix/ArrayOperation.page
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: Squidly271
PR: unraid/webgui#0
File: :0-0
Timestamp: 2025-05-31T05:10:13.120Z
Learning: Squidly271 prefers not to receive CodeRabbit reviews or feedback while PRs are in draft status. Only provide reviews after PRs are moved out of draft.
🔇 Additional comments (4)
emhttp/plugins/dynamix/DashStats.page (1)

2-2: Removing ":stop" on ups_status aligns with exit-on-no-listeners; verify publisher/subscriber naming stays consistent

This matches the new lifecycle where scripts self-terminate without explicit stop hints. Please double-check that the ups_status publisher still emits on the apcups channel (the JS subscribes to /sub/apcups) and that it cleanly exits when no client subscribes. A naming drift between publisher (ups_status) and subscriber (apcups) would lead to either no updates or an idle script.

emhttp/plugins/dynamix.vm.manager/VMUsageStats.page (3)

3-3: LGTM: Channel name simplified correctly.

The channel name change from "vm_usage:stop" to "vm_usage" aligns with the broader refactoring to use the new publish_noDupe mechanism, which handles deduplication internally without requiring channel suffixes.


35-35: LGTM: Client-side initialization simplified.

Removing the .monitor() call is consistent with the PR objective to eliminate monitor/focus-based live-update pause behavior. The simplified vmusage.start() call maintains the subscription functionality while removing the deprecated monitoring feature.


28-32: Ensure there’s a matching publisher for the vm_usage channel

I wasn’t able to find any server-side publish calls for /pub/vm_usage (no publish_noDupe, publish_md5 or direct Nchan API). Before shipping, please confirm that:

  • A backend routine actually invokes something like
    publish_noDupe('/pub/vm_usage', json_encode($htmlSnippet), …);
    at the same cadence as your stats collector (e.g. in a cron or daemon).
  • The payload remains a JSON-encoded HTML string (so JSON.parse(msg) yields a <tr>…</tr> snippet, not an [object Object]).

Locations of interest:

  • emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php → get_vm_usage_stats() builds the raw data
  • (wherever you wire that into an Nchan publish call)

Please verify or add the publish logic so the client’s NchanSubscriber('/sub/vm_usage') actually receives the expected HTML-wrapped JSON.

Comment thread emhttp/plugins/dynamix.docker.manager/DockerContainers.page
Comment thread emhttp/plugins/dynamix.docker.manager/DockerContainers.page

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (1)
emhttp/plugins/dynamix/nchan/wg_poller (1)

18-28: Prevent unit-index overflow and clamp inputs in wg_scale()

Rounding up to the next unit can push $base past the last index (Yi), causing undefined offset. Also clamp/cast $value defensively and fix the boundary check.

Apply this diff:

 function wg_scale($value, &$unit) {
   $units = ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi','Yi'];
   $size = count($units);
-  $base = $value ? floor(log($value, 1024)) : 0;
-  if ($base>$size) $base = $size-1;
-  $value /= pow(1024, $base);
+  $value = max(0, (float)$value);
+  $base  = $value ? (int)floor(log($value, 1024)) : 0;
+  if ($base >= $size) $base = $size - 1;
+  $value /= pow(1024, $base);
   $decimals = $value>=100 ? 0 : ($value>=10 ? 1 : (round($value*100)%100===0 ? 0 : 2));
-  if (round($value,-1)==1000) {$value = 1; $base++;}
+  if (round($value, -1) == 1000 && $base < $size - 1) { $value = 1; $base++; }
   $unit = $units[$base].'B';
   return number_format($value, $decimals, '.', $value>9999 ? ',':'');
 }
🧹 Nitpick comments (1)
emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php (1)

549-556: Avoid potential duplicate reload timers when setTimerReload is called repeatedly.

Clear any existing interval before creating a new one to prevent multiple intervals running concurrently.

Apply this diff:

   function setTimerReload() {
-      timers.reload = setInterval(function(){
+      if (timers.reload) clearInterval(timers.reload);
+      timers.reload = setInterval(function(){
         if (! dialogOpen() ) {
           location.reload();
         }
       },<?=$myPage['Load'] * 60000?>);
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5d984d and 021afaf.

📒 Files selected for processing (2)
  • emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php (2 hunks)
  • emhttp/plugins/dynamix/nchan/wg_poller (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Squidly271
PR: unraid/webgui#0
File: :0-0
Timestamp: 2025-05-31T05:10:13.120Z
Learning: Squidly271 prefers not to receive CodeRabbit reviews or feedback while PRs are in draft status. Only provide reviews after PRs are moved out of draft.
📚 Learning: 2025-05-31T05:10:13.120Z
Learnt from: Squidly271
PR: unraid/webgui#0
File: :0-0
Timestamp: 2025-05-31T05:10:13.120Z
Learning: Squidly271 prefers not to receive CodeRabbit reviews or feedback while PRs are in draft status. Only provide reviews after PRs are moved out of draft.

Applied to files:

  • emhttp/plugins/dynamix/nchan/wg_poller
🔇 Additional comments (2)
emhttp/plugins/dynamix/nchan/wg_poller (2)

3-3: LGTM: Copyright year update

Header year bump looks correct.


14-16: Use long open tags for CLI portability

Short open tags (<?) can be disabled; prefer <?php to avoid environment dependency (especially for CLI).

Apply this diff:

-<?
+<?php

Please confirm short_open_tag is enabled in the target runtime if you prefer to keep <?.

Comment thread emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php
Comment thread emhttp/plugins/dynamix/nchan/wg_poller
Comment thread emhttp/plugins/dynamix/nchan/wg_poller
Comment thread emhttp/plugins/dynamix/nchan/wg_poller Outdated
@Squidly271 Squidly271 marked this pull request as ready for review August 13, 2025 05:12
@ljm42 ljm42 added the 7.2 label Aug 13, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (1)
emhttp/plugins/dynamix/nchan/update_3 (1)

74-85: Fix inter-sample delta ($ts) logic; current code under-reports speeds over time

$ts uses ($time1 - $time0) where $time0 is never updated, so the denominator grows each iteration while the numerator is only the last-sample delta. This progressively understates rx/tx rates.

Suggested refactor:

 while (true) {
-  // check for language changes
+  // roll timestamps for this sample
+  $time0 = $time1;
+  $time1 = microtime(true);
+  // check for language changes
   extract(parse_plugin_cfg('dynamix',true));
   ...
-  sleep(1);
-  $time1 = microtime(true);
+  sleep(1);
 }

Also applies to: 164-166

♻️ Duplicate comments (1)
emhttp/plugins/dynamix/nchan/parity_list (1)

151-151: Double-check frontend handling of the completed case ($echo === "").

When parity completes, $echo is an empty string. If the frontend always JSON.parse’s the message body for the 'parity' topic, JSON.parse('') will throw. Arrays are handled automatically server-side, but empty strings are not auto-encoded. Please verify the subscriber code guards against empty payloads before JSON.parse or expects a JSON string ("").

Run this script to locate the relevant handlers and confirm they gate JSON.parse on non-empty payloads:

#!/bin/bash
set -euo pipefail

# Find parity-topic handlers and nearby JSON.parse calls
rg -n --line-number -A 5 -B 5 '(parity|mainPingListener|JSON\.parse)' \
  emhttp 2>/dev/null || true

# If ArrayOperation.page exists, show focused context
fd -a 'ArrayOperation.page' 2>/dev/null | xargs -r -I{} rg -n -A 5 -B 5 '(parity|JSON\.parse)' {}
🧹 Nitpick comments (9)
emhttp/plugins/dynamix.vm.manager/nchan/vm_usage (3)

68-71: Clean up $echo initialization and assign once after the loop

$echo is initialized twice to an array and then repeatedly reassigned inside the loop. Initialize to a string and assign once after the foreach to improve clarity (and avoid type flip).

Apply:

-  $echo = [];
-  $echo = [];
   $echodata = "";
   $running = 0;
@@
-    $echo = $echodata ;
-  }
+  }
+  $echo = $echodata;
   if ($running < 1) $echo = "<tr><td colspan='7' style='text-align:center;padding-top:12px'>"._('No VMs running')."</td></tr>";

Also applies to: 86-88


17-17: Remove unused variable from legacy md5 flow

$md5_old is no longer used after dropping publish_md5(); remove to avoid confusion.

-$md5_old = -1;

13-15: Avoid closing and reopening PHP in a CLI script

The early closing tag followed by a second open tag is unnecessary and can be dropped to keep a single PHP block.

-?>
-<?
emhttp/plugins/dynamix/nchan/parity_list (1)

150-157: Move the ping publish first to short‑circuit when there are no listeners (and fix comment typo).

Send the dummy ping before the other publishes so the script exits immediately when there are no subscribers, avoiding unnecessary work and publishes. Also fixes the “timeoutto” typo and improves comment clarity.

-  // publish without a timeout for no listeners
-  	publish('parity', $echo,1,false);
-	publish('paritymonitor', $spot > 0 ? 1 : 0,1,false);
-	publish('fsState', $fsState,1,false);
-	publish('mymonitor', $process,1,false);
-
-	//publish to the dummy listener with the timeoutto see if there are any subscribers
-	publish('mainPingListener',"ping");
+  // Ping a dummy listener (with default exit-on-no-listener semantics) to short-circuit this loop if there are no subscribers
+  publish('mainPingListener', "ping");
+  // Publish without a timeout for no listeners
+  publish('parity', $echo, 1, false);
+  publish('paritymonitor', $spot > 0 ? 1 : 0, 1, false);
+  publish('fsState', $fsState, 1, false);
+  publish('mymonitor', $process, 1, false);
emhttp/plugins/dynamix/nchan/update_3 (2)

162-162: Confirm dedupe parity vs prior publish_md5(..., true) usage

The previous call used md5-based dedupe. If dedupe is still desired for this channel, consider publish_noDupe() to keep parity with the old behavior; otherwise, the channel may receive repetitive identical payloads.

Proposed change:

-  publish('update3',$echo);
+  publish_noDupe('update3', $echo);

162-162: Optional: Tune abortTime to reduce idle-exit latency

Default abortTime is 30s. Given this script publishes every 1s, consider a shorter abort time (e.g., 10s) to stop sooner when there are no subscribers.

Example:

-  publish('update3',$echo);
+  publish('update3', $echo, 1, true, 10);
emhttp/plugins/dynamix/nchan/update_1 (2)

126-126: Confirm dedupe parity vs prior publish_md5(..., true) usage

If the intent was to suppress redundant updates like before, switch to publish_noDupe(); otherwise identical payloads will be published each tick.

Proposed change:

-  publish('update1',$echo);
+  publish_noDupe('update1', $echo);

Also consider explicit abortTime if you want faster idle-exit for a 5s cadence, e.g. 15–20s:

-  publish('update1',$echo);
+  publish('update1', $echo, 1, true, 20);

3-5: Verify copyright year consistency

The topline was updated to 2005–2025; if Bergware International contributions continued in 2024–2025, consider aligning the second line as well.

Example:

- * Copyright 2012-2023, Bergware International.
+ * Copyright 2012-2025, Bergware International.
emhttp/plugins/dynamix/nchan/vm_dashusage (1)

24-24: Remove leftover md5-related variable

$md5_old appears to be a vestige from the previous md5-based publish flow and is now unused. Please remove to avoid confusion.

-$md5_old = -1;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac9d97a and 4ed3180.

📒 Files selected for processing (11)
  • emhttp/plugins/dynamix.docker.manager/nchan/docker_load (1 hunks)
  • emhttp/plugins/dynamix.vm.manager/nchan/vm_usage (2 hunks)
  • emhttp/plugins/dynamix/nchan/device_list (1 hunks)
  • emhttp/plugins/dynamix/nchan/parity_list (1 hunks)
  • emhttp/plugins/dynamix/nchan/update_1 (2 hunks)
  • emhttp/plugins/dynamix/nchan/update_2 (1 hunks)
  • emhttp/plugins/dynamix/nchan/update_3 (1 hunks)
  • emhttp/plugins/dynamix/nchan/ups_status (2 hunks)
  • emhttp/plugins/dynamix/nchan/vm_dashusage (2 hunks)
  • emhttp/plugins/dynamix/nchan/wg_poller (3 hunks)
  • emhttp/plugins/dynamix/nchan/wlan0 (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • emhttp/plugins/dynamix.docker.manager/nchan/docker_load
  • emhttp/plugins/dynamix/nchan/ups_status
  • emhttp/plugins/dynamix/nchan/wg_poller
  • emhttp/plugins/dynamix/nchan/device_list
  • emhttp/plugins/dynamix/nchan/wlan0
  • emhttp/plugins/dynamix/nchan/update_2
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: Squidly271
PR: unraid/webgui#2333
File: emhttp/plugins/dynamix/nchan/wg_poller:39-41
Timestamp: 2025-08-13T05:09:31.948Z
Learning: In the Unraid webGUI nchan system, the publish() function will automatically exit the script when there are no listeners, eliminating the need to manually check return values and break out of loops in nchan poller scripts.
Learnt from: Squidly271
PR: unraid/webgui#0
File: :0-0
Timestamp: 2025-05-31T05:10:13.120Z
Learning: Squidly271 prefers not to receive CodeRabbit reviews or feedback while PRs are in draft status. Only provide reviews after PRs are moved out of draft.
📚 Learning: 2025-08-13T02:06:47.712Z
Learnt from: Squidly271
PR: unraid/webgui#2333
File: emhttp/plugins/dynamix/nchan/parity_list:150-158
Timestamp: 2025-08-13T02:06:47.712Z
Learning: In the unraid/webgui codebase, both publish() and publish_noDupe() functions in emhttp/plugins/dynamix/include/publish.php automatically detect arrays passed as the $message parameter and convert them to JSON strings using json_encode() internally. This eliminates the need for manual json_encode() calls at call sites - arrays are automatically converted to JSON while strings are passed through unchanged.

Applied to files:

  • emhttp/plugins/dynamix/nchan/parity_list
📚 Learning: 2025-08-13T02:06:47.712Z
Learnt from: Squidly271
PR: unraid/webgui#2333
File: emhttp/plugins/dynamix/nchan/parity_list:150-158
Timestamp: 2025-08-13T02:06:47.712Z
Learning: In the unraid/webgui codebase, the publish() and publish_noDupe() functions in emhttp/plugins/dynamix/include/publish.php automatically handle JSON encoding when arrays are passed to them, eliminating the need for manual json_encode() calls at the call sites.

Applied to files:

  • emhttp/plugins/dynamix/nchan/parity_list
📚 Learning: 2025-08-10T20:48:52.086Z
Learnt from: Squidly271
PR: unraid/webgui#2326
File: emhttp/plugins/dynamix.vm.manager/nchan/vm_usage:93-93
Timestamp: 2025-08-10T20:48:52.086Z
Learning: In the unraid/webgui codebase, Squidly271 prefers the publish() function to internally handle parameter type overloading (e.g., accepting boolean true in place of buffer length 1) to avoid repetitive parameter specifications and maintain backwards compatibility. The publish() function in emhttp/plugins/dynamix/include/publish.php is designed to sort out these parameters internally rather than requiring explicit values at every call site.

Applied to files:

  • emhttp/plugins/dynamix/nchan/parity_list
📚 Learning: 2025-08-13T03:13:53.283Z
Learnt from: Squidly271
PR: unraid/webgui#2333
File: emhttp/plugins/dynamix/include/publish.php:28-36
Timestamp: 2025-08-13T03:13:53.283Z
Learning: In the unraid/webgui codebase, PR #2333 by Squidly271 supersedes earlier work that already addressed all legacy publish() calls using the old overloaded syntax. There are no remaining legacy calls that need backward compatibility handling in the publish() function.

Applied to files:

  • emhttp/plugins/dynamix/nchan/parity_list
📚 Learning: 2025-05-31T05:10:13.120Z
Learnt from: Squidly271
PR: unraid/webgui#0
File: :0-0
Timestamp: 2025-05-31T05:10:13.120Z
Learning: Squidly271 prefers not to receive CodeRabbit reviews or feedback while PRs are in draft status. Only provide reviews after PRs are moved out of draft.

Applied to files:

  • emhttp/plugins/dynamix/nchan/parity_list
🔇 Additional comments (5)
emhttp/plugins/dynamix.vm.manager/nchan/vm_usage (1)

3-4: LGTM: copyright year updates are correct

Years updated consistently; no issues.

emhttp/plugins/dynamix/nchan/parity_list (1)

151-154: LGTM: publish() usage aligns with the new API and array auto-JSON behavior.

Passing $echo directly (array or string) is correct given publish()’s internal array→JSON handling in publish.php. The signature and per-topic flags look consistent.

emhttp/plugins/dynamix/nchan/update_3 (1)

162-162: Switch to new publish() is correct and aligns with auto-exit semantics

LGTM. This matches the updated publish API and the PR goal of letting scripts exit when there are no listeners. Per our prior learning for this project, publish() will auto-exit when there are no subscribers, so no return checks or loop breaks are needed.

emhttp/plugins/dynamix/nchan/update_1 (1)

126-126: Switch to new publish() is correct and aligns with auto-exit semantics

LGTM. This matches the new API and the PR objective (scripts exiting when no listeners), so no extra loop control is required.

emhttp/plugins/dynamix/nchan/vm_dashusage (1)

3-4: Copyright year updates — LGTM

Header years updated correctly. No further action needed.

Comment thread emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
Comment thread emhttp/plugins/dynamix/nchan/vm_dashusage

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
emhttp/plugins/dynamix/scripts/install_key (1)

17-21: Optional: clarify intent and use boolean over “1” for readability (if supported)

If publish() supports boolean true as an alias for len=1 (as per recent overloading work), this improves readability. A brief comment also makes the no-abort rationale obvious to future readers.

-    publish('plugins', $message,1,false);
+    // Keep running even if there are no listeners (do not abort this CLI-driven flow)
+    publish('plugins', $message, true, false);
emhttp/plugins/dynamix.plugin.manager/scripts/plugin (1)

181-190: Optional: centralize nchan write behavior to avoid duplication

The write(...$messages) + publish('plugins', …, 1, false) pattern is repeated in multiple scripts (plugin, language, multiplugin). Consider factoring this into a small helper (e.g., publish_plugins($message)) in a shared include to keep behavior consistent and simplify future tweaks.

Example of a thin wrapper you could add (in an appropriate shared include):

function publish_plugins($message, $abort=false, $len=true) {
  // boolean $len=true can be treated as 1 by publish()’s internal overloading
  return publish('plugins', $message, $len, $abort);
}

Then here:

-      publish('plugins', $message,1,false);
+      publish_plugins($message);
emhttp/plugins/dynamix.plugin.manager/scripts/language (1)

70-79: Optional: prefer boolean true over magic number and document intent (if overloading is enabled)

For consistency with the publish() overloading work and readability, consider using true in place of 1, and add a short comment explaining abort=false.

-      publish('plugins', $message,1,false);
+      // Do not abort the script if there are no listeners (UI closed)
+      publish('plugins', $message, true, false);
emhttp/plugins/dynamix.plugin.manager/scripts/multiplugin (1)

23-32: Optional: deduplicate write/publish logic across scripts

Same suggestion as in plugin/language: consider a shared helper (e.g., publish_plugins($message)) to reduce duplication and ensure consistent len/abort behavior everywhere.

Within this file:

-      publish('plugins', $message,1,false);
+      publish_plugins($message);

Helper (placed in a common include such as publish.php or Wrappers.php):

function publish_plugins($message, $abort=false, $len=true) {
  return publish('plugins', $message, $len, $abort);
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ed3180 and 173c388.

📒 Files selected for processing (9)
  • emhttp/plugins/dynamix.docker.manager/scripts/container_size (1 hunks)
  • emhttp/plugins/dynamix.docker.manager/scripts/update_container (1 hunks)
  • emhttp/plugins/dynamix.plugin.manager/scripts/language (1 hunks)
  • emhttp/plugins/dynamix.plugin.manager/scripts/multiplugin (1 hunks)
  • emhttp/plugins/dynamix.plugin.manager/scripts/plugin (1 hunks)
  • emhttp/plugins/dynamix/scripts/diagnostics (1 hunks)
  • emhttp/plugins/dynamix/scripts/install_key (1 hunks)
  • emhttp/plugins/dynamix/scripts/newperms (1 hunks)
  • emhttp/plugins/dynamix/scripts/ssd_trim (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: Squidly271
PR: unraid/webgui#2333
File: emhttp/plugins/dynamix/nchan/wg_poller:39-41
Timestamp: 2025-08-13T05:09:31.948Z
Learning: In the Unraid webGUI nchan system, the publish() function will automatically exit the script when there are no listeners, eliminating the need to manually check return values and break out of loops in nchan poller scripts.
Learnt from: Squidly271
PR: unraid/webgui#0
File: :0-0
Timestamp: 2025-05-31T05:10:13.120Z
Learning: Squidly271 prefers not to receive CodeRabbit reviews or feedback while PRs are in draft status. Only provide reviews after PRs are moved out of draft.
📚 Learning: 2025-08-13T05:09:31.948Z
Learnt from: Squidly271
PR: unraid/webgui#2333
File: emhttp/plugins/dynamix/nchan/wg_poller:39-41
Timestamp: 2025-08-13T05:09:31.948Z
Learning: In the Unraid webGUI nchan system, the publish() function will automatically exit the script when there are no listeners, eliminating the need to manually check return values and break out of loops in nchan poller scripts.

Applied to files:

  • emhttp/plugins/dynamix.plugin.manager/scripts/language
  • emhttp/plugins/dynamix.plugin.manager/scripts/plugin
  • emhttp/plugins/dynamix/scripts/newperms
  • emhttp/plugins/dynamix.plugin.manager/scripts/multiplugin
  • emhttp/plugins/dynamix.docker.manager/scripts/update_container
📚 Learning: 2025-08-10T20:48:52.086Z
Learnt from: Squidly271
PR: unraid/webgui#2326
File: emhttp/plugins/dynamix.vm.manager/nchan/vm_usage:93-93
Timestamp: 2025-08-10T20:48:52.086Z
Learning: In the unraid/webgui codebase, Squidly271 prefers the publish() function to internally handle parameter type overloading (e.g., accepting boolean true in place of buffer length 1) to avoid repetitive parameter specifications and maintain backwards compatibility. The publish() function in emhttp/plugins/dynamix/include/publish.php is designed to sort out these parameters internally rather than requiring explicit values at every call site.

Applied to files:

  • emhttp/plugins/dynamix.plugin.manager/scripts/plugin
  • emhttp/plugins/dynamix/scripts/diagnostics
  • emhttp/plugins/dynamix.docker.manager/scripts/container_size
  • emhttp/plugins/dynamix.plugin.manager/scripts/multiplugin
  • emhttp/plugins/dynamix/scripts/ssd_trim
  • emhttp/plugins/dynamix/scripts/install_key
🔇 Additional comments (9)
emhttp/plugins/dynamix.docker.manager/scripts/container_size (1)

30-30: Confirm abort=false is intentional for non-poller script

Based on the new publish() behavior (auto-exit when no listeners), setting abort=false here looks correct so the script completes even if the UI disconnects. Please confirm this endpoint is meant to keep running regardless of listeners.

Note: I leveraged your recent learning that publish() auto-exits when there are no listeners in pollers; this script appears to be a non-poller workflow.

emhttp/plugins/dynamix/scripts/ssd_trim (1)

36-36: LGTM: Keep TRIM running even if no listener

Passing abort=false is appropriate so TRIM operations aren’t killed if the client disconnects. This aligns with the new auto-exit semantics for pollers while ensuring maintenance tasks complete.

emhttp/plugins/dynamix/scripts/newperms (1)

30-30: LGTM: Consistent publish semantics for long-running job

Using abort=false under the nchan path ensures newperms won’t be terminated mid-run if the panel closes, while still streaming logs when listeners exist.

emhttp/plugins/dynamix.docker.manager/scripts/update_container (1)

36-36: LGTM: Don’t abort container updates on disconnect

For image pulls and container updates, abort=false is the safe choice—prevents terminating critical operations if the UI goes away mid-stream, while still publishing logs when available.

emhttp/plugins/dynamix/scripts/diagnostics (1)

50-50: LGTM: Diagnostics should finish even without listeners

abort=false makes sense here so the diagnostics ZIP completes even if the user closes the page; logs are still published when a listener is present.

emhttp/plugins/dynamix/scripts/install_key (1)

19-19: LGTM: publish() now uses explicit len=1 and abort=false appropriately

Using abort=false is correct here so the key install flow isn’t terminated when no UI listener is attached. The explicit len=1 aligns with keeping only the latest message in the channel.

emhttp/plugins/dynamix.plugin.manager/scripts/plugin (1)

185-185: LGTM: explicit publish() parameters fit the plugin manager flow

Passing len=1 and abort=false is appropriate so the install/update operations proceed even if the UI disconnects. This is consistent with the new publish() signature and the PR objective to only auto-exit in poller-type scripts.

emhttp/plugins/dynamix.plugin.manager/scripts/language (1)

74-74: LGTM: publish(..., 1, false) avoids unintended script termination

This ensures language operations continue when no listeners are present, which is the desired behavior for these non-poller scripts.

emhttp/plugins/dynamix.plugin.manager/scripts/multiplugin (1)

27-27: LGTM: parameters match desired semantics (keep last message, don’t abort)

The change aligns with the updated publish() API and the intent for multiplugin operations to continue independent of listener presence.

@limetech limetech merged commit db30f1c into unraid:master Aug 14, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants