Skip to content

Conversation

@akoserwal
Copy link

closes #433

Add gRPC support

@jem-davies jem-davies self-assigned this Aug 19, 2025
@akoserwal
Copy link
Author

One issue with the plugin is that it requires the gRPC server to implement pb.UnimplementedBentoIngressServer to publish and subscribe, which is not feasible in most cases, as it necessitates additional code changes in the application server code. I will replace the generic implementation, which will work without any code changes to the server or receiver client.

@jem-davies
Copy link
Collaborator

One issue with the plugin is that it requires the gRPC server to implement pb.UnimplementedBentoIngressServer to publish and subscribe, which is not feasible in most cases, as it necessitates additional code changes in the application server code. I will replace the generic implementation, which will work without any code changes to the server or receiver client.

This has been on my want-to-have list for a while! Thanks so much for the effort with the PR. I am currently reading up on gRPC - then I will give the PR a good review.

From my initial thoughts - and what you pertain to in your comment - would it make sense to follow how Bento works with http, we have a http_client and http_server inputs & outputs - so like grpc_client & grpc_server. What we have on this PR would be the grpc_client I am thinking.

When you say you "will replace the generic implementation" - is that a change you wish to make in a follow-up or change on this PR?

@akoserwal
Copy link
Author

One issue with the plugin is that it requires the gRPC server to implement pb.UnimplementedBentoIngressServer to publish and subscribe, which is not feasible in most cases, as it necessitates additional code changes in the application server code. I will replace the generic implementation, which will work without any code changes to the server or receiver client.

This has been on my want-to-have list for a while! Thanks so much for the effort with the PR. I am currently reading up on gRPC - then I will give the PR a good review.

From my initial thoughts - and what you pertain to in your comment - would it make sense to follow how Bento works with http, we have a http_client and http_server inputs & outputs - so like grpc_client & grpc_server. What we have on this PR would be the grpc_client I am thinking.

When you say you "will replace the generic implementation" - is that a change you wish to make in a follow-up or change on this PR?

yes

@jem-davies
Copy link
Collaborator

yes

Which?

@akoserwal
Copy link
Author

yes

Which? sorry, I can create a follow up pr, that will be better as it will new changes.

Copy link
Collaborator

@jem-davies jem-davies left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that I would want to resolve some of the obvious issues - then spend more time looking at the implementation.

It has been on my radar to do some gRPC components for Bento - I think that we might want to think about if this approach is the right one - and if we could do something more dynamic so we don't have to use protoc to generate go source at compile time, then have the user stuck with a vague protobuf schema. If we could take the approach like https://github.com/fullstorydev/grpcurl so it's more dynamic.

I am thinking that I will put effort into writing a suite of gRPC components. That will maybe will work with the 4 types of request/response setups: unary RPCs, Server streaming RPCs, Client streaming RPCs and Bidirectional streaming RPCs.


func registerGRPCInput() error {
spec := service.NewConfigSpec().
Version("1.6.0").
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Version("1.6.0").
Version("1.11.0").


func registerGRPCOutput() error {
spec := service.NewConfigSpec().
Version("1.6.0").
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Version("1.6.0").
Version("1.11.0").

Comment on lines +130 to +131
@GOBIN=$(GOPATH_BIN) $(GO) install google.golang.org/protobuf/cmd/protoc-gen-go@latest
@GOBIN=$(GOPATH_BIN) $(GO) install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think we should pin these deps rather than using the latest tag

Comment on lines +66 to +67
tlsCfg := &tls.Config{MinVersion: tls.VersionTLS12}
b.opts = append(b.opts, grpc.WithTransportCredentials(credentials.NewTLS(tlsCfg)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole tls setup is really confusing - seems like we use tlsConf, tlsEnabled, _ := conf.FieldTLSToggled("tls") in the constructor but then here we are just replacing the tlsConf with &tls.Config{MinVersion: tls.VersionTLS12}.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that it would be better if we altered the PR such that we have input_grpc_client.go & output_grpc_client.go files that:

  • register the component in init()
  • define the component spec & constructor

So effectively removing the internal/impl/grpc/init.go & internal/impl/grpc/register.go. It's just the way the vast majority of plugins are implemented - not that this way is flawed.

`,
)

return service.RegisterOutput("grpc", spec, func(conf *service.ParsedConfig, res *service.Resources) (service.Output, int, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return service.RegisterOutput("grpc", spec, func(conf *service.ParsedConfig, res *service.Resources) (service.Output, int, error) {
return service.RegisterOutput("grpc_client", spec, func(conf *service.ParsedConfig, res *service.Resources) (service.Output, int, error) {

auth authConfig
}

func buildDialOptions(_ context.Context, useTLS bool, cfg clientOpts) ([]grpc.DialOption, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come we have a ctx in the call signature if we aren't using it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we need this builder pattern - can't we just create a []grpc.DialOption in the constructor?

Comment on lines +184 to +185
_ = ctx
time.Sleep(5 * time.Millisecond)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would need to properly handle context termination, and tidy up any created resources properly.

Categories("Services").
Summary("Receive messages from a gRPC server-side stream using a simple proto contract.").
Description("Subscribes to a server-side stream and emits each received frame as a message. Message body is taken from Frame.data and metadata from Frame.metadata. Supports TLS, bearer token auth, custom per-RPC headers, keepalive parameters, and client options such as authority, user agent, and load balancing policy.").
Field(service.NewStringField("address").Description("Server address to connect to, e.g. host:port").Default("127.0.0.1:50051")).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would need to add descriptions to the fields, and more description for the components themselves ideally. Would want to talk about the Frame schema etc...

@akoserwal
Copy link
Author

@jem-davies I have a separate implementation on the way, I will have a pr open for it. I would suggest wait until I have new Pr open with changes.

@jem-davies
Copy link
Collaborator

@jem-davies I have a separate implementation on the way, I will have a pr open for it. I would suggest wait until I have new Pr open with changes.

Ok - going to mark this PR as draft

@jem-davies jem-davies marked this pull request as draft August 27, 2025 12:26
@jem-davies jem-davies removed their assignment Aug 27, 2025
@jem-davies
Copy link
Collaborator

jem-davies commented Sep 3, 2025

Closed for #458

@jem-davies jem-davies closed this Sep 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a gRPC plugin in go

2 participants