class LambdaPunch::Worker

This `LambdaPunch::Worker` has a few responsibilities:

1. Maintain a class level DRb reference to your function's `LambdaPunch::Queue` object.
2. Process extension `INVOKE` events by waiting for your function to complete.
3. Triggering your application to perform work after each request.

Public Class Methods

call(event_payload) click to toggle source

Creates a new instance of this object with the event payload from the `LambdaPunch::Api#invoke` method and immediately performs the `call` method which waits for the function's handler to complete.

# File lib/lambda_punch/worker.rb, line 25
def call(event_payload)
  new(event_payload).call
end
call_queue() click to toggle source

A safe and resilient way to call the remote queue.

# File lib/lambda_punch/worker.rb, line 31
def call_queue
  queue.call
rescue DRb::DRbConnError
  LambdaPunch.logger.error "Worker#call_queue => DRb::DRbConnError"
  new_drb_queue
  queue.call
end
new(event_payload) click to toggle source
# File lib/lambda_punch/worker.rb, line 54
def initialize(event_payload)
  @invoked = false
  @event_payload = event_payload
  @notifier = Notifier.new
  @notifier.watch { |request_id| notified(request_id) }
  @request_id_notifier = nil
end
start!() click to toggle source

Method to lazily require rb-inotify and start the DRb service.

# File lib/lambda_punch/worker.rb, line 14
def start!
  LambdaPunch.logger.info "Worker.start!..."
  require 'timeout'
  require 'rb-inotify'
  DRb.start_service
  new_drb_queue
end

Private Class Methods

new_drb_queue() click to toggle source
# File lib/lambda_punch/worker.rb, line 48
def new_drb_queue
  @queue = DRbObject.new_with_uri(Server.uri)
end
queue() click to toggle source

The `@queue` object is the local process' reference to the application `LambdaPunch::Queue` instance which does all the work in the applciation's scope.

# File lib/lambda_punch/worker.rb, line 44
def queue
  @queue
end

Public Instance Methods

call() click to toggle source

Here we wait for the application's handler to signal it is done via the `LambdaPunch::Notifier` or if the function has timed out. In either event there may be work to perform in the `LambdaPunch::Queue`. This method also ensures any clean up is done. For example, closing file notifications.

# File lib/lambda_punch/worker.rb, line 66
def call
  timeout { @notifier.process unless invoked? }
rescue Timeout::Error
  logger.error "Worker#call => Function timeout reached."
ensure
  @notifier.close
  self.class.call_queue
end

Private Instance Methods

invoked?() click to toggle source

The Notifier's watch handler would set this instance variable to `true`. We also return `true` if the extension's invoke palyload event has a `requestId` matching what the handler has written to the `LambdaPunch::Notifier` file location. See also `request_ids_match?` method. Lastly if the timeout

# File lib/lambda_punch/worker.rb, line 82
def invoked?
  @invoked || request_ids_match? || timed_out?
end
logger() click to toggle source
# File lib/lambda_punch/worker.rb, line 138
def logger
  LambdaPunch.logger
end
noop() click to toggle source
# File lib/lambda_punch/worker.rb, line 142
def noop ; end
notified(request_id) click to toggle source

Our `LambdaPunch::Notifier` instance callback.

# File lib/lambda_punch/worker.rb, line 133
def notified(request_id)
  @invoked = true
  @request_id_notifier = request_id
end
request_id_notifier() click to toggle source

Set via the `LambdaPunch::Notifier` watch event from the your function's handler.

# File lib/lambda_punch/worker.rb, line 95
def request_id_notifier
  @request_id_notifier
end
request_id_payload() click to toggle source

The unique AWS reqeust id that both the extension and handler receive for each invoke. This one represents the extension's side.

# File lib/lambda_punch/worker.rb, line 89
def request_id_payload
  @event_payload['requestId']
end
request_ids_match?() click to toggle source

Check if notified via inotify or in some rare case the function's handler has already completed and written the matching request id via the context object to the `LambdaPunch::Notifier` file.

# File lib/lambda_punch/worker.rb, line 102
def request_ids_match?
  request_id_payload == (request_id_notifier || Notifier.request_id)
end
timed_out?() click to toggle source

Helps guard for deadline milliseconds in the past.

# File lib/lambda_punch/worker.rb, line 119
def timed_out?
  @timeout == 0 || @timeout < 0
end
timeout() { || ... } click to toggle source

A safe timeout method which accounts for a 0 or negative timeout value.

# File lib/lambda_punch/worker.rb, line 108
def timeout
  @timeout = timeout_seconds
  if timed_out?
    yield
  else
    Timeout.timeout(@timeout) { yield }
  end
end
timeout_seconds() click to toggle source

The function's timeout in seconds using the `INVOKE` event payload's `deadlineMs` value.

# File lib/lambda_punch/worker.rb, line 125
def timeout_seconds
  deadline_milliseconds = @event_payload['deadlineMs']
  deadline = Time.at(deadline_milliseconds / 1000.0)
  deadline - Time.now
end