chore(furniture-bff): merge contract integration branch
This commit is contained in:
commit
df0b6dc57d
@ -11,5 +11,6 @@
|
||||
## Edge Responsibilities
|
||||
|
||||
- Validate and normalize consumer request inputs.
|
||||
- Map downstream service responses to consumer-facing shapes.
|
||||
- Map edge requests to furniture-service transport-neutral contracts.
|
||||
- Map downstream furniture-service responses to consumer-facing shapes.
|
||||
- Map downstream errors to consistent API error models.
|
||||
|
||||
@ -5,9 +5,14 @@ package "furniture-bff" {
|
||||
class Program
|
||||
interface IGetFurnitureAvailabilityHandler
|
||||
class GetFurnitureAvailabilityHandler
|
||||
interface IFurnitureAvailabilityEdgeContractAdapter
|
||||
interface IFurnitureAvailabilityEdgeGrpcContractAdapter
|
||||
class GetFurnitureAvailabilityEdgeGrpcContract
|
||||
interface IFurnitureServiceClient
|
||||
|
||||
GetFurnitureAvailabilityHandler ..|> IGetFurnitureAvailabilityHandler
|
||||
GetFurnitureAvailabilityHandler --> IFurnitureAvailabilityEdgeContractAdapter
|
||||
IFurnitureAvailabilityEdgeGrpcContractAdapter --> GetFurnitureAvailabilityEdgeGrpcContract
|
||||
GetFurnitureAvailabilityHandler --> IFurnitureServiceClient
|
||||
}
|
||||
|
||||
@ -16,5 +21,5 @@ package "furniture-service" as FurnitureService
|
||||
|
||||
Consumers --> Program : REST
|
||||
Program --> IGetFurnitureAvailabilityHandler
|
||||
IFurnitureServiceClient ..> FurnitureService : gRPC/internal
|
||||
IFurnitureServiceClient ..> FurnitureService : service contracts
|
||||
@enduml
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
- Preserve correlation headers to downstream service calls.
|
||||
- Add correlation headers if missing at the edge.
|
||||
- Populate furniture-service request contracts with correlation identifiers.
|
||||
|
||||
## Observability Baseline
|
||||
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
using Furniture.Bff.Contracts.Api;
|
||||
using Furniture.Service.Contracts.UseCases;
|
||||
|
||||
namespace Furniture.Bff.Application.Adapters;
|
||||
|
||||
/// <summary>
|
||||
/// Defines adapter boundary between furniture BFF edge contracts and furniture service contracts.
|
||||
/// </summary>
|
||||
public interface IFurnitureAvailabilityEdgeContractAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Maps edge API request into furniture service request contract.
|
||||
/// </summary>
|
||||
/// <param name="request">Edge API request.</param>
|
||||
/// <returns>Furniture service request contract.</returns>
|
||||
GetFurnitureAvailabilityRequest ToServiceRequest(GetFurnitureAvailabilityApiRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Maps furniture service response contract into edge API response.
|
||||
/// </summary>
|
||||
/// <param name="response">Furniture service response contract.</param>
|
||||
/// <returns>Edge API response.</returns>
|
||||
GetFurnitureAvailabilityApiResponse ToApiResponse(GetFurnitureAvailabilityResponse response);
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
using Furniture.Bff.Application.Grpc;
|
||||
using Furniture.Bff.Contracts.Api;
|
||||
|
||||
namespace Furniture.Bff.Application.Adapters;
|
||||
|
||||
/// <summary>
|
||||
/// Defines adapter boundary for gRPC translation at the furniture edge.
|
||||
/// </summary>
|
||||
public interface IFurnitureAvailabilityEdgeGrpcContractAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Maps edge API request into gRPC contract shape.
|
||||
/// </summary>
|
||||
/// <param name="request">Edge API request.</param>
|
||||
/// <returns>gRPC request contract shape.</returns>
|
||||
GetFurnitureAvailabilityEdgeGrpcContract ToGrpc(GetFurnitureAvailabilityApiRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Maps gRPC request contract shape back into edge API request.
|
||||
/// </summary>
|
||||
/// <param name="contract">gRPC request contract shape.</param>
|
||||
/// <returns>Edge API request.</returns>
|
||||
GetFurnitureAvailabilityApiRequest FromGrpc(GetFurnitureAvailabilityEdgeGrpcContract contract);
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
using Furniture.Bff.Contracts.Api;
|
||||
using Furniture.Service.Contracts.UseCases;
|
||||
|
||||
namespace Furniture.Bff.Application.Adapters;
|
||||
|
||||
@ -10,7 +10,7 @@ public interface IFurnitureServiceClient
|
||||
/// <summary>
|
||||
/// Retrieves furniture availability from downstream service.
|
||||
/// </summary>
|
||||
/// <param name="furnitureId">Furniture identifier.</param>
|
||||
/// <returns>Consumer-ready availability contract.</returns>
|
||||
Task<GetFurnitureAvailabilityApiResponse> GetAvailabilityAsync(string furnitureId);
|
||||
/// <param name="request">Service-layer availability request contract.</param>
|
||||
/// <returns>Service-layer availability response contract.</returns>
|
||||
Task<GetFurnitureAvailabilityResponse> GetAvailabilityAsync(GetFurnitureAvailabilityRequest request);
|
||||
}
|
||||
|
||||
@ -6,5 +6,6 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Furniture.Bff.Contracts\Furniture.Bff.Contracts.csproj" />
|
||||
<ProjectReference Include="..\..\..\furniture-service\src\Furniture.Service.Contracts\Furniture.Service.Contracts.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
namespace Furniture.Bff.Application.Grpc;
|
||||
|
||||
/// <summary>
|
||||
/// Defines minimal gRPC contract shape for furniture availability edge translation.
|
||||
/// </summary>
|
||||
/// <param name="FurnitureId">Furniture identifier provided by consumers.</param>
|
||||
/// <param name="CorrelationId">Request correlation identifier.</param>
|
||||
public sealed record GetFurnitureAvailabilityEdgeGrpcContract(string FurnitureId, string CorrelationId);
|
||||
@ -6,12 +6,16 @@ namespace Furniture.Bff.Application.Handlers;
|
||||
/// <summary>
|
||||
/// Default edge handler implementation for furniture availability.
|
||||
/// </summary>
|
||||
public sealed class GetFurnitureAvailabilityHandler(IFurnitureServiceClient serviceClient)
|
||||
public sealed class GetFurnitureAvailabilityHandler(
|
||||
IFurnitureServiceClient serviceClient,
|
||||
IFurnitureAvailabilityEdgeContractAdapter contractAdapter)
|
||||
: IGetFurnitureAvailabilityHandler
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<GetFurnitureAvailabilityApiResponse> HandleAsync(GetFurnitureAvailabilityApiRequest request)
|
||||
public async Task<GetFurnitureAvailabilityApiResponse> HandleAsync(GetFurnitureAvailabilityApiRequest request)
|
||||
{
|
||||
return serviceClient.GetAvailabilityAsync(request.FurnitureId);
|
||||
var serviceRequest = contractAdapter.ToServiceRequest(request);
|
||||
var serviceResponse = await serviceClient.GetAvailabilityAsync(serviceRequest);
|
||||
return contractAdapter.ToApiResponse(serviceResponse);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,4 +4,5 @@ namespace Furniture.Bff.Contracts.Api;
|
||||
/// External REST request contract for furniture availability.
|
||||
/// </summary>
|
||||
/// <param name="FurnitureId">Furniture identifier provided by consumers.</param>
|
||||
public sealed record GetFurnitureAvailabilityApiRequest(string FurnitureId);
|
||||
/// <param name="CorrelationId">Cross-service correlation identifier.</param>
|
||||
public sealed record GetFurnitureAvailabilityApiRequest(string FurnitureId, string CorrelationId = "");
|
||||
|
||||
@ -4,5 +4,6 @@ namespace Furniture.Bff.Contracts.Api;
|
||||
/// External REST response contract for furniture availability.
|
||||
/// </summary>
|
||||
/// <param name="FurnitureId">Requested furniture identifier.</param>
|
||||
/// <param name="DisplayName">Display name to present to consumer clients.</param>
|
||||
/// <param name="QuantityAvailable">Availability value for client display.</param>
|
||||
public sealed record GetFurnitureAvailabilityApiResponse(string FurnitureId, int QuantityAvailable);
|
||||
public sealed record GetFurnitureAvailabilityApiResponse(string FurnitureId, string DisplayName, int QuantityAvailable);
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
using Furniture.Bff.Contracts.Api;
|
||||
|
||||
namespace Furniture.Bff.Application.UnitTests;
|
||||
|
||||
public class ContractShapeTests
|
||||
{
|
||||
[Fact]
|
||||
public void GetFurnitureAvailabilityApiRequest_WhenCreated_StoresCorrelationId()
|
||||
{
|
||||
var request = new GetFurnitureAvailabilityApiRequest("FUR-001", "corr-123");
|
||||
|
||||
Assert.Equal("FUR-001", request.FurnitureId);
|
||||
Assert.Equal("corr-123", request.CorrelationId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetFurnitureAvailabilityApiResponse_WhenCreated_StoresDisplayName()
|
||||
{
|
||||
var response = new GetFurnitureAvailabilityApiResponse("FUR-001", "Chair", 8);
|
||||
|
||||
Assert.Equal("FUR-001", response.FurnitureId);
|
||||
Assert.Equal("Chair", response.DisplayName);
|
||||
Assert.Equal(8, response.QuantityAvailable);
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
using Furniture.Bff.Application.Adapters;
|
||||
using Furniture.Bff.Application.Handlers;
|
||||
using Furniture.Bff.Contracts.Api;
|
||||
using Furniture.Service.Contracts.UseCases;
|
||||
|
||||
namespace Furniture.Bff.Application.UnitTests;
|
||||
|
||||
@ -9,19 +10,38 @@ public class GetFurnitureAvailabilityHandlerTests
|
||||
[Fact]
|
||||
public async Task HandleAsync_WhenCalled_DelegatesToServiceClient()
|
||||
{
|
||||
var handler = new GetFurnitureAvailabilityHandler(new FakeFurnitureServiceClient());
|
||||
var handler = new GetFurnitureAvailabilityHandler(
|
||||
new FakeFurnitureServiceClient(),
|
||||
new FakeFurnitureAvailabilityEdgeContractAdapter());
|
||||
|
||||
var response = await handler.HandleAsync(new GetFurnitureAvailabilityApiRequest("FUR-001"));
|
||||
var response = await handler.HandleAsync(new GetFurnitureAvailabilityApiRequest("FUR-001", "corr-123"));
|
||||
|
||||
Assert.Equal("FUR-001", response.FurnitureId);
|
||||
Assert.Equal("Chair", response.DisplayName);
|
||||
Assert.Equal(3, response.QuantityAvailable);
|
||||
}
|
||||
|
||||
private sealed class FakeFurnitureServiceClient : IFurnitureServiceClient
|
||||
{
|
||||
public Task<GetFurnitureAvailabilityApiResponse> GetAvailabilityAsync(string furnitureId)
|
||||
public Task<GetFurnitureAvailabilityResponse> GetAvailabilityAsync(GetFurnitureAvailabilityRequest request)
|
||||
{
|
||||
return Task.FromResult(new GetFurnitureAvailabilityApiResponse(furnitureId, 3));
|
||||
return Task.FromResult(new GetFurnitureAvailabilityResponse(request.FurnitureId, "Chair", 3));
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeFurnitureAvailabilityEdgeContractAdapter : IFurnitureAvailabilityEdgeContractAdapter
|
||||
{
|
||||
public GetFurnitureAvailabilityRequest ToServiceRequest(GetFurnitureAvailabilityApiRequest request)
|
||||
{
|
||||
return new GetFurnitureAvailabilityRequest(request.FurnitureId, request.CorrelationId);
|
||||
}
|
||||
|
||||
public GetFurnitureAvailabilityApiResponse ToApiResponse(GetFurnitureAvailabilityResponse response)
|
||||
{
|
||||
return new GetFurnitureAvailabilityApiResponse(
|
||||
response.FurnitureId,
|
||||
response.DisplayName,
|
||||
response.QuantityAvailable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user