Skip to content

[ruby] module path names seems to be broken in >= v1.30.2 #23672

@rahul342

Description

@rahul342

What version of gRPC and what language are you using?

grpc_tools_ruby_protoc 1.30.2

What operating system (Linux, Windows,...) and version?

macOS 10.15.5
(Saw a similar issue in docker circleci/golang:1.13 image)

What runtime / compiler are you using (e.g. python version or version of gcc)

Ruby 2.7.1 (also tried in 2.6.6)

What did you do?

For v1.30.2 and newer, with the following tmp.proto file.

syntax = "proto3";

package task_planner;

service TaskPlanner {
  rpc Health(HealthRequest) returns (Status);
}

// Requests/Response
message Status {
  string msg = 1;
}

message HealthRequest {}

I ran grpc_tools_ruby_protoc -I . --ruby_out=tmp1 --grpc_out=tmp1 tmp.proto

This generates -
Filename: tmp_pb.rb

# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: tmp.proto

require 'google/protobuf'

Google::Protobuf::DescriptorPool.generated_pool.build do
  add_file("tmp.proto", :syntax => :proto3) do
    add_message "task_planner.Status" do
      optional :msg, :string, 1
    end
    add_message "task_planner.HealthRequest" do
    end
  end
end

module TaskPlanner
  Status = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("task_planner.Status").msgclass
  HealthRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("task_planner.HealthRequest").msgclass
end

and
Filename: tmp_services_pb.rb

# Generated by the protocol buffer compiler.  DO NOT EDIT!
# Source: tmp.proto for package 'task_planner'

require 'grpc'
require 'tmp_pb'

module TaskPlanner
  module TaskPlanner
    class Service

      include GRPC::GenericService

      self.marshal_class_method = :encode
      self.unmarshal_class_method = :decode
      self.service_name = 'task_planner.TaskPlanner'

      rpc :Health, TaskPlanner::HealthRequest, TaskPlanner::Status
    end

    Stub = Service.rpc_stub_class
  end
end

I then tried to load the generated service file in a shell.
In my local tmp1 folder where the generated files are -

$ irb
irb(main):001:0> $LOAD_PATH << Dir.pwd
irb(main):002:0> require 'tmp_services_pb'

What did you expect to see?

File to be successfully loaded

What did you see instead?

It generates NameError (uninitialized constant TaskPlanner::TaskPlanner::HealthRequest), which makes sense because the service file is not using absolute paths like ::TaskPlanner::HealthRequest, hence it end up looking in the parent module.

Full trace

Traceback (most recent call last):
       10: from /Users/rahulagrawal/.rbenv/versions/2.6.6/bin/irb:23:in `<main>'
        9: from /Users/rahulagrawal/.rbenv/versions/2.6.6/bin/irb:23:in `load'
        8: from /Users/rahulagrawal/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
        7: from (irb):2
        6: from /Users/rahulagrawal/.rbenv/versions/2.6.6/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        5: from /Users/rahulagrawal/.rbenv/versions/2.6.6/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        4: from /Users/rahulagrawal/Code/protobuf_definitions/tmp1/tmp_services_pb.rb:7:in `<top (required)>'
        3: from /Users/rahulagrawal/Code/protobuf_definitions/tmp1/tmp_services_pb.rb:8:in `<module:TaskPlanner>'
        2: from /Users/rahulagrawal/Code/protobuf_definitions/tmp1/tmp_services_pb.rb:9:in `<module:TaskPlanner>'
        1: from /Users/rahulagrawal/Code/protobuf_definitions/tmp1/tmp_services_pb.rb:17:in `<class:Service>'
NameError (uninitialized constant TaskPlanner::TaskPlanner::HealthRequest)

Anything else we should know about your project / environment?

If I ran the same grpc_tools_ruby_protoc command with grpc-tools v1.30.1
I get the follow service file, which uses relative module name and loads fine.

# Generated by the protocol buffer compiler.  DO NOT EDIT!
# Source: tmp.proto for package 'task_planner'

require 'grpc'
require 'tmp_pb'

module TaskPlanner
  module TaskPlanner
    class Service

      include GRPC::GenericService

      self.marshal_class_method = :encode
      self.unmarshal_class_method = :decode
      self.service_name = 'task_planner.TaskPlanner'

      rpc :Health, HealthRequest, Status
    end

    Stub = Service.rpc_stub_class
  end
end

In shell sames steps

irb(main):001:0> $LOAD_PATH << Dir.pwd
irb(main):002:0> require 'tmp_services_pb'
=> true

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions