Is it service or entrypoint who should transform request data into domain model - go

I have a simple microservice build with go-kit and protocol buffers. And I have a question about where should I transform request into business-ish data.
For instance, I have following protobuf
import "google/protobuf/empty.proto";
service Location {
rpc DeleteLocation(DeleteLocationRequest) returns (google.protobuf.Empty) {};
}
message DeleteLocationRequest {
string locationUID = 1;
}
A request has uid to delete as a string; however, I would like to use my custom struct
type LocationUID struct {
uuid.UUID
}
So, I'm wondering where it's better to transform incoming string into domain object.
Should I do it inside entrypoint? Get data from reqeust, transform it into LocationUID and then call service with business logic to perform a required action.
Or is it better to place inside service? Pass the whole request object from entrypoint into a service and then, inside service, get reqired data, transform it, validate (and return an error if data is invalid)

Related

Is there known way to add new syntax features to Protobuf?

Protobuf provides service keyword that defines rpc-interface of one application.
I also want to use concept of entity which means that is part of service (one service contains multiple entities). Each entity type has own unique identifier that gives possibility to address different entities in service.
I would like to use proto like this
message UserReq {
string username = 1;
string password = 2;
}
message RegReq {
uint8 result_code = 1;
}
message RemoteEntityInterface
{
MyEntity entity = 1;
}
message GiveItemResult
{
uint8 result_code = 1;
}
service MyService {
rpc RegisterUser (UserReq) returns (RegReq) {}
rpc Login(UserReq) returns (RemoteEntityInterface) {}
}
entity MyEntity
{
rpc GiveItem (GiveItemReq) returns (GiveItemResult) {}
}
As you can see in example, I used unknown for protobuf keyword entity, this keyword means that MyService can return the interface to some remote object (MyEntity) by using Login remote method.
What are the ways to do this? (maybe write plugin or known way to modify source code of protobuf). Or maybe there are more flexible solutions than protobuf?
I also would like to use multiple parameters per one rpc; adding java-like attributes to rpc; service and entity; and data-model for entity (variables/fields) to add real-time replication support from entity to another service.
I think it is very flexible for services in game-development.
The only official way to extend .proto syntax is to define custom options.
For example, you could have something like:
extend google.protobuf.ServiceOptions {
optional bool is_entity = 123456;
}
service MyEntity
{
option (is_entity) = true;
rpc GiveItem (GiveItemReq) returns (GiveItemResult) {}
}
The default code generator will not do anything special with this option, but you can access it from your own code and from a protoc plugin if you write one.

Can gRPC method return a message with a field that could be string or null?

I'm designing a gRPC service written in Go.
In front of the gRPC service is Envoy which converts incoming HTTP requests to gRPC and converts the gRPC responses to JSON.
The requirement of this application is to have an endpoint that returns the following JSON object:
{
my_id: "AAA"
}
I can model this response pretty simply in Go like this:
// A MyResponse object.
message MyResponse {
// contents is a list of contents.
string my_id = 1;
}
But the requirement that I have is that sometimes my_id might be null. In that case, I want to get the following JSON back:
{
my_id: null
}
it
Is it possible to modify MyResponse such that my_id can be a string or a null in the JSON object that is returned? If so, how? If not, isn't this a pretty big gap in the design of gRPC?
I suggest you to use the StringValue field of the Package google.protobuf:
StringValue Wrapper message for string.
The JSON representation for StringValue is JSON string.
So in your proto files, you should import:
import "google/protobuf/wrappers.proto";
then use as example:
google.protobuf.StringValue name = 2;
For handle the values you can check the wrappers.StringValue
type of the github.com/golang/protobuf/ptypes/wrappers package and the helpers of the google.golang.org/protobuf/types/known/wrapperspb repo.

Returning a list of messages

Given that i have multiple models, each needed to have their own create/get/get list API.
Do i need to add two different types of messages (single and list) for every model?
For example :
If i have a student type -
message Student{
string name = 1;
}
and a rpc:
rpc CreateStudent(Student) returns (google.protobuf.Empty){
..............
}
If i'd like to add a rpc to create a list of students, or get a list of students
rpc CreateStudends(??????) returns (google.protobuf.Empty){
..............
}
rpc GetAllStudents() returns (??????){
..............
}
Do i need to also define
message StudentList{
repeated Student students = 1;
}
Or is there a way to use a list type directly in the message input/output?
Yes, basically - you would want a different message type per element type, or maybe a single root type with a oneof style content. Raw protobuf does not include a concept of generics or templates.
Some libraries do, but: that's outside of the specification.
You can simply add the stream keyword to your RPCs. No need to define a message field as repeated, stream will send or receive multiple independent messages.
message Student {
string name = 1;
}
with RPCs:
rpc CreateStudent(Student) returns (google.protobuf.Empty) {
..............
}
rpc CreateStudents(stream Student) returns (google.protobuf.Empty) {
..............
}
rpc GetAllStudents() returns (stream Student) {
..............
}
It's good practice to send/stream a response object rather than empty. Otherwise, you only have the gRPC response code to indicate a problem and will need to reference the logs to debug.

Idiomatic way of verifying a reactive request before actually persisting to the database

I have an endpoint that accepts as well as returns a reactive type. What I'm trying to achieve is to somehow verify that the complete reactive request (that is actually an array of resources) is valid before persisting the changes to the database (read Full-Update of a ressource). The question is not so much concerned with how to actually verify the request but more with how to chain the steps together using which of springs reactive handler methods (map, flatMap and the likes) in the desired order which is basically:
verify correctness of request (the Ressource is properly annotated with JSR-303 annotations)
clear the current resource in case of valid request
persist new resources in the database after clearing the database
Let's assume the following scenario:
val service : ResourceService
#PostMapping("/resource/")
fun replaceResources(#Valid #RequestBody resources:
Flux<RessourceDto>): Flux<RessourceDto> {
var deleteWrapper = Mono.fromCallable {
service.deleteAllRessources()
}
deleteWrapper = deleteWrapper.subscribeOn(Schedulers.elastic())
return deleteWrapper.thenMany<RessourceDto> {
resources
.map(mapper::map) // map to model object
.flatMap(service::createResource)
.map(mapper::map) // map to dto object
.subscribeOn(Schedulers.parallel())
}
}
//alternative try
#PostMapping("/resourceAlternative/")
override fun replaceResourcesAlternative2(#RequestBody resources:
Flux<ResourceDto>): Flux<ResourceDto> {
return service.deleteAllResources()
.thenMany<ResourceDto> {
resources
.map(mapper::map)
.flatMap(service::createResource)
.map(mapper::map)
}
}
Whats the idiomatic way of doing this in a reactive fashion?

.Net Web API IActionFilter.OnActionExecuted return type

I have an application on .Net Web API. After each action get executed, I want to take a look at result and change something in that.
Say my API controllerAction looks like
public Car Get()
{
...
}
After the action is executed, I want to modify the properties of return type in this case Car (but can be different for different action).
I know that IActionFilter.OnActionExecuted() gets called after an action gets executed. But I am not sure how to access the return type in this method.
You should be able to do this by looking at the response on the action executed context. If you want to get the car and modify it you could write something like this:
Car car;
if (actionExecutedContext.Response.TryGetContentValue<Car>(out car))
{
// modify the car to send back in the response
}
If you want to check the type of the response, you could write:
ObjectContent objectContent = actionExecutedContext.Response.Content as ObjectContent;
if (objectContent != null)
{
Type responseType = objectContent.ObjectType;
// do stuff with the type
}

Resources