跳到主要内容

与外部 gRPC 服务协作

很多时候你想在 gRPC 服务器中包含不是从 Ent 模式自动生成的方法。 为达到这一目的,在 entpb 目录中额外的 .proto 文件中定义附加的服务。

信息

可以在 本拉取请求 中找到本部分描述的修改内容。

例如假设你想要添加一个名为 TopUser 的方法,这个方法返回具有最大 ID 编号值的用户。 可以在 entpb 目录中创建一个新的 .proto 文件,并定义新的服务:

ent/proto/entpb/ext.proto
syntax = "proto3";

package entpb;

option go_package = "github.com/rotemtam/ent-grpc-example/ent/proto/entpb";

import "entpb/entpb.proto";

import "google/protobuf/empty.proto";


service ExtService {
rpc TopUser ( google.protobuf.Empty ) returns ( User );
}

下一步在 protoc 命令输入中更新 entpb/generate.go 以包含新的文件:

ent/proto/entpb/generate.go
- //go:generate protoc -I=.. --go_out=.. --go-grpc_out=.. --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative --entgrpc_out=.. --entgrpc_opt=paths=source_relative,schema_path=../../schema entpb/entpb.proto 
+ //go:generate protoc -I=.. --go_out=.. --go-grpc_out=.. --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative --entgrpc_out=.. --entgrpc_opt=paths=source_relative,schema_path=../../schema entpb/entpb.proto entpb/ext.proto

再次运行代码生成:

go generate ./...

可以看到一些新的文件已经在 ent/proto/entpb 目录生成了:

tree
.
|-- entpb.pb.go
|-- entpb.proto
|-- entpb_grpc.pb.go
|-- entpb_user_service.go
|-- ext.pb.go
|-- ext.proto
|-- ext_grpc.pb.go
`-- generate.go

0 directories, 9 files

现在你可以在 ent/proto/entpb/ext.go 中实现 TopUser 方法:

ent/proto/entpb/ext.go
package entpb

import (
"context"

"github.com/rotemtam/ent-grpc-example/ent"
"github.com/rotemtam/ent-grpc-example/ent/user"
"google.golang.org/protobuf/types/known/emptypb"
)

// ExtService implements ExtServiceServer.
type ExtService struct {
client *ent.Client
UnimplementedExtServiceServer
}

// TopUser returns the user with the highest ID.
func (s *ExtService) TopUser(ctx context.Context, _ *emptypb.Empty) (*User, error) {
id := s.client.User.Query().Aggregate(ent.Max(user.FieldID)).IntX(ctx)
user := s.client.User.GetX(ctx, id)
return toProtoUser(user)
}

// NewExtService returns a new ExtService.
func NewExtService(client *ent.Client) *ExtService {
return &ExtService{
client: client,
}
}

将新的服务添加到 gRPC 服务器

最后更新 cmd/server.go 以包含新的服务:

cmd/server.go
package main

import (
"context"
"log"
"net"

_ "github.com/mattn/go-sqlite3"
"github.com/rotemtam/ent-grpc-example/ent"
"github.com/rotemtam/ent-grpc-example/ent/proto/entpb"
"google.golang.org/grpc"
)

func main() {
// Initialize an ent client.
client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
if err != nil {
log.Fatalf("failed opening connection to sqlite: %v", err)
}
defer client.Close()

// Run the migration tool (creating tables, etc).
if err := client.Schema.Create(context.Background()); err != nil {
log.Fatalf("failed creating schema resources: %v", err)
}

// Initialize the generated User service.
svc := entpb.NewUserService(client)

// Create a new gRPC server (you can wire multiple services to a single server).
server := grpc.NewServer()

// Register the User service with the server.
entpb.RegisterUserServiceServer(server, svc)

// Register the external ExtService service with the server.
entpb.RegisterExtServiceServer(server, entpb.NewExtService(client))

// Open port 5000 for listening to traffic.
lis, err := net.Listen("tcp", ":5000")
if err != nil {
log.Fatalf("failed listening: %s", err)
}

// Listen for traffic indefinitely.
if err := server.Serve(lis); err != nil {
log.Fatalf("server ended: %s", err)
}
}