grpc_kit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,110 @@
1
+ // Copyright 2015 gRPC authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ syntax = "proto3";
16
+
17
+ option java_multiple_files = true;
18
+ option java_package = "io.grpc.examples.routeguide";
19
+ option java_outer_classname = "RouteGuideProto";
20
+
21
+ package routeguide;
22
+
23
+ // Interface exported by the server.
24
+ service RouteGuide {
25
+ // A simple RPC.
26
+ //
27
+ // Obtains the feature at a given position.
28
+ //
29
+ // A feature with an empty name is returned if there's no feature at the given
30
+ // position.
31
+ rpc GetFeature(Point) returns (Feature) {}
32
+
33
+ // A server-to-client streaming RPC.
34
+ //
35
+ // Obtains the Features available within the given Rectangle. Results are
36
+ // streamed rather than returned at once (e.g. in a response message with a
37
+ // repeated field), as the rectangle may cover a large area and contain a
38
+ // huge number of features.
39
+ rpc ListFeatures(Rectangle) returns (stream Feature) {}
40
+
41
+ // A client-to-server streaming RPC.
42
+ //
43
+ // Accepts a stream of Points on a route being traversed, returning a
44
+ // RouteSummary when traversal is completed.
45
+ rpc RecordRoute(stream Point) returns (RouteSummary) {}
46
+
47
+ // A Bidirectional streaming RPC.
48
+ //
49
+ // Accepts a stream of RouteNotes sent while a route is being traversed,
50
+ // while receiving other RouteNotes (e.g. from other users).
51
+ rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
52
+ }
53
+
54
+ // Points are represented as latitude-longitude pairs in the E7 representation
55
+ // (degrees multiplied by 10**7 and rounded to the nearest integer).
56
+ // Latitudes should be in the range +/- 90 degrees and longitude should be in
57
+ // the range +/- 180 degrees (inclusive).
58
+ message Point {
59
+ int32 latitude = 1;
60
+ int32 longitude = 2;
61
+ }
62
+
63
+ // A latitude-longitude rectangle, represented as two diagonally opposite
64
+ // points "lo" and "hi".
65
+ message Rectangle {
66
+ // One corner of the rectangle.
67
+ Point lo = 1;
68
+
69
+ // The other corner of the rectangle.
70
+ Point hi = 2;
71
+ }
72
+
73
+ // A feature names something at a given point.
74
+ //
75
+ // If a feature could not be named, the name is empty.
76
+ message Feature {
77
+ // The name of the feature.
78
+ string name = 1;
79
+
80
+ // The point where the feature is detected.
81
+ Point location = 2;
82
+ }
83
+
84
+ // A RouteNote is a message sent while at a given point.
85
+ message RouteNote {
86
+ // The location from which the message is sent.
87
+ Point location = 1;
88
+
89
+ // The message to be sent.
90
+ string message = 2;
91
+ }
92
+
93
+ // A RouteSummary is received in response to a RecordRoute rpc.
94
+ //
95
+ // It contains the number of individual points received, the number of
96
+ // detected features, and the total distance covered as the cumulative sum of
97
+ // the distance between each point.
98
+ message RouteSummary {
99
+ // The number of points received.
100
+ int32 point_count = 1;
101
+
102
+ // The number of known features passed while traversing the route.
103
+ int32 feature_count = 2;
104
+
105
+ // The distance covered in metres.
106
+ int32 distance = 3;
107
+
108
+ // The duration of the traversal in seconds.
109
+ int32 elapsed_time = 4;
110
+ }
@@ -0,0 +1,37 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: routeguide.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message "routeguide.Point" do
8
+ optional :latitude, :int32, 1
9
+ optional :longitude, :int32, 2
10
+ end
11
+ add_message "routeguide.Rectangle" do
12
+ optional :lo, :message, 1, "routeguide.Point"
13
+ optional :hi, :message, 2, "routeguide.Point"
14
+ end
15
+ add_message "routeguide.Feature" do
16
+ optional :name, :string, 1
17
+ optional :location, :message, 2, "routeguide.Point"
18
+ end
19
+ add_message "routeguide.RouteNote" do
20
+ optional :location, :message, 1, "routeguide.Point"
21
+ optional :message, :string, 2
22
+ end
23
+ add_message "routeguide.RouteSummary" do
24
+ optional :point_count, :int32, 1
25
+ optional :feature_count, :int32, 2
26
+ optional :distance, :int32, 3
27
+ optional :elapsed_time, :int32, 4
28
+ end
29
+ end
30
+
31
+ module Routeguide
32
+ Point = Google::Protobuf::DescriptorPool.generated_pool.lookup("routeguide.Point").msgclass
33
+ Rectangle = Google::Protobuf::DescriptorPool.generated_pool.lookup("routeguide.Rectangle").msgclass
34
+ Feature = Google::Protobuf::DescriptorPool.generated_pool.lookup("routeguide.Feature").msgclass
35
+ RouteNote = Google::Protobuf::DescriptorPool.generated_pool.lookup("routeguide.RouteNote").msgclass
36
+ RouteSummary = Google::Protobuf::DescriptorPool.generated_pool.lookup("routeguide.RouteSummary").msgclass
37
+ end
@@ -0,0 +1,61 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: routeguide.proto for package 'routeguide'
3
+ # Original file comments:
4
+ # Copyright 2015 gRPC authors.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'grpc'
20
+ require 'routeguide_pb'
21
+
22
+ module Routeguide
23
+ module RouteGuide
24
+ # Interface exported by the server.
25
+ class Service
26
+
27
+ include GRPC::GenericService
28
+
29
+ self.marshal_class_method = :encode
30
+ self.unmarshal_class_method = :decode
31
+ self.service_name = 'routeguide.RouteGuide'
32
+
33
+ # A simple RPC.
34
+ #
35
+ # Obtains the feature at a given position.
36
+ #
37
+ # A feature with an empty name is returned if there's no feature at the given
38
+ # position.
39
+ rpc :GetFeature, Point, Feature
40
+ # A server-to-client streaming RPC.
41
+ #
42
+ # Obtains the Features available within the given Rectangle. Results are
43
+ # streamed rather than returned at once (e.g. in a response message with a
44
+ # repeated field), as the rectangle may cover a large area and contain a
45
+ # huge number of features.
46
+ rpc :ListFeatures, Rectangle, stream(Feature)
47
+ # A client-to-server streaming RPC.
48
+ #
49
+ # Accepts a stream of Points on a route being traversed, returning a
50
+ # RouteSummary when traversal is completed.
51
+ rpc :RecordRoute, stream(Point), RouteSummary
52
+ # A Bidirectional streaming RPC.
53
+ #
54
+ # Accepts a stream of RouteNotes sent while a route is being traversed,
55
+ # while receiving other RouteNotes (e.g. from other users).
56
+ rpc :RouteChat, stream(RouteNote), stream(RouteNote)
57
+ end
58
+
59
+ Stub = Service.rpc_stub_class
60
+ end
61
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path('./examples/routeguide')
4
+
5
+ require 'grpc_kit'
6
+ require 'pry'
7
+ require 'routeguide_services_pb'
8
+
9
+ stub = Routeguide::RouteGuide::Stub.new('localhost', 50051)
10
+
11
+ def get_feature(stub)
12
+ points = [
13
+ Routeguide::Point.new(latitude: 409_146_138, longitude: -746_188_906),
14
+ Routeguide::Point.new(latitude: 0, longitude: 0)
15
+ ]
16
+
17
+ points.each do |pt|
18
+ feature = stub.get_feature(pt)
19
+ puts "get_feature #{feature.name}, #{feature.location}"
20
+ end
21
+ end
22
+
23
+ get_feature(stub)
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path('./examples/routeguide')
4
+
5
+ require 'grpc_kit'
6
+ require 'pry'
7
+ require 'json'
8
+ require 'routeguide_services_pb'
9
+
10
+ class Server < Routeguide::RouteGuide::Service
11
+ RESOURCE_PATH = './examples/routeguide/routeguide.json'
12
+
13
+ def initialize
14
+ File.open(RESOURCE_PATH) do |f|
15
+ features = JSON.load(f.read)
16
+ @features = Hash[features.map { |x| [x['location'], x['name']] }]
17
+ end
18
+ end
19
+
20
+ def get_feature(point, _call)
21
+ name = @features.fetch({ 'longitude' => point.longitude, 'latitude' => point.latitude }, '')
22
+ Routeguide::Feature.new(location: point, name: name)
23
+ end
24
+ end
25
+
26
+ sock = TCPServer.new(50051)
27
+
28
+ server = GrpcKit::Server.new
29
+ server.handle(Server.new)
30
+ server.run
31
+
32
+ loop do
33
+ conn = sock.accept
34
+ server.session_start(conn)
35
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'grpc_kit/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'grpc_kit'
9
+ spec.version = GrpcKit::VERSION
10
+ spec.authors = ['ganmacs']
11
+ spec.email = ['ganmacs@gmail.com']
12
+
13
+ spec.summary = 'A kit for creating gRPC server/client'
14
+ spec.description = 'A kit for creating gRPC server/client'
15
+ spec.homepage = 'https://github.com/ganmacs/grpc_kit'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+ spec.bindir = 'exe'
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.add_dependency 'ds9', '~> 1.1.1'
26
+ spec.add_dependency 'google-protobuf', '~> 3.6.1'
27
+ spec.add_dependency 'googleapis-common-protos-types', '~> 1.0.2'
28
+
29
+ spec.add_development_dependency 'bundler'
30
+ spec.add_development_dependency 'grpc-tools'
31
+ spec.add_development_dependency 'pry-byebug'
32
+ spec.add_development_dependency 'rake'
33
+ spec.add_development_dependency 'rspec'
34
+ spec.add_development_dependency 'rubocop'
35
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Compat file for xx_services_pb.rb
4
+ require 'grpc_kit'
5
+ require 'grpc_kit/grpc/generic_service'
6
+
7
+ GRPC = GrpcKit::GRPC
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ require 'grpc_kit/version'
6
+ require 'grpc_kit/server'
7
+ require 'grpc_kit/client'
8
+
9
+ module GrpcKit
10
+ def self.logger
11
+ @logger ||= Logger.new(STDOUT, level: :debug) # TODO: use :info level
12
+ end
13
+
14
+ def self.logger=(logger)
15
+ @logger = logger
16
+ end
17
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'socket'
4
+ require 'grpc_kit/session/client'
5
+
6
+ module GrpcKit
7
+ class Client
8
+ def initialize(host, port, io = GrpcKit::IO::Basic)
9
+ @host = host
10
+ @port = port
11
+ @authority = "#{host}:#{port}"
12
+ @io = io
13
+ end
14
+
15
+ # @params handler [object]
16
+ def handle(handler)
17
+ klass = handler.class
18
+
19
+ klass.rpc_descs.values.each do |rpc_desc|
20
+ path = rpc_desc.path(klass.service_name)
21
+ if @rpc_descs[path]
22
+ raise "Duplicated method registered #{key}, class: #{handler}"
23
+ end
24
+
25
+ @rpc_descs[path] = [rpc_desc, handler]
26
+ end
27
+ end
28
+
29
+ class RequestResponse
30
+ attr_writer :session
31
+
32
+ def initialize(path, opts = {})
33
+ @path = path
34
+ @opts = opts
35
+ @session = nil
36
+ @data = ''
37
+ end
38
+
39
+ def invoke(data)
40
+ @session.submit_settings([])
41
+
42
+ stream_id = submit_request(data)
43
+ @session.start(stream_id)
44
+ @data
45
+ end
46
+
47
+ def on_data_chunk_recv(stream, data)
48
+ compressed, length, buf = data.unpack('CNa*')
49
+ if compressed == 0 # TODO: not
50
+ if length != buf.size
51
+ raise 'recived data inconsistent'
52
+ end
53
+
54
+ @data << buf
55
+ stream.recv2(buf)
56
+ else
57
+ raise 'not supported'
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def submit_request(data)
64
+ @session.submit_request(
65
+ {
66
+ ':method' => 'POST',
67
+ ':scheme' => 'http',
68
+ ':authority' => @opts[:authority],
69
+ ':path' => @path.to_s,
70
+ 'te' => 'trailers',
71
+ 'content-type' => 'application/grpc',
72
+ 'user-agent' => "grpc-ruby/#{GrpcKit::VERSION} (grpc_kit)",
73
+ 'grpc-accept-encoding' => 'identity,deflate,gzip',
74
+ },
75
+ data,
76
+ )
77
+ end
78
+ end
79
+
80
+ def request_response(path, request, rpc_desc, opts = {})
81
+ GrpcKit.logger.info('Calling request_respose')
82
+ sock = TCPSocket.new(@host, @port)
83
+
84
+ rr = RequestResponse.new(path, { authority: @authority }.merge(opts))
85
+ session = GrpcKit::Session::Client.new(@io.new(sock, sock), rr)
86
+ rr.session = session
87
+
88
+ req = rpc_desc.encode2(request)
89
+ data = [0, req.length, req].pack('CNa*')
90
+
91
+ resp = rr.invoke(data)
92
+ rpc_desc.decode2(resp)
93
+ end
94
+
95
+ def client_streamer(path, requests, rpc, opts = {})
96
+ GrpcKit.logger.info('Calling client_streamer')
97
+ end
98
+
99
+ def server_streamer(path, request, metadata, opts = {})
100
+ GrpcKit.logger.info('Calling server_streamer')
101
+ end
102
+
103
+ def bidi_streamer(path, requests, metadata, opts = {})
104
+ GrpcKit.logger.info('Calling bidi_streamer')
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grpc_kit/status_codes'
4
+
5
+ module GrpcKit
6
+ module Errors
7
+ # https://github.com/grpc/grpc/blob/23b5b1a5a9c7084c5b64d4998ee15af0f77bd589/doc/statuscodes.md
8
+ class BadStatus < StandardError
9
+ def initialize(code, message)
10
+ super("#{code}:#{details}")
11
+ @code = code
12
+ @message = message
13
+ end
14
+
15
+ class Unimplemented < BadStatus
16
+ def initialize(name)
17
+ super(
18
+ GrpcKit::StatusCodes::UNIMPLEMENTED,
19
+ "Method not found at server: #{name}"
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end