--- paths: - "**/*.proto" - "**/Protos/**" - "*Grpc*" --- # gRPC Integration ## Proto File Conventions Proto files live in `Protos/` directory. The source generator (`Svrnty.CQRS.Grpc.Generators`) auto-generates service implementations at compile time. ### Service Structure ```protobuf service CommandService { rpc PlaceOrder (PlaceOrderCommandRequest) returns (PlaceOrderCommandResponse); } service QueryService { rpc FetchUserById (FetchUserByIdQueryRequest) returns (FetchUserByIdQueryResponse); } service DynamicQueryService { rpc QueryOrders (DynamicQueryOrdersRequest) returns (DynamicQueryOrdersResponse); } ``` ### Naming Rules - RPC method name: command/query name without the `Command`/`Query` suffix - Request message: `{Name}CommandRequest` or `{Name}QueryRequest` - Response message: `{Name}CommandResponse` or `{Name}QueryResponse` - Dynamic query request: `DynamicQuery{PluralEntity}Request` - Dynamic query response: `DynamicQuery{PluralEntity}Response` - Fields use `snake_case` (proto convention), mapped case-insensitively to C# `PascalCase` properties ### Field Mapping C# property names must match proto field names (case-insensitive): | C# Property | Proto Field | |---------------|-----------------| | `UserId` | `user_id` | | `Name` | `name` | | `EmailAddress`| `email_address` | | `OrderItems` | `order_items` | ### Type Mapping | C# | Proto | |-------------|-------------| | `int` | `int32` | | `long` | `int64` | | `string` | `string` | | `bool` | `bool` | | `double` | `double` | | `float` | `float` | | `List` | `repeated T`| | complex type| `message` | ### Dynamic Query Messages (standard, reuse across entities) ```protobuf message DynamicQueryFilter { string path = 1; int32 type = 2; // PoweredSoft.DynamicQuery.Core.FilterType string value = 3; repeated DynamicQueryFilter and = 4; repeated DynamicQueryFilter or = 5; } message DynamicQuerySort { string path = 1; bool ascending = 2; } message DynamicQueryGroup { string path = 1; } message DynamicQueryAggregate { string path = 1; int32 type = 2; // PoweredSoft.DynamicQuery.Core.AggregateType } ``` ## Source Generator Behavior The generator in `Svrnty.CQRS.Grpc.Generators` auto-creates: - `CommandServiceImpl` — implements `CommandService.CommandServiceBase` - `QueryServiceImpl` — implements `QueryService.QueryServiceBase` - `DynamicQueryServiceImpl` — implements `DynamicQueryService.DynamicQueryServiceBase` - `GrpcServiceRegistration` — auto-registration code Generated implementations handle: 1. Request-to-POCO property mapping 2. Validator invocation (if registered) with Google Rich Error Model errors 3. Handler invocation with proper `CancellationToken` 4. DI scope management via `IServiceScopeFactory` ## Validation in gRPC Validation errors return `google.rpc.Status` with `BadRequest` detail containing `FieldViolations`. This is automatic — do not manually validate in handlers. ## Registration ```csharp builder.Services.AddSvrntyCqrs(cqrs => { cqrs.AddGrpc(grpc => grpc.EnableReflection()); // reflection for grpcurl/grpcui }); ```