ampedxx-yrpc 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,79 @@
1
+ module Yrpc
2
+ class Client < SimpleDelegator
3
+
4
+ def initialize(service:, options: {}, client_options: {})
5
+ @base_klass = service
6
+ @service_klass = "#{base_klass}::Service".constantize
7
+ @opts = options || {}
8
+ @opts[:password] = options.fetch(:password, '').to_s
9
+ @opts[:hostname] = options.fetch(:hostname, Yrpc.default_client_host)
10
+ client = "#{service}::Stub".constantize.new(@opts[:hostname], build_ssl_credentials, interceptors: [*client_options[:interceptors]])
11
+ super(client)
12
+ end
13
+
14
+ attr_reader :service_klass
15
+ attr_reader :base_klass
16
+ attr_reader :opts
17
+
18
+ def invoke(request_method, params = {}, metadata={}, opts={}, &block)
19
+ request_method = request_method.to_sym
20
+ req = streaming_request?(request_method) ? params : request_object(request_method, params)
21
+ md = build_metadata(metadata)
22
+ call_sig = call_signature(request_method)
23
+ raise NotImplementedError, "The method #{request_method} has not been implemented in this service." unless call_sig
24
+ resp = execute(call_sig, req, md, opts, &block)
25
+ p resp
26
+ Response.new(resp)
27
+ end
28
+
29
+ def build_metadata(metadata = {})
30
+ unless opts[:password].empty?
31
+ username = opts.fetch(:username, 'grpc').to_s
32
+ username = username.empty? ? '' : "#{username}:"
33
+ auth_string = Base64.encode64("#{username}#{opts[:password]}")
34
+ metadata[:authorization] = "Basic #{auth_string}".tr("\n", '')
35
+ end
36
+ metadata
37
+ end
38
+
39
+ def execute(call_sig, req, metadata, opts = {}, &block)
40
+ # Timer.time do
41
+ opts[:return_op] = true
42
+ opts[:metadata] = metadata
43
+ # end
44
+ send(call_sig, req, opts, &block)
45
+ end
46
+
47
+ def rpc_desc(request_method)
48
+ service_klass.rpc_descs[request_method]
49
+ end
50
+
51
+ def request_object(request_method, params = {})
52
+ desc = rpc_desc(request_method)
53
+ desc && desc.input ? desc.input.new(params) : nil
54
+ end
55
+
56
+ def call_signature(request_method)
57
+ desc = rpc_desc(request_method)
58
+ desc && desc.name ? desc.name.to_s.underscore.to_sym : nil
59
+ end
60
+
61
+ def build_ssl_credentials
62
+ cert = nil
63
+ if opts[:ssl_certificate_file]
64
+ cert = File.read(opts[:ssl_certificate_file]).to_s.strip
65
+ elsif opts[:ssl_certificate]
66
+ cert = opts[:ssl_certificate].to_s.strip
67
+ end
68
+
69
+ cert ? GRPC::Core::ChannelCredentials.new(cert) : :this_channel_is_insecure
70
+ end
71
+
72
+ def streaming_request?(request_method)
73
+ desc = rpc_desc(request_method)
74
+ desc && (desc.client_streamer? || desc.bidi_streamer?)
75
+ end
76
+
77
+
78
+ end
79
+ end
@@ -0,0 +1,48 @@
1
+ require_relative "interceptors/active_record"
2
+ require 'logger'
3
+ module Yrpc
4
+ module Configuration
5
+ VALID_CONFIG_KEYS = {
6
+ server_binding_url: '0.0.0.0:9001',
7
+ interceptors: nil,
8
+ use_default_interceptors: true,
9
+ default_client_host: '',
10
+ controllers_path: 'app/controllers',
11
+ server_options: {},
12
+ services: [],
13
+ logger:nil,
14
+ use_ssl: false,
15
+ }.freeze
16
+
17
+ attr_accessor *VALID_CONFIG_KEYS.keys
18
+
19
+ def self.extended(base)
20
+ base.reset
21
+ end
22
+
23
+ def configure
24
+ yield self
25
+ end
26
+
27
+ def options
28
+ opts = {}
29
+ VALID_CONFIG_KEYS.each_key do |k|
30
+ opts.merge!(k => send(k))
31
+ end
32
+ opts
33
+ end
34
+
35
+ #重制一些配置
36
+ def reset
37
+ VALID_CONFIG_KEYS.each do |k, v|
38
+ send((k.to_s + '='), v)
39
+ end
40
+ self.logger = ::Logger.new(STDOUT)
41
+ self.interceptors = Yrpc::Interceptors::Registry.new
42
+ if use_default_interceptors
43
+ interceptors.use(Yrpc::Interceptors::ActiveRecord::ResetConnection)
44
+ end
45
+ options
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,47 @@
1
+ module Yrpc
2
+ module Controllers
3
+ class Base
4
+ include ActiveSupport::Callbacks
5
+
6
+ define_callbacks :call
7
+
8
+ attr_reader :request
9
+
10
+
11
+ def initialize(method_key:, service:, rpc_desc:, active_call:, message:)
12
+ @request = Request.new(
13
+ method_key: method_key,
14
+ service: service,
15
+ rpc_desc: rpc_desc,
16
+ active_call: active_call,
17
+ message: message
18
+ )
19
+ end
20
+
21
+ def self.before_action(methods)
22
+ [*methods].each do |method|
23
+ set_callback :call, :before, method
24
+ end
25
+ end
26
+
27
+ def self.after_action(methods)
28
+ [*methods].each do |method|
29
+ set_callback :call, :after, method
30
+ end
31
+ end
32
+
33
+
34
+ def self.bind(service_class)
35
+ Yrpc.services << service_class.name.constantize
36
+ ServiceBinder.new(service_class).bind!(self)
37
+ end
38
+
39
+
40
+ def call(method_key, &block)
41
+ run_callbacks :call do
42
+ send(method_key, &block)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,91 @@
1
+ module Yrpc
2
+ module Controllers
3
+
4
+ class Request
5
+
6
+ attr_reader :message
7
+ # @var [GRPC::ActiveCall] active_call
8
+ attr_reader :active_call
9
+ # @var [Symbol] method_key
10
+ attr_reader :method_key
11
+ # @var [Grpc::Controllers::Request::Type] type
12
+ attr_reader :type
13
+ # @var [Class] service
14
+ attr_reader :service
15
+
16
+ delegate :metadata, to: :active_call
17
+ delegate :messages, :client_streamer?, :server_streamer?, :bidi_streamer?, :request_response?, to: :type
18
+
19
+ ##
20
+ # Abstract representation of a gRPC request type
21
+ #
22
+ class Type
23
+ delegate :client_streamer?, :server_streamer?, :bidi_streamer?, :request_response?, to: :@rpc_desc
24
+
25
+ ##
26
+ # Initialize a new request type object
27
+ #
28
+ # @param [GRPC::RpcDesc] rpc_desc The RPC descriptor for the request type
29
+ #
30
+ def initialize(rpc_desc)
31
+ @rpc_desc = rpc_desc
32
+ end
33
+ end
34
+
35
+ ##
36
+
37
+ #struct GRPC::RpcDesc
38
+ def initialize(method_key:, service:, rpc_desc:, active_call:, message:)
39
+ @method_key = method_key
40
+ @service = service
41
+ @active_call = active_call
42
+ @message = message
43
+ @rpc_desc = rpc_desc
44
+ @type = Type.new(rpc_desc)
45
+ end
46
+
47
+
48
+ def service_key
49
+ @service.name.underscore.tr('/', '.').gsub('.service', '')
50
+ end
51
+
52
+ def method_missing(method_id, *arguments, &block)
53
+ method_message = *arguments.join
54
+ if (method_id.to_s =~ /^raise_[\w]+/) == 0
55
+ error_type = method_id.to_s.split('raise_')[1].upcase!
56
+ code = "Yrpc::Response::Code::#{error_type}".constantize
57
+ message = method_message
58
+ raise Yrpc::Error::ResponseError.new(code, message)
59
+ else
60
+ super
61
+ end
62
+ end
63
+
64
+
65
+ def response_class
66
+ @rpc_desc.output
67
+ end
68
+
69
+
70
+ def request_class
71
+ @rpc_desc.input
72
+ end
73
+
74
+ # grpc 中的 service.method
75
+ def method_name
76
+ "#{service_key}.#{method_key}"
77
+ end
78
+
79
+ # 返回这个request的所有mesage 要根据stremer类型来判断
80
+ def messages
81
+ if client_streamer?
82
+ message.call { |msg| yield msg }
83
+ elsif bidi_streamer?
84
+ message
85
+ else
86
+ [message]
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,104 @@
1
+ module Yrpc
2
+
3
+ class Response
4
+
5
+ module Code
6
+ # 添加模型常量国际化方法
7
+ # include Dictionary::Module::I18n
8
+
9
+ ################################################################################
10
+ #
11
+ # 20000 成功
12
+ #
13
+ ################################################################################
14
+
15
+ SUCCESS = '20000'
16
+
17
+ ################################################################################
18
+ #
19
+ # 3xxxx 数据相关
20
+ #
21
+ ################################################################################
22
+
23
+ # 用户绑定第三方账户
24
+
25
+ # 第三方账户已绑定其它用户
26
+ PROVIDER_BIND_ANOTHER_USER = '30010'
27
+
28
+ ################################################################################
29
+ #
30
+ # 4xxxx 业务相关
31
+ #
32
+ ################################################################################
33
+
34
+ # 非法请求
35
+ INVALID_REQUEST = '40300'
36
+
37
+ # 终端密钥错误
38
+ INVALID_TERMINAL_SESSION_KEY = '40301'
39
+
40
+ # 用户密钥错误
41
+ INVALID_USER_SESSION_KEY = '40302'
42
+
43
+ # 超出请求限制数
44
+ EXCEED_REQUEST_LIMIT = '40303'
45
+
46
+ # 版本号不适配
47
+ NOT_COMPATIBLE_REVISION = '40304'
48
+
49
+ # 访问令牌过期
50
+ ACCESS_TOKEN_EXPIRED = '40305'
51
+
52
+ ################################################################################
53
+ #
54
+ # 5xxxx 系统相关
55
+ #
56
+ ################################################################################
57
+
58
+ # 未知错误(通常在捕捉异常后使用)
59
+ ERROR = '50000'
60
+
61
+ # 请求参数缺失
62
+ # Todo: 移动到数据相关
63
+ MISS_REQUEST_PARAMS = '50001'
64
+
65
+ # 数据处理错误
66
+ # Todo: 移动到数据相关
67
+ DATA_PROCESS_ERROR = '51000'
68
+
69
+ # 数据缺失错误
70
+ # Todo: 移动到数据相关
71
+ DATA_MISS_ERROR = '51001'
72
+
73
+ ORDER_PAYMENT_COMPLETED = '55000'
74
+
75
+ NEED_LOGIN = '40100'
76
+
77
+ ERROR_VALIDATE_CODE = '40200'
78
+
79
+ # 全部
80
+ # ALL = get_all_constants.map { |constant| constant.to_s.downcase }
81
+ end
82
+
83
+
84
+ def initialize(operation, execution_time = nil)
85
+ @operation = operation
86
+ @message = operation.execute
87
+ @metadata = operation.metadata
88
+ @trailing_metadata = operation.trailing_metadata
89
+ @deadline = operation.deadline
90
+ @cancelled = operation.cancelled?
91
+ @execution_time = execution_time || 0.0
92
+ end
93
+
94
+ def message
95
+ @message ||= @operation.execute
96
+ end
97
+
98
+ def status
99
+ @message ||= @operation.execute
100
+ @message&.status
101
+ end
102
+
103
+ end
104
+ end
@@ -0,0 +1,87 @@
1
+ module Yrpc
2
+ module Controllers
3
+
4
+ class ServiceBinder
5
+ ##
6
+ #未来可能会有一些desc 的 拓展,先预留一个肉便器类。
7
+ #
8
+ class BoundDesc < SimpleDelegator;
9
+ end
10
+
11
+ #初始化。。没什么好解释的
12
+ def initialize(service)
13
+ @service = service
14
+ end
15
+
16
+
17
+ # 通过controller绑定所有的方法
18
+ def bind!(controller)
19
+ rpc_methods.each { |name, desc| bind_method(controller, name, desc) }
20
+ end
21
+
22
+ def rpc_desc(request_method)
23
+ @service.rpc_descs[request_method]
24
+ end
25
+
26
+ private
27
+
28
+
29
+ #打开类并且进行一个方法define,返回给这个方法打call。这里要注意的是request 会以参数形式构造进controller
30
+ #这里也涉及到stream 类型。
31
+ def bind_method(controller, method_name, desc)
32
+ method_desc = method_name.to_s.to_sym
33
+ method_key = method_name.to_s.underscore.to_sym
34
+ current_desc = rpc_desc(method_desc)
35
+ service_ref = @service
36
+ @service.class_eval do
37
+ if desc.request_response?
38
+ define_method(method_key) do |message, active_call|
39
+ c = controller.new(method_key: method_key, service: service_ref, message: message, active_call: active_call, rpc_desc: desc)
40
+ begin
41
+ c.call(method_key)
42
+ rescue => e
43
+ p method_key
44
+ p e.backtrace_locations
45
+ desc && desc.output ? desc.output.new(status: {code: e.respond_to?(:code) ? e.code : Yrpc::Response::Code::ERROR , message: e.message}) : (raise e)
46
+ end
47
+ end
48
+ elsif desc.client_streamer?
49
+ define_method(method_key) do |active_call|
50
+ c = controller.new(method_key: method_key, service: service_ref, message: proc { |&block| active_call.each_remote_read(&block) }, active_call: active_call, rpc_desc: desc)
51
+ begin
52
+ c.call(method_key)
53
+ rescue => e
54
+ desc && desc.output ? desc.output.new(status: {code: e&.code || Yrpc::Response::Code::ERROR, message: e.message}) : (raise e)
55
+ end
56
+ end
57
+ elsif desc.server_streamer?
58
+ define_method(method_key) do |message, active_call, &block|
59
+ c = controller.new(method_key: method_key, service: service_ref, message: message, active_call: active_call, rpc_desc: desc)
60
+ begin
61
+ c.call(method_key)
62
+ rescue => e
63
+ desc && desc.output ? desc.output.new(status: {code: e&.code || Yrpc::Response::Code::ERROR , message: e.message}) : (raise e)
64
+ end
65
+ end
66
+ else # bidi
67
+ define_method(method_key) do |messages, active_call, &block|
68
+ c = controller.new(method_key: method_key, service: service_ref, message: messages, active_call: active_call, rpc_desc: desc)
69
+ begin
70
+ c.call(method_key)
71
+ rescue => e
72
+ desc && desc.output ? desc.output.new(status: {code: e&.code || Yrpc::Response::Code::ERROR, message: e.message}) : (raise e)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ ##
80
+ # 讲方法都代理到boundDesc 上
81
+ #
82
+ def rpc_methods
83
+ @service.rpc_descs.map { |rd| BoundDesc.new(rd) }
84
+ end
85
+ end
86
+ end
87
+ end