adding a supervisor for the supervisor #2689

Merged
mfreeman451 merged 1 commit from refs/pull/2689/head into staging 2026-01-18 07:30:16 +00:00
mfreeman451 commented 2026-01-18 07:26:50 +00:00 (Migrated from github.com)
Owner

Imported from GitHub pull request.

Original GitHub pull request: #2336
Original author: @mfreeman451
Original URL: https://github.com/carverauto/serviceradar/pull/2336
Original created: 2026-01-18T07:26:50Z
Original updated: 2026-01-18T07:30:18Z
Original head: carverauto/serviceradar:fix/nats-supervisor
Original base: staging
Original merged: 2026-01-18T07:30:16Z by @mfreeman451

User description

IMPORTANT: Please sign the Developer Certificate of Origin

Thank you for your contribution to ServiceRadar. Please note, when contributing, the developer must include
a DCO sign-off statement indicating the DCO acceptance in one commit message. Here
is an example DCO Signed-off-by line in a commit message:

Signed-off-by: J. Doe <j.doe@domain.com>

Describe your changes

Code checklist before requesting a review

  • I have signed the DCO?
  • The build completes without errors?
  • All tests are passing when running make test?

PR Type

Enhancement, Bug fix


Description

  • Refactor NATS connection management to use Gnat.ConnectionSupervisor for fault tolerance

  • Create new ServiceRadar.NATS.Supervisor module wrapping connection supervisor

  • Simplify ServiceRadar.NATS.Connection to provide API-only interface

  • Eliminate manual reconnection logic and health checks in favor of supervisor-managed auto-reconnect


Diagram Walkthrough

flowchart LR
  A["Application Supervision Tree"] -->|starts| B["ServiceRadar.NATS.Supervisor"]
  B -->|wraps| C["Gnat.ConnectionSupervisor"]
  C -->|manages| D["NATS Connection"]
  E["ServiceRadar.NATS.Connection"] -->|queries| D
  E -->|publishes via| D

File Walkthrough

Relevant files
Configuration changes
application.ex
Update application supervision tree for NATS supervisor   

elixir/serviceradar_core/lib/serviceradar/application.ex

  • Updated nats_connection_child() to return ServiceRadar.NATS.Supervisor
    instead of ServiceRadar.NATS.Connection
  • Updated comment to clarify NATS connection is now supervisor-managed
    with auto-reconnect capability
+2/-2     
Enhancement
connection.ex
Refactor to stateless API layer for NATS publishing           

elixir/serviceradar_core/lib/serviceradar/nats/connection.ex

  • Converted from GenServer-based connection manager to stateless API
    module
  • Removed all connection state management, reconnection logic, and
    health checks
  • Simplified get() and get!() to query connection PID via
    Process.whereis()
  • Updated publish() to use supervised connection with error handling for
    dead connections
  • Simplified connected?() and status() to query current connection state
  • Kept start_link() and reconnect() as no-ops for backward compatibility
  • Updated module documentation to reflect new role as API layer
+93/-321
supervisor.ex
New supervisor module for fault-tolerant NATS connections

elixir/serviceradar_core/lib/serviceradar/nats/supervisor.ex

  • New module implementing Supervisor behavior wrapping
    Gnat.ConnectionSupervisor
  • Builds connection settings from configuration including host, port,
    TLS, and credentials
  • Handles authentication setup for nkey, JWT, and user/password methods
  • Loads credentials from file if provided via ServiceRadar.NATS.Creds
  • Provides fault-tolerant connection management with automatic
    reconnection on failure
  • Configurable backoff period for reconnection attempts
+184/-0 

Imported from GitHub pull request. Original GitHub pull request: #2336 Original author: @mfreeman451 Original URL: https://github.com/carverauto/serviceradar/pull/2336 Original created: 2026-01-18T07:26:50Z Original updated: 2026-01-18T07:30:18Z Original head: carverauto/serviceradar:fix/nats-supervisor Original base: staging Original merged: 2026-01-18T07:30:16Z by @mfreeman451 --- ### **User description** ## IMPORTANT: Please sign the Developer Certificate of Origin Thank you for your contribution to ServiceRadar. Please note, when contributing, the developer must include a [DCO sign-off statement]( https://developercertificate.org/) indicating the DCO acceptance in one commit message. Here is an example DCO Signed-off-by line in a commit message: ``` Signed-off-by: J. Doe <j.doe@domain.com> ``` ## Describe your changes ## Issue ticket number and link ## Code checklist before requesting a review - [ ] I have signed the DCO? - [ ] The build completes without errors? - [ ] All tests are passing when running make test? ___ ### **PR Type** Enhancement, Bug fix ___ ### **Description** - Refactor NATS connection management to use `Gnat.ConnectionSupervisor` for fault tolerance - Create new `ServiceRadar.NATS.Supervisor` module wrapping connection supervisor - Simplify `ServiceRadar.NATS.Connection` to provide API-only interface - Eliminate manual reconnection logic and health checks in favor of supervisor-managed auto-reconnect ___ ### Diagram Walkthrough ```mermaid flowchart LR A["Application Supervision Tree"] -->|starts| B["ServiceRadar.NATS.Supervisor"] B -->|wraps| C["Gnat.ConnectionSupervisor"] C -->|manages| D["NATS Connection"] E["ServiceRadar.NATS.Connection"] -->|queries| D E -->|publishes via| D ``` <details><summary><h3>File Walkthrough</h3></summary> <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Configuration changes</strong></td><td><table> <tr> <td> <details> <summary><strong>application.ex</strong><dd><code>Update application supervision tree for NATS supervisor</code>&nbsp; &nbsp; </dd></summary> <hr> elixir/serviceradar_core/lib/serviceradar/application.ex <ul><li>Updated <code>nats_connection_child()</code> to return <code>ServiceRadar.NATS.Supervisor</code> <br>instead of <code>ServiceRadar.NATS.Connection</code><br> <li> Updated comment to clarify NATS connection is now supervisor-managed <br>with auto-reconnect capability</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2336/files#diff-a9ffbf400b7f9b22cd8980c41286c54fe373f1f1a8684bb6a344a5fb39b178d0">+2/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></td></tr><tr><td><strong>Enhancement</strong></td><td><table> <tr> <td> <details> <summary><strong>connection.ex</strong><dd><code>Refactor to stateless API layer for NATS publishing</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> elixir/serviceradar_core/lib/serviceradar/nats/connection.ex <ul><li>Converted from GenServer-based connection manager to stateless API <br>module<br> <li> Removed all connection state management, reconnection logic, and <br>health checks<br> <li> Simplified <code>get()</code> and <code>get!()</code> to query connection PID via <br><code>Process.whereis()</code><br> <li> Updated <code>publish()</code> to use supervised connection with error handling for <br>dead connections<br> <li> Simplified <code>connected?()</code> and <code>status()</code> to query current connection state<br> <li> Kept <code>start_link()</code> and <code>reconnect()</code> as no-ops for backward compatibility<br> <li> Updated module documentation to reflect new role as API layer</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2336/files#diff-a48e9add5c28f0e3ba14798d6b23315e0a8e112f3ec922f22b80532dd19695c1">+93/-321</a></td> </tr> <tr> <td> <details> <summary><strong>supervisor.ex</strong><dd><code>New supervisor module for fault-tolerant NATS connections</code></dd></summary> <hr> elixir/serviceradar_core/lib/serviceradar/nats/supervisor.ex <ul><li>New module implementing Supervisor behavior wrapping <br><code>Gnat.ConnectionSupervisor</code><br> <li> Builds connection settings from configuration including host, port, <br>TLS, and credentials<br> <li> Handles authentication setup for nkey, JWT, and user/password methods<br> <li> Loads credentials from file if provided via <code>ServiceRadar.NATS.Creds</code><br> <li> Provides fault-tolerant connection management with automatic <br>reconnection on failure<br> <li> Configurable backoff period for reconnection attempts</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2336/files#diff-da867b13a3a709da96a07177a77ad04afc100bcc0fe2a2e571f6b424b64ac97d">+184/-0</a>&nbsp; </td> </tr> </table></td></tr></tbody></table> </details> ___
qodo-code-review[bot] commented 2026-01-18 07:27:26 +00:00 (Migrated from github.com)
Author
Owner

Imported GitHub PR comment.

Original author: @qodo-code-review[bot]
Original URL: https://github.com/carverauto/serviceradar/pull/2336#issuecomment-3765011492
Original created: 2026-01-18T07:27:26Z

ⓘ Your approaching your monthly quota for Qodo. Upgrade your plan

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Sensitive info exposure

Description: The warning log on credential-read failure includes the raw creds_file path
(Logger.warning("Failed to read NATS creds file #{creds_file}: ...")), which can expose
sensitive filesystem layout and secret file locations to anyone with log access.
supervisor.ex [160-168]

Referred Code
defp load_creds(creds_file, jwt, nkey_seed) do
  case ServiceRadar.NATS.Creds.read(creds_file) do
    {:ok, creds} ->
      {creds.jwt, creds.nkey_seed}

    {:error, reason} ->
      Logger.warning("Failed to read NATS creds file #{creds_file}: #{inspect(reason)}")
      {jwt, nkey_seed}
  end
Insecure TLS options

Description: TLS configuration accepts arbitrary ssl_opts from config (tls_opts when
is_list(tls_opts)), which can enable insecure settings (e.g., verify: :verify_none) and
silently weaken transport security if misconfigured.
supervisor.ex [142-155]

Referred Code
defp add_tls_settings(settings, tls) do
  case tls do
    true ->
      Map.put(settings, :tls, true)

    tls_opts when is_list(tls_opts) ->
      settings
      |> Map.put(:tls, true)
      |> Map.put(:ssl_opts, tls_opts)

    _ ->
      settings
  end
end
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Error details exposed: get!/0 raises an exception string containing inspect(reason), which could leak internal
details if this propagates to any user-facing boundary.

Referred Code
Gets the NATS connection PID, raising on error.
"""
@spec get!() :: pid()
def get! do
  case get() do
    {:ok, conn} -> conn
    {:error, reason} -> raise "NATS connection error: #{inspect(reason)}"
  end

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Sensitive data in logs: Logging inspect(reason) for NATS credential file read failures may inadvertently log
sensitive or overly-informative details depending on the underlying error structure.

Referred Code
defp load_creds(creds_file, jwt, nkey_seed) do
  case ServiceRadar.NATS.Creds.read(creds_file) do
    {:ok, creds} ->
      {creds.jwt, creds.nkey_seed}

    {:error, reason} ->
      Logger.warning("Failed to read NATS creds file #{creds_file}: #{inspect(reason)}")
      {jwt, nkey_seed}
  end

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
- Requires Further Human Verification
🏷️ - Compliance label
Imported GitHub PR comment. Original author: @qodo-code-review[bot] Original URL: https://github.com/carverauto/serviceradar/pull/2336#issuecomment-3765011492 Original created: 2026-01-18T07:27:26Z --- <pre>ⓘ Your approaching your monthly quota for Qodo. <a href="https://www.qodo.ai/pricing">Upgrade your plan</a></pre> ## PR Compliance Guide 🔍 <!-- https://github.com/carverauto/serviceradar/commit/8f94037a9969ffa5ac920983aaf7b71995a4e735 --> Below is a summary of compliance checks for this PR:<br> <table><tbody><tr><td colspan='2'><strong>Security Compliance</strong></td></tr> <tr><td rowspan=2>⚪</td> <td><details><summary><strong>Sensitive info exposure </strong></summary><br> <b>Description:</b> The warning log on credential-read failure includes the raw <code>creds_file</code> path <br>(<code>Logger.warning("Failed to read NATS creds file #{creds_file}: ...")</code>), which can expose <br>sensitive filesystem layout and secret file locations to anyone with log access.<br> <strong><a href='https://github.com/carverauto/serviceradar/pull/2336/files#diff-da867b13a3a709da96a07177a77ad04afc100bcc0fe2a2e571f6b424b64ac97dR160-R168'>supervisor.ex [160-168]</a></strong><br> <details open><summary>Referred Code</summary> ```elixir defp load_creds(creds_file, jwt, nkey_seed) do case ServiceRadar.NATS.Creds.read(creds_file) do {:ok, creds} -> {creds.jwt, creds.nkey_seed} {:error, reason} -> Logger.warning("Failed to read NATS creds file #{creds_file}: #{inspect(reason)}") {jwt, nkey_seed} end ``` </details></details></td></tr> <tr><td><details><summary><strong>Insecure TLS options </strong></summary><br> <b>Description:</b> TLS configuration accepts arbitrary <code>ssl_opts</code> from config (<code>tls_opts when </code><br><code>is_list(tls_opts)</code>), which can enable insecure settings (e.g., <code>verify: :verify_none</code>) and <br>silently weaken transport security if misconfigured.<br> <strong><a href='https://github.com/carverauto/serviceradar/pull/2336/files#diff-da867b13a3a709da96a07177a77ad04afc100bcc0fe2a2e571f6b424b64ac97dR142-R155'>supervisor.ex [142-155]</a></strong><br> <details open><summary>Referred Code</summary> ```elixir defp add_tls_settings(settings, tls) do case tls do true -> Map.put(settings, :tls, true) tls_opts when is_list(tls_opts) -> settings |> Map.put(:tls, true) |> Map.put(:ssl_opts, tls_opts) _ -> settings end end ``` </details></details></td></tr> <tr><td colspan='2'><strong>Ticket Compliance</strong></td></tr> <tr><td>⚪</td><td><details><summary>🎫 <strong>No ticket provided </strong></summary> - [ ] Create ticket/issue <!-- /create_ticket --create_ticket=true --> </details></td></tr> <tr><td colspan='2'><strong>Codebase Duplication Compliance</strong></td></tr> <tr><td>⚪</td><td><details><summary><strong>Codebase context is not defined </strong></summary> Follow the <a href='https://qodo-merge-docs.qodo.ai/core-abilities/rag_context_enrichment/'>guide</a> to enable codebase context checks. </details></td></tr> <tr><td colspan='2'><strong>Custom Compliance</strong></td></tr> <tr><td rowspan=4>🟢</td><td> <details><summary><strong>Generic: Comprehensive Audit Trails</strong></summary><br> **Objective:** To create a detailed and reliable record of critical system actions for security analysis <br>and compliance.<br> **Status:** Passed<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td> <details><summary><strong>Generic: Meaningful Naming and Self-Documenting Code</strong></summary><br> **Objective:** Ensure all identifiers clearly express their purpose and intent, making code <br>self-documenting<br> **Status:** Passed<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td> <details><summary><strong>Generic: Robust Error Handling and Edge Case Management</strong></summary><br> **Objective:** Ensure comprehensive error handling that provides meaningful context and graceful <br>degradation<br> **Status:** Passed<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td> <details><summary><strong>Generic: Security-First Input Validation and Data Handling</strong></summary><br> **Objective:** Ensure all data inputs are validated, sanitized, and handled securely to prevent <br>vulnerabilities<br> **Status:** Passed<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td rowspan=2>⚪</td> <td><details> <summary><strong>Generic: Secure Error Handling</strong></summary><br> **Objective:** To prevent the leakage of sensitive system information through error messages while <br>providing sufficient detail for internal debugging.<br> **Status:** <br><a href='https://github.com/carverauto/serviceradar/pull/2336/files#diff-a48e9add5c28f0e3ba14798d6b23315e0a8e112f3ec922f22b80532dd19695c1R56-R63'><strong>Error details exposed</strong></a>: <code>get!/0</code> raises an exception string containing <code>inspect(reason)</code>, which could leak internal <br>details if this propagates to any user-facing boundary.<br> <details open><summary>Referred Code</summary> ```elixir Gets the NATS connection PID, raising on error. """ @spec get!() :: pid() def get! do case get() do {:ok, conn} -> conn {:error, reason} -> raise "NATS connection error: #{inspect(reason)}" end ``` </details> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td><details> <summary><strong>Generic: Secure Logging Practices</strong></summary><br> **Objective:** To ensure logs are useful for debugging and auditing without exposing sensitive <br>information like PII, PHI, or cardholder data.<br> **Status:** <br><a href='https://github.com/carverauto/serviceradar/pull/2336/files#diff-da867b13a3a709da96a07177a77ad04afc100bcc0fe2a2e571f6b424b64ac97dR160-R168'><strong>Sensitive data in logs</strong></a>: Logging <code>inspect(reason)</code> for NATS credential file read failures may inadvertently log <br>sensitive or overly-informative details depending on the underlying error structure.<br> <details open><summary>Referred Code</summary> ```elixir defp load_creds(creds_file, jwt, nkey_seed) do case ServiceRadar.NATS.Creds.read(creds_file) do {:ok, creds} -> {creds.jwt, creds.nkey_seed} {:error, reason} -> Logger.warning("Failed to read NATS creds file #{creds_file}: #{inspect(reason)}") {jwt, nkey_seed} end ``` </details> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td align="center" colspan="2"> <!-- placeholder --> <!-- /compliance --update_compliance=true --> </td></tr></tbody></table> <details><summary>Compliance status legend</summary> 🟢 - Fully Compliant<br> 🟡 - Partial Compliant<br> 🔴 - Not Compliant<br> ⚪ - Requires Further Human Verification<br> 🏷️ - Compliance label<br> </details>
qodo-code-review[bot] commented 2026-01-18 07:28:24 +00:00 (Migrated from github.com)
Author
Owner

Imported GitHub PR comment.

Original author: @qodo-code-review[bot]
Original URL: https://github.com/carverauto/serviceradar/pull/2336#issuecomment-3765012082
Original created: 2026-01-18T07:28:24Z

ⓘ Your approaching your monthly quota for Qodo. Upgrade your plan

PR Code Suggestions

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Catch exceptions in publish

Add a rescue clause to the try block in the publish/3 function to catch and
handle exceptions from Gnat.pub/4, returning an error tuple instead of crashing.

elixir/serviceradar_core/lib/serviceradar/nats/connection.ex [77-91]

 def publish(subject, payload, opts \\ []) do
   case get() do
     {:ok, conn} ->
       try do
         Gnat.pub(conn, subject, payload, opts)
+      rescue
+        exception ->
+          Logger.error("NATS publish exception: #{inspect(exception)}")
+          {:error, {:nats_publish_error, exception}}
       catch
         :exit, reason ->
           Logger.warning("NATS publish failed (connection died): #{inspect(reason)}")
           {:error, {:nats_connection_died, reason}}
       end
 
     {:error, reason} ->
       {:error, {:nats_not_connected, reason}}
   end
 end
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: This is a valuable suggestion for improving robustness by adding a rescue clause to handle potential exceptions from Gnat.pub/4, preventing the calling process from crashing.

Medium
Fail supervisor on bad config

Change the init/1 function to raise an exception on invalid NATS configuration
instead of silently starting without the NATS supervisor.

elixir/serviceradar_core/lib/serviceradar/nats/supervisor.ex [56-75]

 case build_connection_settings(config) do
   {:ok, connection_settings} ->
-    ... 
+    ...
     Supervisor.init(children, strategy: :one_for_one)
 
   {:error, reason} ->
-    Logger.error("Failed to build NATS connection settings: #{inspect(reason)}")
-    # Start with empty children - will not have NATS
-    Supervisor.init([], strategy: :one_for_one)
+    raise "Invalid NATS configuration: #{inspect(reason)}"
 end

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 6

__

Why: The suggestion proposes a "fail-fast" approach, which is a valid strategy. However, the current implementation of silently disabling NATS on configuration error is also a reasonable design choice to prevent the entire application from crashing.

Low
Refactor logic using a with statement

Refactor the build_connection_settings/1 function to use a with statement for
more idiomatic and readable error handling.

elixir/serviceradar_core/lib/serviceradar/nats/supervisor.ex [78-112]

 defp build_connection_settings(config) do
   host = Keyword.get(config, :host, "localhost")
   port = Keyword.get(config, :port, 4222)
   tls = Keyword.get(config, :tls, false)
   creds_file = resolve_value(Keyword.get(config, :creds_file)) |> normalize()
   jwt = resolve_value(Keyword.get(config, :jwt)) |> normalize()
   nkey_seed = resolve_value(Keyword.get(config, :nkey_seed)) |> normalize()
   user = resolve_value(Keyword.get(config, :user))
   password = resolve_value(Keyword.get(config, :password))
 
   # Load credentials from file if provided
   {jwt, nkey_seed} = load_creds(creds_file, jwt, nkey_seed)
 
-  settings = %{
+  base_settings = %{
     host: host,
     port: port
   }
 
-  # Apply authentication
-  settings =
-    case apply_auth_settings(settings, jwt, nkey_seed, user, password) do
-      {:ok, updated} -> updated
-      {:error, _reason} = error -> error
-    end
-
-  case settings do
-    {:error, _} = error ->
-      error
-
-    settings ->
-      # Apply TLS settings
-      settings = add_tls_settings(settings, tls)
-      {:ok, settings}
+  with {:ok, auth_settings} <- apply_auth_settings(base_settings, jwt, nkey_seed, user, password) do
+    # Apply TLS settings
+    settings = add_tls_settings(auth_settings, tls)
+    {:ok, settings}
   end
 end
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly identifies an opportunity to refactor the code using a with statement, which is more idiomatic in Elixir and improves readability by flattening the control flow.

Low
Possible issue
Return a valid child spec or empty list

Modify nats_connection_child/0 to return an empty list [] instead of nil when
NATS is disabled to avoid injecting nil into the supervision tree.

elixir/serviceradar_core/lib/serviceradar/application.ex [325-331]

 defp nats_connection_child do
   if nats_enabled?() do
-    ServiceRadar.NATS.Supervisor
+    {ServiceRadar.NATS.Supervisor, []}
   else
-    nil
+    []
   end
 end
  • Apply / Chat
Suggestion importance[1-10]: 4

__

Why: While returning nil is handled by OTP supervisors, the suggestion to return an empty list [] instead is a good practice for consistency, though it may require flattening the children list.

Low
  • More
Imported GitHub PR comment. Original author: @qodo-code-review[bot] Original URL: https://github.com/carverauto/serviceradar/pull/2336#issuecomment-3765012082 Original created: 2026-01-18T07:28:24Z --- <pre>ⓘ Your approaching your monthly quota for Qodo. <a href="https://www.qodo.ai/pricing">Upgrade your plan</a></pre> ## PR Code Suggestions ✨ <!-- 8f94037 --> Explore these optional code suggestions: <table><thead><tr><td><strong>Category</strong></td><td align=left><strong>Suggestion&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </strong></td><td align=center><strong>Impact</strong></td></tr><tbody><tr><td rowspan=3>General</td> <td> <details><summary>Catch exceptions in publish</summary> ___ **Add a <code>rescue</code> clause to the <code>try</code> block in the <code>publish/3</code> function to catch and <br>handle exceptions from <code>Gnat.pub/4</code>, returning an error tuple instead of crashing.** [elixir/serviceradar_core/lib/serviceradar/nats/connection.ex [77-91]](https://github.com/carverauto/serviceradar/pull/2336/files#diff-a48e9add5c28f0e3ba14798d6b23315e0a8e112f3ec922f22b80532dd19695c1R77-R91) ```diff def publish(subject, payload, opts \\ []) do case get() do {:ok, conn} -> try do Gnat.pub(conn, subject, payload, opts) + rescue + exception -> + Logger.error("NATS publish exception: #{inspect(exception)}") + {:error, {:nats_publish_error, exception}} catch :exit, reason -> Logger.warning("NATS publish failed (connection died): #{inspect(reason)}") {:error, {:nats_connection_died, reason}} end {:error, reason} -> {:error, {:nats_not_connected, reason}} end end ``` - [ ] **Apply / Chat** <!-- /improve --apply_suggestion=0 --> <details><summary>Suggestion importance[1-10]: 7</summary> __ Why: This is a valuable suggestion for improving robustness by adding a `rescue` clause to handle potential exceptions from `Gnat.pub/4`, preventing the calling process from crashing. </details></details></td><td align=center>Medium </td></tr><tr><td> <details><summary>Fail supervisor on bad config</summary> ___ **Change the <code>init/1</code> function to raise an exception on invalid NATS configuration <br>instead of silently starting without the NATS supervisor.** [elixir/serviceradar_core/lib/serviceradar/nats/supervisor.ex [56-75]](https://github.com/carverauto/serviceradar/pull/2336/files#diff-da867b13a3a709da96a07177a77ad04afc100bcc0fe2a2e571f6b424b64ac97dR56-R75) ```diff case build_connection_settings(config) do {:ok, connection_settings} -> - ... + ... Supervisor.init(children, strategy: :one_for_one) {:error, reason} -> - Logger.error("Failed to build NATS connection settings: #{inspect(reason)}") - # Start with empty children - will not have NATS - Supervisor.init([], strategy: :one_for_one) + raise "Invalid NATS configuration: #{inspect(reason)}" end ``` `[To ensure code accuracy, apply this suggestion manually]` <details><summary>Suggestion importance[1-10]: 6</summary> __ Why: The suggestion proposes a "fail-fast" approach, which is a valid strategy. However, the current implementation of silently disabling NATS on configuration error is also a reasonable design choice to prevent the entire application from crashing. </details></details></td><td align=center>Low </td></tr><tr><td> <details><summary>Refactor logic using a <code>with</code> statement</summary> ___ **Refactor the <code>build_connection_settings/1</code> function to use a <code>with</code> statement for <br>more idiomatic and readable error handling.** [elixir/serviceradar_core/lib/serviceradar/nats/supervisor.ex [78-112]](https://github.com/carverauto/serviceradar/pull/2336/files#diff-da867b13a3a709da96a07177a77ad04afc100bcc0fe2a2e571f6b424b64ac97dR78-R112) ```diff defp build_connection_settings(config) do host = Keyword.get(config, :host, "localhost") port = Keyword.get(config, :port, 4222) tls = Keyword.get(config, :tls, false) creds_file = resolve_value(Keyword.get(config, :creds_file)) |> normalize() jwt = resolve_value(Keyword.get(config, :jwt)) |> normalize() nkey_seed = resolve_value(Keyword.get(config, :nkey_seed)) |> normalize() user = resolve_value(Keyword.get(config, :user)) password = resolve_value(Keyword.get(config, :password)) # Load credentials from file if provided {jwt, nkey_seed} = load_creds(creds_file, jwt, nkey_seed) - settings = %{ + base_settings = %{ host: host, port: port } - # Apply authentication - settings = - case apply_auth_settings(settings, jwt, nkey_seed, user, password) do - {:ok, updated} -> updated - {:error, _reason} = error -> error - end - - case settings do - {:error, _} = error -> - error - - settings -> - # Apply TLS settings - settings = add_tls_settings(settings, tls) - {:ok, settings} + with {:ok, auth_settings} <- apply_auth_settings(base_settings, jwt, nkey_seed, user, password) do + # Apply TLS settings + settings = add_tls_settings(auth_settings, tls) + {:ok, settings} end end ``` - [ ] **Apply / Chat** <!-- /improve --apply_suggestion=2 --> <details><summary>Suggestion importance[1-10]: 5</summary> __ Why: The suggestion correctly identifies an opportunity to refactor the code using a `with` statement, which is more idiomatic in Elixir and improves readability by flattening the control flow. </details></details></td><td align=center>Low </td></tr><tr><td rowspan=1>Possible issue</td> <td> <details><summary>Return a valid child spec or empty list</summary> ___ **Modify <code>nats_connection_child/0</code> to return an empty list <code>[]</code> instead of <code>nil</code> when <br>NATS is disabled to avoid injecting <code>nil</code> into the supervision tree.** [elixir/serviceradar_core/lib/serviceradar/application.ex [325-331]](https://github.com/carverauto/serviceradar/pull/2336/files#diff-a9ffbf400b7f9b22cd8980c41286c54fe373f1f1a8684bb6a344a5fb39b178d0R325-R331) ```diff defp nats_connection_child do if nats_enabled?() do - ServiceRadar.NATS.Supervisor + {ServiceRadar.NATS.Supervisor, []} else - nil + [] end end ``` - [ ] **Apply / Chat** <!-- /improve --apply_suggestion=3 --> <details><summary>Suggestion importance[1-10]: 4</summary> __ Why: While returning `nil` is handled by OTP supervisors, the suggestion to return an empty list `[]` instead is a good practice for consistency, though it may require flattening the children list. </details></details></td><td align=center>Low </td></tr> <tr><td align="center" colspan="2"> - [ ] More <!-- /improve --more_suggestions=true --> </td><td></td></tr></tbody></table>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
carverauto/serviceradar!2689
No description provided.