Skip to content

Implement service bus monitoring with heartbeat detection and automatic recovery - #4601

Draft
Marcus Robinson (marrobi) with Copilot wants to merge 60 commits into
mainfrom
copilot/fix-4464
Draft

Implement service bus monitoring with heartbeat detection and automatic recovery#4601
Marcus Robinson (marrobi) with Copilot wants to merge 60 commits into
mainfrom
copilot/fix-4464

Conversation

Copilot AI commented Jun 25, 2025

Copy link
Copy Markdown
Contributor

Resolves #4464

What is being addressed

VM operations in the TRE UI were getting stuck in "awaiting_action" status indefinitely. The resource processor completed operations successfully (VMs started/stopped in Azure), but the API never received status updates, leaving operations stuck in the UI.

Root cause: Service bus consumers (DeploymentStatusUpdater and AirlockStatusUpdater) could fail silently or hang without detection or recovery mechanisms.

How is this addressed

Implemented a comprehensive monitoring and auto-recovery system with dual detection:

Key Features

ServiceBusConsumer Base Class: Provides heartbeat monitoring and supervisor functionality for all service bus consumers.

Dual Monitoring:

  • Task monitoring: Detects when receive_messages() tasks fail or complete
  • Heartbeat monitoring: Detects silent hangs via in-memory heartbeat timestamps (5-minute staleness threshold)

Automatic Recovery:

  • Failed tasks restart with exponential backoff (5 seconds to 300 seconds maximum)
  • Silent hangs detected and restarted within 5 minutes
  • Health endpoint integration for monitoring consumer status

Implementation Details

  • Enhanced error handling: Improved exception handling with explanatory comments
  • Configuration: Extracted magic numbers to named constants for maintainability
  • Code quality: Follows Python best practices and PEP 8 guidelines
  • Logging: Enhanced logging for better observability
  • Testing: Comprehensive unit and edge case test coverage
  • Health endpoint integration: Consumer status exposed via /health endpoint

Files Changed

  • CHANGELOG.md - Added entry in BUG FIXES section
  • api_app/_version.py - Incremented to 0.26.1
  • service_bus/service_bus_consumer.py - New base class with monitoring (follows PEP 8 import conventions)
  • service_bus/deployment_status_updater.py - Inherits from base class
  • service_bus/airlock_request_status_update.py - Same integration
  • main.py - Uses supervisor functions
  • services/logging.py - Enhanced logging
  • api/routes/health.py - Consumer status integration
  • services/health_checker.py - Health check support
  • Complete test suite for all functionality

Result

Before: Manual API restart required when consumers failed
After: Self-healing system with zero manual intervention needed and health endpoint monitoring

This eliminates indefinitely stuck operations and makes the TRE service bus system resilient to both transient failures and silent hangs.

Documentation and versioning

  • Updated CHANGELOG.md with entry in BUG FIXES section
  • Incremented API version from 0.26.0 to 0.26.1

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…tions

Co-authored-by: marrobi <17089773+marrobi@users.noreply.github.com>
Copilot AI changed the title [WIP] TRE processor/UI does not seem to be picking up VM resource status changes/operations Add restart mechanism to deployment status updater to fix stuck VM operations Jun 25, 2025
@marrobi

Copy link
Copy Markdown
Member

Copilot can the supervisor be moved into async def runner(process_number: int, config: dict):.

@github-actions

github-actions Bot commented Jun 25, 2025

Copy link
Copy Markdown

Unit Test Results

780 tests   780 ✅  10s ⏱️
  1 suites    0 💤
  1 files      0 ❌

Results for commit bf633fd.

♻️ This comment has been updated with latest results.

@marrobi

Copy link
Copy Markdown
Member

Copilot can you add something in the supervisor function to check that there is still a heartbeat.

…ection

Co-authored-by: marrobi <17089773+marrobi@users.noreply.github.com>

Copilot AI commented Jun 25, 2025

Copy link
Copy Markdown
Contributor Author

Copilot can you add something in the supervisor function to check that there is still a heartbeat.

Added heartbeat monitoring to the supervisor function. Each worker process now updates a heartbeat file every iteration, and the supervisor checks these timestamps to detect stuck processes. Stale processes (no heartbeat update for 5 minutes) are automatically terminated and restarted. This ensures the system can recover from processes that are alive but not actively working. Changes include:

  • update_heartbeat() function to write process heartbeat timestamps
  • check_process_heartbeat() function to validate heartbeat freshness
  • Enhanced check_runners() function to monitor heartbeats and restart stuck processes
  • Comprehensive unit tests for the new functionality

Commit: c7072b9

@marrobi

Copy link
Copy Markdown
Member

Copilot this needs to be for deployment status updater, ion the API, not the runner.

…s updater

Co-authored-by: marrobi <17089773+marrobi@users.noreply.github.com>

Copilot AI commented Jun 25, 2025

Copy link
Copy Markdown
Contributor Author

Copilot this needs to be for deployment status updater, ion the API, not the runner.

Moved the heartbeat monitoring from the resource processor to the deployment status updater in the API as requested. The implementation now includes:

  • Heartbeat file updates in receive_messages()
  • check_heartbeat() method to validate heartbeat freshness
  • supervisor_with_heartbeat_check() function that monitors the heartbeat and restarts the task if it becomes stale (no update for 5 minutes)
  • Updated main.py to use the supervisor function
  • Comprehensive unit tests for the heartbeat functionality

Commit: 202e726

@marrobi

Copy link
Copy Markdown
Member

Copilot fix the linting issues:

2025-06-25 21:33:34 [ERROR] Found errors in [flake8] linter!
2025-06-25 21:33:34 [ERROR] Error code: 1. Command output:


/github/workspace/api_app/service_bus/deployment_status_updater.py:57:1: W293 blank line contains whitespace
/github/workspace/api_app/service_bus/deployment_status_updater.py:60:1: W293 blank line contains whitespace
/github/workspace/api_app/service_bus/deployment_status_updater.py:63:1: W293 blank line contains whitespace
/github/workspace/api_app/service_bus/deployment_status_updater.py:95:1: W293 blank line contains whitespace
/github/workspace/api_app/service_bus/deployment_status_updater.py:101:1: W293 blank line contains whitespace
/github/workspace/api_app/service_bus/deployment_status_updater.py:111:1: W293 blank line contains whitespace
/github/workspace/api_app/service_bus/deployment_status_updater.py:125:1: W293 blank line contains whitespace
/github/workspace/api_app/service_bus/deployment_status_updater.py:128:1: W293 blank line contains whitespace

2025-06-25 21:33:34 [INFO] ---------------------------
2025-06-25 21:33:34 [INFO] File:[/github/workspace/api_app/tests_ma/test_service_bus/test_deployment_status_update.py]
2025-06-25 21:33:34 [ERROR] Found errors in [flake8] linter!
2025-06-25 21:33:34 [ERROR] Error code: 1. Command output:

/github/workspace/api_app/tests_ma/test_service_bus/test_deployment_status_update.py:460:1: W293 blank line contains whitespace
/github/workspace/api_app/tests_ma/test_service_bus/test_deployment_status_update.py:472:1: W293 blank line contains whitespace
/github/workspace/api_app/tests_ma/test_service_bus/test_deployment_status_update.py:492:1: W293 blank line contains whitespace

And increment the API version.

Co-authored-by: marrobi <17089773+marrobi@users.noreply.github.com>

Copilot AI commented Jun 25, 2025

Copy link
Copy Markdown
Contributor Author

Copilot fix the linting issues:

2025-06-25 21:33:34 [ERROR] Found errors in [flake8] linter!
...

Fixed all linting issues by removing trailing whitespace from blank lines in both deployment_status_updater.py and test_deployment_status_update.py. Also incremented the API version from 0.24.3 to 0.24.4 as requested.

Commit: 381bd9c

@marrobi

Copy link
Copy Markdown
Member

/test-extended 381bd9c

@github-actions

Copy link
Copy Markdown

🤖 pr-bot 🤖

🏃 Running extended tests: https://github.com/microsoft/AzureTRE/actions/runs/15887800326 (with refid ce7e1779)

(in response to this comment from Marcus Robinson (@marrobi))

@marrobi
Marcus Robinson (marrobi) marked this pull request as draft September 4, 2026 10:02
Copilot AI and others added 2 commits September 4, 2026 10:05
…-4464

# Conflicts:
#	api_app/_version.py
#	api_app/service_bus/airlock_request_status_update.py
#	api_app/service_bus/deployment_status_updater.py

Co-authored-by: marrobi <17089773+marrobi@users.noreply.github.com>
async with get_credential_async_context():
raise RuntimeError("Test Error")

mock_credential.close.assert_awaited_once()

Copilot AI 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.

🟡 Changes recommended

Idle consumers can be falsely marked stale, and supervisor lifecycle and recovery timing do not yet meet the intended behavior.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 22/22 changed files
  • Comments generated: 6
  • Review effort level: Balanced

Comment thread api_app/main.py Outdated
Comment on lines 41 to 43
asyncio.create_task(deploymentStatusUpdater.supervisor_with_heartbeat_check())
asyncio.create_task(airlockStatusUpdater.supervisor_with_heartbeat_check())
yield

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Marcus Robinson (@marrobi) PR #4924 also addresses this

Comment thread api_app/service_bus/airlock_request_status_update.py
Comment on lines +69 to +70
async for msg in receiver:
complete_message = await self.process_message(msg)
Comment thread api_app/service_bus/deployment_status_updater.py
self.update_heartbeat()
task_just_started = True

await asyncio.sleep(HEARTBEAT_CHECK_INTERVAL_SECONDS)
Comment thread CHANGELOG.md Outdated
Comment on lines +83 to +84
BUG FIXES:
* Implement service bus consumer monitoring with heartbeat detection, automatic recovery, and /health endpoint integration to prevent operations getting stuck indefinitely ([#4464](https://github.com/microsoft/AzureTRE/issues/4464))
@marrobi

Copy link
Copy Markdown
Member

Copilot Fix the code for all comments in this review thread.

When a review comment includes a suggested change, apply the suggestion exactly.

Do not make changes beyond what is described in the linked review thread.

Co-authored-by: marrobi <17089773+marrobi@users.noreply.github.com>

Copilot AI commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Copilot Fix the code for all comments in this review thread.

When a review comment includes a suggested change, apply ...

Addressed all review-thread comments in commit 883cdaf. Targeted service-bus tests and flake8 pass; CodeQL found no alerts.

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.

TRE processor/UI does not seem to be picking up VM resource status changes/operations

4 participants