class Yoda::Server::RootHandler
Constants
- NOT_INITIALIZED
- NotImplementedMethod
Attributes
future_map[R]
@return [Concurrent::Map{ String => Future }]
thread_pool[R]
@return [Concurrent::ThreadPoolExecutor]
writer[R]
@return [ConcurrentWriter]
Public Class Methods
default_thread_pool()
click to toggle source
@return [Concurrent::ThreadPoolExecutor]
# File lib/yoda/server/root_handler.rb, line 20 def self.default_thread_pool Concurrent.global_fast_executor end
new(writer:, thread_pool: nil)
click to toggle source
@param writer [ConcurrentWriter] @param thread_pool
[Concurrent::ThreadPoolExecutor]
# File lib/yoda/server/root_handler.rb, line 26 def initialize(writer:, thread_pool: nil) @thread_pool = thread_pool || self.class.default_thread_pool @writer = writer @future_map = Concurrent::Map.new end
Public Instance Methods
cancel_all_requests()
click to toggle source
# File lib/yoda/server/root_handler.rb, line 60 def cancel_all_requests future_map.each_value { |future| future&.cancel } end
cancel_request(id)
click to toggle source
@param id [String]
# File lib/yoda/server/root_handler.rb, line 56 def cancel_request(id) future_map[id]&.cancel end
handle(id:, method:, params:)
click to toggle source
@param id [String] @param method [Symbol] @param params [Hash] @return [Concurrent::Future, nil]
# File lib/yoda/server/root_handler.rb, line 36 def handle(id:, method:, params:) if lifecycle_handler.handle?(method) return write_response(id, lifecycle_handler.handle(method: method, params: params)) end return write_response(id, build_error_response(NOT_INITIALIZED)) unless session if provider = Providers.build_provider(notifier: notifier, session: session, method: method) provide_async(provider: provider, id: id, method: method, params: params) else write_response(id, build_error_response(NotImplementedMethod.new(method))) end end
notifier()
click to toggle source
@return [Notifier]
# File lib/yoda/server/root_handler.rb, line 51 def notifier @notifier ||= Notifier.new(writer) end
Private Instance Methods
build_error_response(reason)
click to toggle source
@param reason [Exception, Symbol, Struct]
# File lib/yoda/server/root_handler.rb, line 108 def build_error_response(reason) case reason when Concurrent::CancelledOperationError LanguageServer::Protocol::Interface::ResponseError.new( code: LanguageServer::Protocol::Constant::ErrorCodes::REQUEST_CANCELLED, message: 'Request is canceled', ) when NOT_INITIALIZED LanguageServer::Protocol::Interface::ResponseError.new( code: LanguageServer::Protocol::Constant::ErrorCodes::SERVER_NOT_INITIALIZED, message: "Server is not initialized", ) when NotImplementedMethod LanguageServer::Protocol::Interface::ResponseError.new( code: LanguageServer::Protocol::Constant::ErrorCodes::METHOD_NOT_FOUND, message: "Method (#{reason.method_name}) is not implemented", ) else LanguageServer::Protocol::Interface::ResponseError.new( code: LanguageServer::Protocol::Constant::ErrorCodes::INTERNAL_ERROR, message: reason.respond_to?(:message) ? message : 'Internal error', ) end end
lifecycle_handler()
click to toggle source
@return [LifecycleHandler]
# File lib/yoda/server/root_handler.rb, line 70 def lifecycle_handler @lifecycle_handler ||= LifecycleHandler.new(self) end
provide_async(provider:, id:, method:, params:)
click to toggle source
@return [Concurrent::Future]
# File lib/yoda/server/root_handler.rb, line 75 def provide_async(provider:, id:, method:, params:) future = Concurrent::Future.new(executor: thread_pool) do notifier.busy(type: method, id: id) { provider.provide(params) } end future.add_observer do |_time, value, reason| begin reason ? write_response(id, build_error_response(reason)) : write_response(id, value) ensure future_map.delete(id) end end future_map.put_if_absent(id, future) Concurrent::ScheduledTask.execute(provider.timeout, executor: thread_pool) { future.cancel } if provider.timeout future.execute future end
write_response(id, result)
click to toggle source
@param id [Object] @param result [Object] @return [nil]
# File lib/yoda/server/root_handler.rb, line 96 def write_response(id, result) return if result == NO_RESPONSE if result.is_a?(LanguageServer::Protocol::Interface::ResponseError) writer.write(id: id, error: result) else writer.write(id: id, result: result) end nil end