lib/functions_framework/registry.rb (48 lines of code) (raw):

# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module FunctionsFramework ## # Registry providing lookup of functions by name. # class Registry ## # Create a new empty registry. # def initialize @mutex = ::Mutex.new @functions = {} @start_tasks = [] end ## # Look up a function definition by name. # # @param name [String] The function name # @return [FunctionsFramework::Function] if the function is found # @return [nil] if the function is not found # def [] name @mutex.synchronize { @functions[name.to_s] } end ## # Returns the list of defined names # # @return [Array<String>] # def names @mutex.synchronize { @functions.keys.sort } end ## # Return an array of startup tasks. # # @return [Array<FunctionsFramework::Function>] # def startup_tasks @mutex.synchronize { @start_tasks.dup } end ## # Add an HTTP function to the registry. # # You must provide a name for the function, and a block that implemets the # function. The block should take a single `Rack::Request` argument. It # should return one of the following: # * A standard 3-element Rack response array. See # https://github.com/rack/rack/blob/master/SPEC # * A `Rack::Response` object. # * A simple String that will be sent as the response body. # * A Hash object that will be encoded as JSON and sent as the response # body. # # @param name [String] The function name # @param block [Proc] The function code as a proc # @return [self] # def add_http name, &block name = name.to_s @mutex.synchronize do raise ::ArgumentError, "Function already defined: #{name}" if @functions.key? name @functions[name] = Function.http name, &block end self end ## # Add a Typed function to the registry. # # You must provide a name for the function, and a block that implements the # function. The block should take a single `Hash` argument which will be the # JSON decoded request payload. It should return a `Hash` response which # will be JSON encoded and written to the response. # # @param name [String] The function name. # @param request_class [#decode_json] An optional class which will be used # to decode the request. # @param block [Proc] The function code as a proc # @return [self] # def add_typed name, request_class: nil, &block name = name.to_s @mutex.synchronize do raise ::ArgumentError, "Function already defined: #{name}" if @functions.key? name @functions[name] = Function.typed name, request_class: request_class, &block end self end ## # Add a CloudEvent function to the registry. # # You must provide a name for the function, and a block that implemets the # function. The block should take _one_ argument: the event object of type # [`CloudEvents::Event`](https://cloudevents.github.io/sdk-ruby/latest/CloudEvents/Event). # Any return value is ignored. # # @param name [String] The function name # @param block [Proc] The function code as a proc # @return [self] # def add_cloud_event name, &block name = name.to_s @mutex.synchronize do raise ::ArgumentError, "Function already defined: #{name}" if @functions.key? name @functions[name] = Function.cloud_event name, &block end self end ## # Add a startup task. # # Startup tasks are generally run just before a server starts. They are # passed the {FunctionsFramework::Function} identifying the function to # execute, and have no return value. # # @param block [Proc] The startup task # @return [self] # def add_startup_task &block @mutex.synchronize do @start_tasks << Function.startup_task(&block) end self end end end