Class: THTP::MiddlewareStack

Inherits:
Object
  • Object
show all
Defined in:
lib/thtp/middleware_stack.rb

Overview

An implementation of the middleware pattern (a la Rack) for RPC handling. Extracts RPCs from a Thrift service and passes requests to a handler via a middleware stack. Note, NOT threadsafe – mount all desired middlewares before calling.

Instance Method Summary collapse

Constructor Details

#initialize(thrift_service, handlers) ⇒ MiddlewareStack

Returns a new instance of MiddlewareStack.

Parameters:

  • thrift_service (Class)

    The Thrift service from which to extract RPCs

  • handlers (Object, Array<Object>)

    An object or objects responding to each defined RPC; if multiple respond, the first will be used



12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/thtp/middleware_stack.rb', line 12

def initialize(thrift_service, handlers)
  # initialise middleware stack as empty with a generic dispatcher at the bottom
  @stack = []
  @dispatcher = ->(rpc, *rpc_args, **_rpc_opts) do
    handler = Array(handlers).find { |h| h.respond_to?(rpc) }
    raise NoMethodError, "No handler for rpc #{rpc}" unless handler
    handler.public_send(rpc, *rpc_args) # opts are for middleware use only
  end
  # define instance methods for each RPC
  Utils.extract_rpcs(thrift_service).each do |rpc|
    define_singleton_method(rpc) { |*rpc_args_and_opts| call(rpc, *rpc_args_and_opts) }
  end
end

Instance Method Details

#call(rpc, *rpc_args, **rpc_opts) ⇒ Object

Freezes and execute the middleware stack culminating in the RPC itself



42
43
44
# File 'lib/thtp/middleware_stack.rb', line 42

def call(rpc, *rpc_args, **rpc_opts)
  compose.call(rpc, *rpc_args, **rpc_opts)
end

#use(middleware_class, *middleware_args) ⇒ Object

Nests a middleware at the bottom of the stack (closest to the function call). A middleware is any class implementing #call and calling app.call in turn., i.e.,

class PassthroughMiddleware
  def initialize(app, *opts)
    @app = app
  end
  def call(rpc, *rpc_args, **rpc_opts)
    @app.call(rpc, *rpc_args, **rpc_opts)
  end
end


37
38
39
# File 'lib/thtp/middleware_stack.rb', line 37

def use(middleware_class, *middleware_args)
  @stack << [middleware_class, middleware_args]
end