Skip to content

fix: call list endpoint on every poll cycle to advance pre-change job state - #11

Open
noppanut15 wants to merge 2 commits into
netascode:mainfrom
noppanut15:fix/prechange-polling-list-endpoint
Open

fix: call list endpoint on every poll cycle to advance pre-change job state#11
noppanut15 wants to merge 2 commits into
netascode:mainfrom
noppanut15:fix/prechange-polling-list-endpoint

Conversation

@noppanut15

@noppanut15 noppanut15 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Problem

nac-analytics nd prechange would hang indefinitely at:

Waiting for pre-change analysis <job_id>...

The job would never complete unless the user manually opened the pre-change analysis page in the Nexus Dashboard GUI. For example, even after waiting for more than 25 mins, the tool was still stuck at Waiting for pre-change analysis..., but once the GUI page was opened, the tool would resume and finish within ~15 seconds. (the next the poll interval)

Affected ND Version

  • 4.2(1)
  • 4.3(1)

Root Cause

The polling loop in wait_prechange_analysis() was exclusively calling the single-job GET endpoint:

GET /api/v1/analyze/jobs/prechangeAnalysis/{job_id}

The Nexus Dashboard backend does not advance a job's state in response to this endpoint alone. Advancing job state requires the list endpoint to be called (mimics what GUI does):

GET /api/v1/analyze/jobs/prechangeAnalysis?sort=-analysisSubmissionTime&offset=0&max=10

This was confirmed manually via Postman. The list endpoint is required for both transitions:

Transition of analysisStatus Requires list endpoint
submittedrunning
runningcompleted

Opening the GUI's pre-change list page fires this exact request on every page load, which is why the CLI would unblock whenever the user navigated to the GUI.

Fix

Added list_prechange_analyses() which calls the list endpoint with the same query parameters the GUI uses. It is called on every poll iteration in wait_prechange_analysis() before the single-job GET. The list response is discarded — the single-job GET is still used for the actual status check, so we avoid iterating potentially many jobs on every cycle.

poll cycle:
  1. GET /api/v1/analyze/jobs/prechangeAnalysis?sort=-analysisSubmissionTime&offset=0&max=10  ← trigger the job status refresh
  2. GET /api/v1/analyze/jobs/prechangeAnalysis/{job_id}  ← read status

Testing

Verified end-to-end against a real Nexus Dashboard instance, both version 4.2(1) and 4.3(1), with plan.json — the job progressed through both transitions and completed successfully without any GUI interaction:

Connecting to <ndi-host> as <user>...
Submitting pre-change analysis...
Waiting for pre-change analysis 6a8f684db88af8fdb902f04c...
Collecting change approval detail...
DECISION: PASS — No new critical/major anomalies (1 new overall).

All 218 unit tests pass. Ruff clean.

Changes

  • nac_analytics/products/nexus_dashboard/client.py — added list_prechange_analyses() and called it on every poll cycle in wait_prechange_analysis()
  • tests/unit/test_prechange.py — added LIST_PATH / LIST_RESPONSE constants and registered the list route in all polling test labs
  • tests/unit/test_cli_commands.py — added PRECHANGE_LIST_PATH and registered the list route in build_lab()

… state

The single-job GET (/api/v1/analyze/jobs/prechangeAnalysis/{job_id})
does not reflect live state — the backend only advances a job when the
list endpoint (GET /api/v1/analyze/jobs/prechangeAnalysis) is called.
This is required for both transitions:

  submitted → running:   without the list call, the job never starts
  running   → completed: without the list call, the job never finishes

This matches the behaviour observed in Postman: calling the list
endpoint immediately causes the single-job GET to return the updated
status on the next request.

The list endpoint is called on every poll iteration to mimic what the
GUI's pre-change list page does on each load. Its result is discarded;
the single-job GET is still used for the actual status check so we
avoid iterating potentially many jobs on every cycle.
The wait_prechange_analysis() polling loop now calls the list endpoint
on every iteration. Add LIST_PATH / PRECHANGE_LIST_PATH routes (returning
an empty entries list) to all affected test labs so they don't 404.
@noppanut15

Copy link
Copy Markdown
Contributor Author

FYI: The PR description has been updated with ND 4.3 testing.

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