module Protobuf::Rpc::ServiceFilters::InstanceMethods

Private Instance Methods

call_or_send(callable, *args, &block) click to toggle source

Call the object if it is callable, otherwise invoke the method using __send__ assuming that we respond_to it. Return the call’s return value.

# File lib/protobuf/rpc/service_filters.rb, line 243
def call_or_send(callable, *args, &block)
  return callable.call(self, *args, &block) if callable.respond_to?(:call)
  __send__(callable, *args, &block)
end
filters() click to toggle source

Get back to class filters.

# File lib/protobuf/rpc/service_filters.rb, line 87
def filters
  self.class.filters
end
invoke_filter?(rpc_method, filter) click to toggle source

Predicate which uses the filter options to determine if the filter should be called. Specifically checks the :if, :unless, :only, and :except options for every filter. Each option check is expected to return false if the filter should not be invoked, true if invocation should occur.

# File lib/protobuf/rpc/service_filters.rb, line 96
def invoke_filter?(rpc_method, filter)
  invoke_via_only?(rpc_method, filter) &&
    invoke_via_except?(rpc_method, filter) &&
    invoke_via_if?(rpc_method, filter) &&
    invoke_via_unless?(rpc_method, filter)
end
invoke_via_except?(rpc_method, filter) click to toggle source

If the target rpc endpoint method is listed under an :except option, return false to indicate that the filter should not be invoked. Any other target rpc endpoint methods not listed should be invoked. This option is the opposite of :only.

Value should be a symbol/string or an array of symbols/strings.

# File lib/protobuf/rpc/service_filters.rb, line 110
def invoke_via_except?(rpc_method, filter)
  except = [filter.fetch(:except) { [] }].flatten
  except.empty? || !except.include?(rpc_method)
end
invoke_via_if?(_rpc_method, filter) click to toggle source

Invoke the given :if callable (if any) and return its return value. Used by ‘invoke_filter?` which expects a true/false return value to determine if we should invoke the target filter.

Value can either be a symbol/string indicating an instance method to call or an object that responds to ‘call`.

# File lib/protobuf/rpc/service_filters.rb, line 122
def invoke_via_if?(_rpc_method, filter)
  if_check = filter.fetch(:if, nil)
  return true if if_check.nil?
  call_or_send(if_check)
end
invoke_via_only?(rpc_method, filter) click to toggle source

If the target rpc endpoint method is listed in the :only option, it should be invoked. Any target rpc endpoint methods not listed in this option should not be invoked. This option is the opposite of :except.

Value should be a symbol/string or an array of symbols/strings.

# File lib/protobuf/rpc/service_filters.rb, line 134
def invoke_via_only?(rpc_method, filter)
  only = [filter.fetch(:only) { [] }].flatten
  only.empty? || only.include?(rpc_method)
end
invoke_via_unless?(_rpc_method, filter) click to toggle source

Invoke the given :unless callable (if any) and return the opposite of it’s return value. Used by ‘invoke_filter?` which expects a true/false return value to determine if we should invoke the target filter.

Value can either be a symbol/string indicating an instance method to call or an object that responds to ‘call`.

# File lib/protobuf/rpc/service_filters.rb, line 146
def invoke_via_unless?(_rpc_method, filter)
  unless_check = filter.fetch(:unless, nil)
  return true if unless_check.nil?
  !call_or_send(unless_check)
end
rescue_filters() click to toggle source
# File lib/protobuf/rpc/service_filters.rb, line 152
def rescue_filters
  self.class.rescue_filters
end
run_around_filters(rpc_method) click to toggle source

Reverse build a chain of around filters. To implement an around chain, simply build a method that yields control when it expects the underlying method to be invoked. If the endpoint should not be run (due to some condition), simply do not yield.

Around filters are invoked in the order they are defined, outer to inner, with the inner-most method called being the actual rpc endpoint.

Let’s say you have a class defined with the following filters:

class MyService
  around_filter :filter1, :filter2, :filter3

  def my_endpoint
    # do stuff
  end
end

When the my_endpoint method is invoked using Service#callable_rpc_method, It is similar to this call chain:

filter1 do
  filter2 do
    filter3 do
      my_endpoint
    end
  end
end
# File lib/protobuf/rpc/service_filters.rb, line 199
def run_around_filters(rpc_method)
  final = -> { __send__(rpc_method) }
  filters[:around].reverse.reduce(final) do |previous, filter|
    if invoke_filter?(rpc_method, filter)
      -> { call_or_send(filter[:callable], &previous) }
    else
      previous
    end
  end.call
end
run_filters(rpc_method) click to toggle source

Entry method to call each filter type in the appropriate order. This should be used instead of the other run methods directly.

# File lib/protobuf/rpc/service_filters.rb, line 213
def run_filters(rpc_method)
  run_rescue_filters do
    continue = run_unwrapped_filters(filters[:before], rpc_method, true)
    if continue
      run_around_filters(rpc_method)
      run_unwrapped_filters(filters[:after], rpc_method)
    end
  end
end
run_rescue_filters() { || ... } click to toggle source
# File lib/protobuf/rpc/service_filters.rb, line 223
def run_rescue_filters
  if rescue_filters.keys.empty?
    yield
  else
    begin
      yield
    rescue *rescue_filters.keys => ex
      callable = rescue_filters.fetch(ex.class) do
        mapped_klass = rescue_filters.keys.find { |child_klass| ex.class < child_klass }
        rescue_filters[mapped_klass]
      end

      call_or_send(callable, ex)
    end
  end
end
run_unwrapped_filters(unwrapped_filters, rpc_method, stop_on_false_return = false) click to toggle source

Loop over the unwrapped filters and invoke them. An unwrapped filter is either a before or after filter, not an around filter.

# File lib/protobuf/rpc/service_filters.rb, line 159
def run_unwrapped_filters(unwrapped_filters, rpc_method, stop_on_false_return = false)
  unwrapped_filters.each do |filter|
    if invoke_filter?(rpc_method, filter)
      return_value = call_or_send(filter[:callable])
      return false if stop_on_false_return && return_value == false
    end
  end

  true
end