Added support for Ruby v2 Specialization (#1101)
* Added support for Ruby v2 Specialization * Added ruby v2 example with builder code
This commit is contained in:
committed by
Ta-Ching Chen
parent
f104f0b46b
commit
c717f182b6
@@ -1,16 +1,11 @@
|
|||||||
FROM ruby:2.4.1
|
FROM ruby:2.6.1-alpine3.9
|
||||||
|
|
||||||
RUN apt-get update -qq && apt-get install -y build-essential
|
RUN apk update
|
||||||
|
RUN apk add --no-cache build-base
|
||||||
RUN mkdir /app
|
|
||||||
WORKDIR /app
|
|
||||||
ADD Gemfile /app/Gemfile
|
|
||||||
ADD Gemfile.lock /app/Gemfile.lock
|
|
||||||
RUN bundle install
|
|
||||||
|
|
||||||
COPY . /app
|
COPY . /app
|
||||||
|
WORKDIR /app
|
||||||
EXPOSE 8888
|
RUN bundle install
|
||||||
|
|
||||||
ENTRYPOINT ["ruby"]
|
ENTRYPOINT ["ruby"]
|
||||||
CMD ["server.rb"]
|
CMD ["server.rb"]
|
||||||
|
|||||||
@@ -2,3 +2,4 @@
|
|||||||
source "https://rubygems.org"
|
source "https://rubygems.org"
|
||||||
|
|
||||||
gem "rack"
|
gem "rack"
|
||||||
|
gem "thin"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This is the Ruby environment for Fission.
|
This is the Ruby environment for Fission.
|
||||||
|
|
||||||
It's a Docker image containing a Ruby 2.4.1 runtime. The image uses
|
It's a Docker image containing a Ruby 2.6.1 runtime. The image uses
|
||||||
Rack with WEBrick to host the internal web server.
|
Rack with WEBrick to host the internal web server.
|
||||||
|
|
||||||
The environment works via convention where you create a Ruby method
|
The environment works via convention where you create a Ruby method
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
ARG BUILDER_IMAGE=fission/builder:latest
|
||||||
|
FROM ${BUILDER_IMAGE}
|
||||||
|
|
||||||
|
FROM ruby:2.6.1-alpine3.9
|
||||||
|
COPY --from=0 /builder /builder
|
||||||
|
|
||||||
|
RUN apk update
|
||||||
|
RUN apk add --no-cache ruby ruby-dev ruby-bundler build-base
|
||||||
|
|
||||||
|
ADD defaultBuildCmd /usr/local/bin/build
|
||||||
|
|
||||||
|
EXPOSE 8001
|
||||||
Executable
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
if [ -f ${SRC_PKG}/Gemfile.lock ]
|
||||||
|
then
|
||||||
|
cd $SRC_PKG
|
||||||
|
bundle install --deployment
|
||||||
|
fi
|
||||||
|
cp -r ${SRC_PKG} ${DEPLOY_PKG}
|
||||||
@@ -7,10 +7,10 @@ module Fission
|
|||||||
def self.call(env)
|
def self.call(env)
|
||||||
context = Context.new(env)
|
context = Context.new(env)
|
||||||
|
|
||||||
response = if method(:handler).arity > 0
|
response = if $handler.arity > 0
|
||||||
handler(context)
|
$handler.call(context)
|
||||||
else
|
else
|
||||||
handler
|
$handler.call
|
||||||
end
|
end
|
||||||
|
|
||||||
response.is_a?(Array) ? response : Rack::Response.new([response]).finish
|
response.is_a?(Array) ? response : Rack::Response.new([response]).finish
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'benchmark'
|
require 'benchmark'
|
||||||
|
require 'json'
|
||||||
|
|
||||||
module Fission
|
module Fission
|
||||||
CODE_PATH = '/userfunc/user'
|
|
||||||
|
|
||||||
module Specializer
|
module Specializer
|
||||||
|
|
||||||
|
CODE_PATH = '/userfunc/user'
|
||||||
|
|
||||||
def self.call(env)
|
def self.call(env)
|
||||||
request = Request.new(env)
|
request = Request.new(env)
|
||||||
|
|
||||||
@@ -12,11 +15,70 @@ module Fission
|
|||||||
time = Benchmark.measure { load CODE_PATH }
|
time = Benchmark.measure { load CODE_PATH }
|
||||||
request.logger.info("User code loaded in #{(time.real * 1000).round(3)}ms")
|
request.logger.info("User code loaded in #{(time.real * 1000).round(3)}ms")
|
||||||
|
|
||||||
Rack::Response.new([], 201).finish
|
# set to "handler" for v1 specialization
|
||||||
|
$handler = method(:handler)
|
||||||
|
|
||||||
|
Rack::Response.new([], 201).finish
|
||||||
rescue => e
|
rescue => e
|
||||||
request.logger.error(%(Specialization failed - #{e}\n#{e.backtrace.join("\n")}))
|
request.logger.error(%(Specialization failed - #{e}\n#{e.backtrace.join("\n")}))
|
||||||
Rack::Response.new(['500 Internal Server Error'], 500, {}).finish
|
Rack::Response.new(['500 Internal Server Error'], 500, {}).finish
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module V2
|
||||||
|
module Specializer
|
||||||
|
|
||||||
|
def self.load_vendor(path)
|
||||||
|
gems = Dir[File.join(path, 'vendor/bundle/ruby/*/gems/*/lib')]
|
||||||
|
exts = Dir[File.join(path, 'vendor/bundle/ruby/*/extensions/x86_64-linux/*/*')]
|
||||||
|
|
||||||
|
$LOAD_PATH.unshift(*gems)
|
||||||
|
$LOAD_PATH.unshift(*exts)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.call(env)
|
||||||
|
request = Request.new(env)
|
||||||
|
|
||||||
|
body = JSON.parse(request.body.read)
|
||||||
|
path = body['filepath']
|
||||||
|
func = body['functionName']
|
||||||
|
|
||||||
|
time = Benchmark.measure do
|
||||||
|
if File.file?(path)
|
||||||
|
# If pointing to just a single file, all we need to do is load it
|
||||||
|
request.logger.debug("Loading file #{path}")
|
||||||
|
|
||||||
|
load path
|
||||||
|
elsif File.directory?(path)
|
||||||
|
# First we want to load all the vendor files
|
||||||
|
load_vendor(path)
|
||||||
|
|
||||||
|
# We then want to get all the .rb files in this src
|
||||||
|
rb_files = File.join(path, "**/*.rb")
|
||||||
|
|
||||||
|
# But we don't want to include the vendor files that we loaded above
|
||||||
|
vendor_dir = File.join(path, 'vendor')
|
||||||
|
src_files = Dir[rb_files].reject {|d| d.start_with?(vendor_dir) }
|
||||||
|
|
||||||
|
request.logger.debug("Loading sources #{src_files}")
|
||||||
|
|
||||||
|
src_files.each do |file|
|
||||||
|
load file
|
||||||
|
end
|
||||||
|
else
|
||||||
|
request.logger.error(%(Specialization failed - could not find src at #{path}}))
|
||||||
|
Rack::Response.new(['500 Internal Server Error'], 500, {}).finish
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
request.logger.info("User code loaded in #{(time.real * 1000).round(3)}ms")
|
||||||
|
|
||||||
|
# set global handler for this specialization
|
||||||
|
$handler = method(func)
|
||||||
|
|
||||||
|
Rack::Response.new([], 201).finish
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,21 +1,33 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rack'
|
require 'rack'
|
||||||
|
require 'thin'
|
||||||
require 'logger'
|
require 'logger'
|
||||||
|
|
||||||
require_relative 'fission/specializer'
|
require_relative 'fission/specializer'
|
||||||
require_relative 'fission/handler'
|
require_relative 'fission/handler'
|
||||||
|
|
||||||
|
$handler = nil
|
||||||
|
|
||||||
app = Rack::Builder.new do
|
app = Rack::Builder.new do
|
||||||
use Rack::Logger, Logger::DEBUG
|
use Rack::Logger, Logger::DEBUG
|
||||||
|
use Rack::CommonLogger
|
||||||
|
|
||||||
map "/specialize" do
|
map "/specialize" do
|
||||||
run Fission::Specializer
|
run Fission::Specializer
|
||||||
end
|
end
|
||||||
|
|
||||||
map "/" do
|
map '/v2/specialize' do
|
||||||
|
run Fission::V2::Specializer
|
||||||
|
end
|
||||||
|
|
||||||
|
map "/healthz" do
|
||||||
|
run ->(env) { [ 200, {}, [] ] }
|
||||||
|
end
|
||||||
|
|
||||||
|
map '/' do
|
||||||
run Fission::Handler
|
run Fission::Handler
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Rack::Handler::WEBrick.run app, Host: '0.0.0.0', Port: 8888
|
Rack::Handler::Thin.run app, Host: '0.0.0.0', Port: 8888
|
||||||
|
|||||||
@@ -105,3 +105,11 @@ $ curl http://$FISSION_ROUTER/request/123?key=abc
|
|||||||
--BODY--
|
--BODY--
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## V2 Specification Example (with builder support)
|
||||||
|
|
||||||
|
```
|
||||||
|
$ fission function create --name parse --env ruby --src "parse/*" --entrypoint handler
|
||||||
|
$ fission fn test --name parse --body '<message>This is my message</message>'
|
||||||
|
This is my message
|
||||||
|
```
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
||||||
|
|
||||||
|
gem "nokogiri"
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
mini_portile2 (2.4.0)
|
||||||
|
nokogiri (1.10.1)
|
||||||
|
mini_portile2 (~> 2.4.0)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
nokogiri
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
1.16.1
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'nokogiri'
|
||||||
|
|
||||||
|
def handler(context)
|
||||||
|
context.logger.info("Received request")
|
||||||
|
|
||||||
|
doc = Nokogiri::XML(context.request.body.read)
|
||||||
|
ele = doc.at_xpath('//message')
|
||||||
|
msg = ele.nil? ? 'No Message' : ele.content
|
||||||
|
|
||||||
|
Rack::Response.new([msg, "\n"]).finish
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user