A gRPC adapter exposes an application’s operations to gRPC clients without making the application core handle gRPC request types. In an Order service, it accepts generated request objects, converts their data into domain objects, calls the APIPort application interface, and converts the result into a generated response. section 4.2.6
func (a Adapter) Create(ctx context.Context, request *order.CreateOrderRequest) (*order.CreateOrderResponse, error) { #1
var orderItems []domain.OrderItem
for _, orderItem := range request.OrderItems { #2
orderItems = append(orderItems, domain.OrderItem{
ProductCode: orderItem.ProductCode,
UnitPrice: orderItem.UnitPrice,
Quantity: orderItem.Quantity,
})
}
newOrder := domain.NewOrder(request.UserId, orderItems) #3
result, err := a.api.PlaceOrder(newOrder) #4
if err != nil {
return nil, err
}
return &order.CreateOrderResponse{OrderId: result.ID}, nil
}
The Create handler maps each requested item to a domain.OrderItem, constructs an order, calls PlaceOrder, and returns the resulting order ID. An application error is returned to the client rather than converted into a success response. section 4.2.6
The adapter holds an APIPort and a listening port, and embeds the generated UnimplementedOrderServer. To run it, open a TCP listener, create a gRPC server, register the generated Order service, and serve requests. Reflection is enabled in the development environment; grpcurl can test the endpoint using reflection or the relevant .proto files. section 4.2.6
package main
import (
"github.com/huseyinbabal/microservices/order/config"
"github.com/huseyinbabal/microservices/order/internal/adapters/db"
"github.com/huseyinbabal/microservices/order/internal/adapters/grpc"
"github.com/huseyinbabal/microservices/order/internal/application/core/
api"
"log"
)
func main() {
dbAdapter, err := db.NewAdapter(config.GetDataSourceURL())
if err != nil {
log.Fatalf("Failed to connect to database. Error: %v", err)
}
application := api.NewApplication(dbAdapter)
grpcAdapter := grpc.NewAdapter(application, config.GetApplicationPort())
grpcAdapter.Run()
}
Wire dependencies at startup: create the database adapter, pass it to the application, then pass the application and configured port to the gRPC adapter before calling Run. section 4.2.7
Keep subsequent business steps behind the application interface. When placing an order also charges a customer, PlaceOrder saves the order and invokes a Payment service through a payment adapter; the gRPC Create handler still calls PlaceOrder. A payment failure can reach the client as an error. Distinguishing errors would let a client decide whether to retry or treat the operation as failed, but that distinction is not implemented here. section 5.2.6
