Files
RoslynBridge/RoslynBridge.WebApi/Controllers/HealthController.cs
AJ Isaacs 1cbfba3893 Add WebAPI middleware for multi-instance Roslyn Bridge routing
Add RoslynBridge.WebApi - ASP.NET Core 8.0 middleware that:
- Provides a centralized REST API for accessing multiple VS instances
- Manages instance registry with discovery by port, solution, or PID
- Proxies requests to the appropriate VS instance
- Tracks request/response history for debugging
- Auto-cleanup of stale instances via background service

Features:
- Health endpoints: /api/health, /api/health/ping
- Roslyn endpoints: /api/roslyn/projects, /api/roslyn/diagnostics, etc.
- Instance management: /api/instances (register, heartbeat, unregister)
- History tracking: /api/history, /api/history/stats
- Swagger UI at root (/) for API documentation
- CORS enabled for web applications

Services:
- InstanceRegistryService: Thread-safe registry of VS instances
- HistoryService: In-memory request/response history (max 1000 entries)
- InstanceCleanupService: Background service to remove stale instances
- RoslynBridgeClient: HTTP client for proxying to VS instances

Update RoslynBridge.sln to include RoslynBridge.WebApi project.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 23:51:33 -04:00

73 lines
2.5 KiB
C#

using Microsoft.AspNetCore.Mvc;
using RoslynBridge.WebApi.Models;
using RoslynBridge.WebApi.Services;
namespace RoslynBridge.WebApi.Controllers;
/// <summary>
/// Health check and status controller
/// </summary>
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class HealthController : ControllerBase
{
private readonly IRoslynBridgeClient _bridgeClient;
private readonly ILogger<HealthController> _logger;
public HealthController(IRoslynBridgeClient bridgeClient, ILogger<HealthController> logger)
{
_bridgeClient = bridgeClient;
_logger = logger;
}
/// <summary>
/// Get the health status of the middleware and Visual Studio plugin
/// </summary>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Health status information</returns>
/// <response code="200">Service is healthy</response>
/// <response code="503">Service is unhealthy</response>
[HttpGet]
[ProducesResponseType(typeof(HealthCheckResponse), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(HealthCheckResponse), StatusCodes.Status503ServiceUnavailable)]
public async Task<ActionResult<HealthCheckResponse>> GetHealth(CancellationToken cancellationToken)
{
var response = new HealthCheckResponse();
try
{
var isVsPluginHealthy = await _bridgeClient.IsHealthyAsync(null, cancellationToken);
response.VsPluginStatus = isVsPluginHealthy ? "Connected" : "Disconnected";
if (!isVsPluginHealthy)
{
response.Status = "Degraded";
_logger.LogWarning("Visual Studio plugin is not accessible");
return StatusCode(StatusCodes.Status503ServiceUnavailable, response);
}
_logger.LogInformation("Health check passed");
return Ok(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "Health check failed");
response.Status = "Unhealthy";
response.VsPluginStatus = "Error";
return StatusCode(StatusCodes.Status503ServiceUnavailable, response);
}
}
/// <summary>
/// Simple ping endpoint
/// </summary>
/// <returns>Pong response</returns>
[HttpGet("ping")]
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
public IActionResult Ping()
{
return Ok(new { message = "pong", timestamp = DateTime.UtcNow });
}
}