Skip to content

fix(connect): serialize nginx reload requests - #2066

Merged
Eli Bosley (elibosley) merged 1 commit into
mainfrom
fix/connect-nginx-reload-race
Aug 25, 2026
Merged

fix(connect): serialize nginx reload requests#2066
Eli Bosley (elibosley) merged 1 commit into
mainfrom
fix/connect-nginx-reload-race

Conversation

@elibosley

@elibosley Eli Bosley (elibosley) commented Aug 25, 2026

Copy link
Copy Markdown
Member

Summary

Concurrent Connect WAN-access transitions could start overlapping rc.nginx rebuilds. This change coalesces in-process reload requests so only one rebuild runs at a time.

Why This Exists

The Unraid 7.3.2 rc.nginx script rebuilds the shared servers.conf file with truncating and append writes. Connect WAN-access event handlers run asynchronously, so overlapping reloads can write duplicate server blocks, make nginx -t fail, and make the local WebGUI unreachable.

Resolution

NginxService now stores the active reload promise at module scope. Concurrent callers wait for that promise and receive the same result. A later caller starts a new reload after the active command completes.

This shape protects all NginxService instances in the API process and does not change the existing success or failure result.

Reviewer Considerations

  • Review the shared promise lifecycle and cleanup in finally.
  • The gate prevents overlap inside one API process. It does not serialize an independently launched rc.nginx process from another OS process.
  • This PR does not change the underlying Unraid rc.nginx script or the event sources.
  • Bare-metal validation on Unraid 7.3.2 remains recommended.

Behavior Changes

Concurrent API-triggered nginx reload requests now run one rc.nginx reload command. Sequential requests after completion still run normally.

Implementation Summary

  • Added an in-process reload gate to api/src/unraid-api/nginx/nginx.service.ts.
  • Added regression tests for concurrent service instances and later reloads.

Verification

  • pnpm --filter ./api exec vitest run src/unraid-api/nginx/nginx.service.spec.ts — 2 passed.
  • pnpm --filter ./api exec vitest run src/unraid-api/nginx src/unraid-api/unraid-file-modifier — 44 passed.
  • pnpm --filter ./api type-check — passed.
  • ESLint on the changed files — passed.
  • GitHub API tests, builds, CodeQL, coverage, and CodeRabbit review — passed.
  • Full local API Vitest run — 2,007 passed; 1 unrelated VMS suite failed because the native @unraid/libvirt module is unavailable in this environment.
  • GitHub Audit Dependencies failed on existing transitive dependency advisories, including postcss and tar. This PR changes no dependency files.

Risk

Low for API-triggered reloads. The remaining risk is limited to reloads started outside this API process.

@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f0bf8a54-c111-4618-bd10-ecf2e7afe429

📥 Commits

Reviewing files that changed from the base of the PR and between a00c99a and 9c42e51.

📒 Files selected for processing (2)
  • api/src/unraid-api/nginx/nginx.service.spec.ts
  • api/src/unraid-api/nginx/nginx.service.ts

Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review.


Walkthrough

NginxService.reload() now returns a shared promise for concurrent requests. The service clears that promise after completion so later requests start a new reload. Vitest coverage validates command execution, successful results, coalescing, and subsequent reloads.

Changes

Nginx reload coordination

Layer / File(s) Summary
Reload coordination and validation
api/src/unraid-api/nginx/nginx.service.ts, api/src/unraid-api/nginx/nginx.service.spec.ts
reload() now returns Promise<boolean>, shares an active reload promise, and clears the tracking state after completion. Tests verify one command for concurrent requests and a new command after completion.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 9c42e

This change serializes concurrent API-triggered nginx reloads while preserving sequential behavior and existing results; no actionable merge-blocking risk remains beyond normal checks and review.

Poem

The rabbit taps reload with care
One command runs through shared fresh air
Waiting calls receive one sign
Then later calls proceed in line
Tests guard the nginx vine

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: serializing concurrent nginx reload requests for Connect.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files.

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/connect-nginx-reload-race

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

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

@linear-code
linear-code Bot marked this pull request as ready for review August 25, 2026 14:53

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c42e51082

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "Codex (@codex) review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "Codex (@codex) address that feedback".

Comment on lines +13 to +15
if (activeReload) {
this.logger.debug('Nginx reload already in progress; waiting for it to complete');
return activeReload;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Queue a reload instead of dropping concurrent requests

When an enable and disable transition overlap, the second handler updates connect.config.wanaccess (wan-access.events.ts:18-29) but this branch merely joins the reload already in progress. Because rc.nginx reads that setting during execution (rc-nginx.modification.ts:51-54), a reload that already consumed the earlier value can finish successfully while the later value is never applied—for example, leaving WAN access enabled after a disable request. Preserve serialization by scheduling a trailing reload after the active command rather than coalescing the request into it.

Useful? React with 👍 / 👎.

@codecov

codecov Bot commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 53.17%. Comparing base (8f6134e) to head (9c42e51).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2066      +/-   ##
==========================================
+ Coverage   53.13%   53.17%   +0.03%     
==========================================
  Files        1041     1041              
  Lines       72425    72476      +51     
  Branches     8354     8363       +9     
==========================================
+ Hits        38482    38537      +55     
+ Misses      33816    33812       -4     
  Partials      127      127              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown
Contributor

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR2066/dynamix.unraid.net.plg

@elibosley
Eli Bosley (elibosley) marked this pull request as draft August 25, 2026 15:01
@elibosley
Eli Bosley (elibosley) marked this pull request as ready for review August 25, 2026 17:02
@elibosley
Eli Bosley (elibosley) merged commit d65341d into main Aug 25, 2026
13 of 14 checks passed
@elibosley
Eli Bosley (elibosley) deleted the fix/connect-nginx-reload-race branch August 25, 2026 17:02
@github-actions

Copy link
Copy Markdown
Contributor

🔄 PR Merged - Plugin Redirected to Staging

This PR has been merged and the preview plugin has been updated to redirect to the staging version.

For users testing this PR:

  • Your plugin will automatically update to the staging version on the next update check
  • The staging version includes all merged changes from this PR
  • No manual intervention required

Staging URL:

https://preview.dl.unraid.net/unraid-api/dynamix.unraid.net.plg

Thank you for testing! 🚀

Eli Bosley (elibosley) pushed a commit that referenced this pull request Aug 25, 2026
🤖 I have created a release *beep* *boop*
---


## [4.37.3](v4.37.2...v4.37.3)
(2026-08-25)


### Bug Fixes

* **connect:** serialize nginx reload requests
([#2066](#2066))
([d65341d](d65341d))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant