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
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
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
# 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
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
# File lib/lambda_punch/worker.rb, line 48 def new_drb_queue @queue = DRbObject.new_with_uri(Server.uri) end
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
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
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
# File lib/lambda_punch/worker.rb, line 138 def logger LambdaPunch.logger end
# File lib/lambda_punch/worker.rb, line 142 def noop ; end
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
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
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
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
Helps guard for deadline milliseconds in the past.
# File lib/lambda_punch/worker.rb, line 119 def timed_out? @timeout == 0 || @timeout < 0 end
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
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