Sha256: c9f9920dd7e69f4fa58bbde89a4545a2c1b5cdb8e1cddfa6e01a9ef2e354167e

Contents?: true

Size: 1.68 KB

Versions: 28

Compression:

Stored size: 1.68 KB

Contents

# frozen_string_literal: true

require "anycable/middleware"
require "monitor"

module AnyCable
  # Middleware chain is used to build the list of
  # gRPC server interceptors.
  #
  # Each interceptor should be a subsclass of
  # AnyCable::Middleware and implement `#call` method.
  class MiddlewareChain
    def initialize
      @registry = []
      @mu = Monitor.new
    end

    def use(middleware)
      check_frozen!
      middleware = build_middleware(middleware)
      sync { registry << middleware }
    end

    def freeze
      registry.freeze
      super
    end

    def to_a
      registry
    end

    def call(method_name, request, meta = {}, &block)
      return yield(method_name, request, meta) if registry.none?

      execute_next_middleware(0, method_name, request, meta, block)
    end

    private

    def execute_next_middleware(ind, method_name, request, meta, block)
      return block.call(method_name, request, meta) if ind >= registry.size

      registry[ind].call(method_name, request, meta) do
        execute_next_middleware(ind + 1, method_name, request, meta, block)
      end
    end

    private

    attr_reader :mu, :registry

    def sync
      mu.synchronize { yield }
    end

    def check_frozen!
      raise "Cannot modify AnyCable middlewares after server started" if frozen?
    end

    def build_middleware(middleware)
      middleware = middleware.new if
        middleware.is_a?(Class) && middleware <= AnyCable::Middleware

      unless middleware.is_a?(AnyCable::Middleware)
        raise ArgumentError,
          "AnyCable middleware must be a subclass of AnyCable::Middleware, " \
          "got #{middleware} instead"
      end

      middleware
    end
  end
end

Version data entries

28 entries across 28 versions & 1 rubygems

Version Path
anycable-core-1.6.0.rc.1 lib/anycable/middleware_chain.rb
anycable-core-1.5.2 lib/anycable/middleware_chain.rb
anycable-core-1.5.1 lib/anycable/middleware_chain.rb
anycable-core-1.5.0 lib/anycable/middleware_chain.rb
anycable-core-1.4.4 lib/anycable/middleware_chain.rb
anycable-core-1.5.0.rc.1 lib/anycable/middleware_chain.rb
anycable-core-1.4.3 lib/anycable/middleware_chain.rb
anycable-core-1.4.2 lib/anycable/middleware_chain.rb
anycable-core-1.4.1 lib/anycable/middleware_chain.rb
anycable-core-1.4.0 lib/anycable/middleware_chain.rb
anycable-core-1.4.0.rc.3 lib/anycable/middleware_chain.rb
anycable-core-1.4.0.rc.2 lib/anycable/middleware_chain.rb
anycable-core-1.4.0.rc.1 lib/anycable/middleware_chain.rb
anycable-core-1.4.0.pre.rc.1 lib/anycable/middleware_chain.rb
anycable-core-1.3.1 lib/anycable/middleware_chain.rb
anycable-core-1.3.0 lib/anycable/middleware_chain.rb
anycable-core-1.2.5 lib/anycable/middleware_chain.rb
anycable-core-1.2.4 lib/anycable/middleware_chain.rb
anycable-core-1.2.3 lib/anycable/middleware_chain.rb
anycable-core-1.2.2 lib/anycable/middleware_chain.rb