class Gruf::Server
Represents a gRPC server. Automatically loads and augments gRPC handlers and services based on configuration values.
Attributes
@return [Hash] Hash of options passed into the server
@return [Integer] The port the server is bound to
Public Class Methods
Initialize the server and load and setup the services
@param [Hash] opts
# File lib/gruf/server.rb, line 38 def initialize(opts = {}) @options = opts || {} @interceptors = opts.fetch(:interceptor_registry, Gruf.interceptors) @interceptors = Gruf::Interceptors::Registry.new unless @interceptors.is_a?(Gruf::Interceptors::Registry) @services = [] @started = false @stop_server = false @stop_server_cv = ConditionVariable.new @stop_server_mu = Monitor.new @server_mu = Monitor.new @hostname = opts.fetch(:hostname, Gruf.server_binding_url) @event_listener_proc = opts.fetch(:event_listener_proc, Gruf.event_listener_proc) setup end
Public Instance Methods
Add an interceptor to the server
@param [Class] klass The Interceptor to add to the registry @param [Hash] opts A hash of options for the interceptor @raise [ServerAlreadyStartedError] if the server is already started
# File lib/gruf/server.rb, line 137 def add_interceptor(klass, opts = {}) raise ServerAlreadyStartedError if @started @interceptors.use(klass, opts) end
Add a gRPC service stub to be served by gruf
@param [Class] klass @raise [ServerAlreadyStartedError] if the server is already started
# File lib/gruf/server.rb, line 124 def add_service(klass) raise ServerAlreadyStartedError if @started @services << klass unless @services.include?(klass) end
Clear the interceptor registry of interceptors
# File lib/gruf/server.rb, line 192 def clear_interceptors raise ServerAlreadyStartedError if @started @interceptors.clear end
Insert an interceptor after another in the currently registered order of execution
@param [Class] after_class The interceptor that you want to add the new interceptor after @param [Class] interceptor_class The Interceptor to add to the registry @param [Hash] opts A hash of options for the interceptor
# File lib/gruf/server.rb, line 163 def insert_interceptor_after(after_class, interceptor_class, opts = {}) raise ServerAlreadyStartedError if @started @interceptors.insert_after(after_class, interceptor_class, opts) end
Insert an interceptor before another in the currently registered order of execution
@param [Class] before_class The interceptor that you want to add the new interceptor before @param [Class] interceptor_class The Interceptor to add to the registry @param [Hash] opts A hash of options for the interceptor
# File lib/gruf/server.rb, line 150 def insert_interceptor_before(before_class, interceptor_class, opts = {}) raise ServerAlreadyStartedError if @started @interceptors.insert_before(before_class, interceptor_class, opts) end
Return the current list of added interceptor classes
@return [Array<Class>]
# File lib/gruf/server.rb, line 174 def list_interceptors @interceptors.list end
Remove an interceptor from the server
@param [Class] klass
# File lib/gruf/server.rb, line 183 def remove_interceptor(klass) raise ServerAlreadyStartedError if @started @interceptors.remove(klass) end
@return [GRPC::RpcServer] The GRPC
server running
# File lib/gruf/server.rb, line 56 def server @server_mu.synchronize do @server ||= begin # For backward compatibility, we allow these options to be passed directly # in the Gruf::Server options, or via Gruf.rpc_server_options. server_options = { pool_size: options.fetch(:pool_size, Gruf.rpc_server_options[:pool_size]), max_waiting_requests: options.fetch(:max_waiting_requests, Gruf.rpc_server_options[:max_waiting_requests]), poll_period: options.fetch(:poll_period, Gruf.rpc_server_options[:poll_period]), pool_keep_alive: options.fetch(:pool_keep_alive, Gruf.rpc_server_options[:pool_keep_alive]), connect_md_proc: options.fetch(:connect_md_proc, Gruf.rpc_server_options[:connect_md_proc]), server_args: options.fetch(:server_args, Gruf.rpc_server_options[:server_args]) } server = if @event_listener_proc server_options[:event_listener_proc] = @event_listener_proc Gruf::InstrumentableGrpcServer.new(**server_options) else GRPC::RpcServer.new(**server_options) end @port = server.add_http2_port(@hostname, ssl_credentials) @services.each { |s| server.handle(s) } server end end end
Start the gRPC server
:nocov:
# File lib/gruf/server.rb, line 88 def start! update_proc_title(:starting) server_thread = Thread.new do logger.info { "Starting gruf server at #{@hostname}..." } server.run end stop_server_thread = Thread.new do loop do break if @stop_server @stop_server_mu.synchronize { @stop_server_cv.wait(@stop_server_mu, 10) } end logger.info { 'Shutting down...' } server.stop end server.wait_till_running @started = true update_proc_title(:serving) stop_server_thread.join server_thread.join @started = false update_proc_title(:stopped) logger.info { 'Goodbye!' } end
Private Instance Methods
@param [String]
# File lib/gruf/server.rb, line 248 def controllers_path options.fetch(:controllers_path, Gruf.controllers_path) end
Auto-load all gRPC handlers
:nocov:
# File lib/gruf/server.rb, line 231 def load_controllers return unless File.directory?(controllers_path) path = File.realpath(controllers_path) $LOAD_PATH.unshift(path) Dir["#{path}/**/*.rb"].each do |f| next if f.include?('_pb') # exclude if people include proto generated files in app/rpc logger.info "- Loading gRPC service file: #{f}" load File.realpath(f) end end
Setup server
:nocov:
# File lib/gruf/server.rb, line 204 def setup setup_signal_handlers load_controllers end
Register signal handlers
:nocov:
# File lib/gruf/server.rb, line 214 def setup_signal_handlers Signal.trap('INT') do @stop_server = true @stop_server_cv.broadcast end Signal.trap('TERM') do @stop_server = true @stop_server_cv.broadcast end end
Load the SSL/TLS credentials for this server
@return [GRPC::Core::ServerCredentials|Symbol]
:nocov:
# File lib/gruf/server.rb, line 258 def ssl_credentials return :this_port_is_insecure unless options.fetch(:use_ssl, Gruf.use_ssl) private_key = File.read(options.fetch(:ssl_key_file, Gruf.ssl_key_file)) cert_chain = File.read(options.fetch(:ssl_crt_file, Gruf.ssl_crt_file)) certs = [nil, [{ private_key: private_key, cert_chain: cert_chain }], false] GRPC::Core::ServerCredentials.new(*certs) end
Updates proc name/title
@param [Symbol] state
:nocov:
# File lib/gruf/server.rb, line 274 def update_proc_title(state) Process.setproctitle("gruf #{Gruf::VERSION} -- #{state}") end