Skip to content

Commit

Permalink
Refactor to dispatch by function name
Browse files Browse the repository at this point in the history
  • Loading branch information
elct9620 committed Jan 1, 2024
1 parent 05d895d commit 5d67d62
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 22 deletions.
42 changes: 36 additions & 6 deletions lib/hanami/lambda/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,46 @@ module ClassMethods
# @api private
# @since 0.1.0
def call(event:, context:)
handler = lookup(event: event, context: context)
handler.call
dispatcher.call(event: event, context: context)
end

# Lookup the handler for the given event
# Definitions of handlers
#
# @api private
# @since 0.1.0
def lookup(event:, context:)
Rack.new(Hanami.app, event: event, context: context)
def definitions
@definitions ||= []
end

# Register a handler
#
# @param name [String] the name of the handler
# @param args [Array] the arguments to pass to the handler
# @param kwargs [Hash] the keyword arguments to pass to the handler
# @param block [Proc] the block to pass to the handler
def register(name, *args, **kwargs, &block)
definitions << [name, args, kwargs, block]
end

# Dispatcher
#
# @api private
def dispatcher
@dispatcher ||= build_dispatcher
end

# Build Dispatcher
#
# @api private
def build_dispatcher
Dispatcher.new(Hanami.app).tap do |dispatcher|
definitions.each do |(name, args, kwargs, block)|
if block
dispatcher.register(name, *args, **kwargs, &block)
else
dispatcher.register(name, *args, **kwargs)
end
end
end
end
end
end
Expand Down
51 changes: 51 additions & 0 deletions lib/hanami/lambda/dispatcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# frozen_string_literal: true

module Hanami
module Lambda
# Dispatch Event to the Handler
#
# @api private
class Dispatcher
attr_reader :app, :handlers

def initialize(app)
@app = app
@handlers = {}
end

# Call the handler
#
# @param event [Hash] the event
# @param context [Hash] the context
#
# @since 0.2.0
def call(event:, context:)
handler = lookup(event: event, context: context)
handler.call(event: event, context: context)
end

# Lookup the handler
#
# @param event [Hash] the event
# @param context [Hash] the context
#
# @return [Handler] the handler
def lookup(event:, context:)
function_name = context.function_name
handlers[function_name]
end

# Register a handler
#
# @param name [String] the name of the handler
# @param args [Array] the arguments to pass to the handler
# @param kwargs [Hash] the keyword arguments to pass to the handler
# @param block [Proc] the block to pass to the handler
#
# @since 0.2.0
def register(name, ...)
handlers[name] = Rack.new(app)
end
end
end
end
15 changes: 8 additions & 7 deletions lib/hanami/lambda/rack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@ module Lambda
# @api private
# @since 0.1.0
class Rack
attr_reader :app, :event, :context
attr_reader :app

# @api private
def initialize(app, event:, context:)
# Initialize the Rack interface
#
# @since 0.1.0
def initialize(app)
@app = app
@event = event
@context = context
end

# Handle the request
#
# @return [Hash] the response
#
# @since 0.1.0
def call
def call(event:, context:)
env = build_env(event, context)
status_code, headers, body = app.call(env)

{
Expand All @@ -38,7 +39,7 @@ def call
# @return [Hash] the Rack environment
#
# @since 0.1.0
def env
def build_env(event, context)
{
::Rack::REQUEST_METHOD => event["httpMethod"],
::Rack::PATH_INFO => event["path"] || "",
Expand Down
37 changes: 31 additions & 6 deletions spec/hanami/lambda/application_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,45 @@
Hanami::Lambda.remove_instance_variable(:@_app) if Hanami::Lambda.instance_variable_defined?(:@_app)
end

subject(:app) { Class.new(described_class) }
subject(:app) do
Class.new(described_class) do
register "ExampleApi"
end
end

it { is_expected.to be_a(Hanami::Lambda::Application::ClassMethods) }

describe ".lookup" do
subject(:lookup) { app.lookup(event: event, context: context) }
describe ".definitions" do
subject(:definitions) { app.definitions }

it { is_expected.to include(["ExampleApi", [], {}, nil]) }
end

describe ".register" do
subject(:register) { app.register("ExampleApi") }

it "registers the application" do
expect { register }.to change { app.definitions.size }.by(1)
end
end

describe ".call" do
subject(:call) { app.call(event: event, context: context) }

let(:rack_app) do
lambda do |_env|
[200, {}, ["Hello World"]]
end
end

let(:event) { {} }
let(:context) { double(:context) }
let(:context) { double(:context, function_name: "ExampleApi") }

before do
allow(Hanami).to receive(:app).and_return(double("Hanami::Application"))
allow(Hanami).to receive(:app).and_return(rack_app)
end

it { is_expected.to be_a(Hanami::Lambda::Rack) }
it { is_expected.to include(statusCode: 200) }
it { is_expected.to include(body: "Hello World") }
end
end
6 changes: 3 additions & 3 deletions spec/hanami/lambda/rack_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

RSpec.describe Hanami::Lambda::Rack do
subject(:rack) { described_class.new(app, event: event, context: context) }
subject(:rack) { described_class.new(app) }

let(:app) do
lambda do |_env|
Expand All @@ -20,15 +20,15 @@
let(:context) { double(:context) }

describe "#call" do
subject(:call) { rack.call }
subject(:call) { rack.call(event: event, context: context) }

it { is_expected.to include(statusCode: 200) }
it { is_expected.to include(body: "Hello from Rack") }
it { is_expected.to include(headers: {}) }
end

describe "#env" do
subject(:env) { rack.env }
subject(:env) { rack.build_env(event, context) }

it { is_expected.to include(::Hanami::Lambda::LAMBDA_EVENT) }
it { is_expected.to include(::Hanami::Lambda::LAMBDA_CONTEXT) }
Expand Down

0 comments on commit 5d67d62

Please sign in to comment.