Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
288 views
in Technique[技术] by (71.8m points)

go - How to make auto-generated unique id fields readonly in protobuf?

I am very new to protobuf so please bare with me.

I noticed that it is common to have a unique identifier in a protobuf message type like so:

message ToDo {
    int64 id = 1; // unique id
    string title = 2;
    string description = 3;
    google.protobuf.Timestamp reminder = 4;
}

The message type can then be used in a service for a create request e.g.

service ToDoService {
  rpc Create(Todo) returns (CreateResponse) {}
}

My expected behaviour is the request to be processed with the id generated when inserting into the DB. However, this means that an id can still be passed in the request payload, but will essentially be ignored, since the id field in ToDo is only relevant for read responses.

For example, todo.Id is not referenced at all in the Create method below.

func (s *toDoServiceServer) Create(ctx context.Context, todo *v1.ToDo) (*v1.CreateResponse, error) {
    
    // ... not relevant

    // insert ToDo entity data
    res, err := c.ExecContext(ctx, "INSERT INTO ToDo(`Title`, `Description`, `Reminder`) VALUES(?, ?, ?)",
        todo.ToDo.Title, todo.ToDo.Description, reminder)
    if err != nil {
        return nil, status.Error(codes.Unknown, "failed to insert into ToDo-> "+err.Error())
    }

    // get ID of creates ToDo
    id, err := res.LastInsertId()
    if err != nil {
        return nil, status.Error(codes.Unknown, "failed to retrieve id for created ToDo-> "+err.Error())
    }

    return &v1.CreateResponse{
        Id:  id,
    }, nil
}

In my opinion this is a bit confusing when making a request to the service, since it could be assumed that an id should be supplied, but in reality it should not be. Since there are no readonly fields in protobuf, is the only option to have two different message types for ToDo, where id is only present in one? e.g.

message ToDoRequest {
    // no id
    string title = 1;
    string description = 2;
    google.protobuf.Timestamp reminder = 3;
}

message ToDo {
    int64 id = 1; // unique id
    string title = 2;
    string description = 3;
    google.protobuf.Timestamp reminder = 4;
}

That way ToDoRequest is only used for create/update requests and ToDo is only used for read responses. My only problem is that it seems tedious defining all other fields twice just to make id 'readonly'.

question from:https://stackoverflow.com/questions/65935468/how-to-make-auto-generated-unique-id-fields-readonly-in-protobuf

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can compose messages too

syntax = "proto3";

package todo;

import "google/protobuf/timestamp.proto";

message ToDo {
    string title = 1;
    string description = 2;
    google.protobuf.Timestamp reminder = 3;
}

message ToDoEntity {
    int64 id = 1;
    ToDo todo = 2;
}

message ToDoRequest {
    ToDo todo = 1;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...