feat: Enhance telemetry metrics recording with sealed mode tagging
This commit is contained in:
132
src/__Libraries/StellaOps.Microservice/TypedEndpointAdapter.cs
Normal file
132
src/__Libraries/StellaOps.Microservice/TypedEndpointAdapter.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StellaOps.Microservice;
|
||||
|
||||
/// <summary>
|
||||
/// Adapts typed endpoint handlers to the raw endpoint interface.
|
||||
/// </summary>
|
||||
public static class TypedEndpointAdapter
|
||||
{
|
||||
private static readonly JsonSerializerOptions DefaultJsonOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Creates a raw handler function from a typed endpoint with request and response.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRequest">The request type.</typeparam>
|
||||
/// <typeparam name="TResponse">The response type.</typeparam>
|
||||
/// <param name="handler">The typed handler.</param>
|
||||
/// <param name="jsonOptions">Optional JSON serialization options.</param>
|
||||
/// <returns>A raw handler function.</returns>
|
||||
public static Func<RawRequestContext, CancellationToken, Task<RawResponse>> Adapt<TRequest, TResponse>(
|
||||
IStellaEndpoint<TRequest, TResponse> handler,
|
||||
JsonSerializerOptions? jsonOptions = null)
|
||||
{
|
||||
var options = jsonOptions ?? DefaultJsonOptions;
|
||||
|
||||
return async (context, cancellationToken) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// Deserialize request
|
||||
TRequest? request;
|
||||
if (context.Body == Stream.Null || context.Body.Length == 0)
|
||||
{
|
||||
request = default;
|
||||
}
|
||||
else
|
||||
{
|
||||
request = await JsonSerializer.DeserializeAsync<TRequest>(
|
||||
context.Body,
|
||||
options,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
if (request is null)
|
||||
{
|
||||
return RawResponse.BadRequest("Invalid request body");
|
||||
}
|
||||
|
||||
// Call handler
|
||||
var response = await handler.HandleAsync(request, cancellationToken);
|
||||
|
||||
// Serialize response
|
||||
return SerializeResponse(response, options);
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
return RawResponse.BadRequest($"Invalid JSON: {ex.Message}");
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return RawResponse.InternalError(ex.Message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a raw handler function from a typed endpoint with response only.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">The response type.</typeparam>
|
||||
/// <param name="handler">The typed handler.</param>
|
||||
/// <param name="jsonOptions">Optional JSON serialization options.</param>
|
||||
/// <returns>A raw handler function.</returns>
|
||||
public static Func<RawRequestContext, CancellationToken, Task<RawResponse>> Adapt<TResponse>(
|
||||
IStellaEndpoint<TResponse> handler,
|
||||
JsonSerializerOptions? jsonOptions = null)
|
||||
{
|
||||
var options = jsonOptions ?? DefaultJsonOptions;
|
||||
|
||||
return async (context, cancellationToken) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// Call handler
|
||||
var response = await handler.HandleAsync(cancellationToken);
|
||||
|
||||
// Serialize response
|
||||
return SerializeResponse(response, options);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return RawResponse.InternalError(ex.Message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a raw handler function from a raw endpoint.
|
||||
/// </summary>
|
||||
/// <param name="handler">The raw handler.</param>
|
||||
/// <returns>A raw handler function.</returns>
|
||||
public static Func<RawRequestContext, CancellationToken, Task<RawResponse>> Adapt(
|
||||
IRawStellaEndpoint handler)
|
||||
{
|
||||
return handler.HandleAsync;
|
||||
}
|
||||
|
||||
private static RawResponse SerializeResponse<TResponse>(TResponse response, JsonSerializerOptions options)
|
||||
{
|
||||
var json = JsonSerializer.SerializeToUtf8Bytes(response, options);
|
||||
var headers = new HeaderCollection();
|
||||
headers.Set("Content-Type", "application/json; charset=utf-8");
|
||||
|
||||
return new RawResponse
|
||||
{
|
||||
StatusCode = 200,
|
||||
Headers = headers,
|
||||
Body = new MemoryStream(json)
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user