require 'rbbt/resource/path'
require 'rbbt/tsv/manipulate'
module Sinatra
module SinatraRbbt
def production?
ENV.include? "RACK_ENV" and not ENV["RACK_ENV"].nil? and ENV['RACK_ENV'].downcase == "production"
end
def old_cache(path, check)
return false if check.nil?
return false if not File.exists? path
check = [check] unless Array === check
return check.select{|file| not File.exists?(file) or File.mtime(file) > File.mtime(path)}.any?
end
def cache(type, options, &block)
cache_type, update, check = Misc.process_options options, :cache_type, :update, :check
check = [check] if not check.nil? and not Array === check
name = type + ":" + Misc.hash2md5(options)
if production?
cache_type ||= :memory
else
cache_type = :none
end
case cache_type.to_sym
when :sync, :synchronous
path = File.join(settings.cache_dir, "sinatra", name)
task = Task.setup(:name => "Sinatra cache", :result_type => :string, &block)
step = Step.new(path, task, nil, nil, self)
step.clean if old_cache(path, check)
begin
case
when (not step.started? and not update == 'check')
step.run
when (step.started? and update == 'reload')
step.clean
step.run
end
rescue
end
begin
case
when step.error?
status 500
status = step.status || "error"
messages = step.messages || []
backtrace = step.info[:backtrace] || []
step.clean
"" << status.to_s << " " << "\n" <<
"" << messages.last << " " << "\n" <<
"
" + backtrace.collect{|line| "- " << line << "
"} * "\n"
when step.done?
step.load
else
if request.xhr?
status 202
"" << (step.status || "starting").to_s << ""
else
retry unless step.done? and not step.error?
step.load
end
end
end
when :async
path = File.join(settings.cache_dir, "sinatra", name)
task = Task.setup(:result_type => :string, &block)
step = Step.new(path, task, nil, nil, self)
step.clean if old_cache(path, check)
case
when (not step.started? and not update == 'check')
step.fork
sleep 0.5
sleep 2 unless step.done?
when (step.started? and update == 'reload')
step.clean
step.fork
sleep 0.5
sleep 2 unless step.done?
end
begin
case
when (not step.started?)
status 202
"" << "not started" << ""
when step.error?
status 500
status = step.status || "error"
messages = step.messages || []
backtrace = step.info[:backtrace] || []
step.clean
"" << status.to_s << " " << "\n" <<
"" << messages.last << " " << "\n" <<
"" + backtrace.collect{|line| "- " << line << "
"} * "\n"
when step.done?
step.load
else
if request.xhr?
status 202
"" << (step.status || "starting").to_s << ""
else
step.join
case
when step.error?
retry
when step.done?
step.load
else
retry
end
end
end
end
when :memory
@@cache ||= {}
@@cache.delete name if not check.nil?
@@cache[name] ||= yield
else
yield
end
end
def job_cache(workflow, task, jobname)
jobname = File.basename(jobname)
@job_cache ||= {}
@job_cache[workflow] ||= {}
@job_cache[workflow][task] ||= {}
@job_cache[workflow][task][jobname] ||= yield
end
def result_cache(workflow, task, jobname)
jobname = File.basename(jobname)
@result_cache ||= {}
@result_cache[workflow] ||= {}
@result_cache[workflow][task] ||= {}
@result_cache[workflow][task][jobname] ||= yield
end
def context_job(workflow, task)
return nil if not defined? session
return nil if not session.include? "context"
return nil if not session["context"].include? workflow
return nil if not session["context"][workflow].include? task
jobname = session["context"][workflow][task]
if authorized?
real_jobname = File.join(user, jobname)
else
real_jobname = jobname
end
return job_cache(workflow.to_s, task.to_s, jobname) do
workflow.load_id File.join(task.to_s, real_jobname)
end
end
def del_context_job(workflow, task)
context = session["context"] || {}
context[workflow] ||= {}
context[workflow].delete task
session["context"] = context
end
def add_context_job(workflow, task, jobname)
jobname = File.basename(jobname)
context = session["context"] || {}
context[workflow] ||= {}
context[workflow][task] = jobname
session["context"] = context
end
def add_param(url, key, value)
if url =~ /\?/
url += "{ key }=#{ value }"
else
url += "?#{ key }=#{ value }"
end
end
def add_params(url, hash)
hash.each do |key, value|
url = add_param url, key, value
end
url
end
#{{{ Params
#
def get_email(params)
IndiferentHash.setup(params)
params.delete :email
end
def get_jobname(params)
IndiferentHash.setup(params)
jobname = params.delete :jobname
jobname = "Default" if jobname.nil? or jobname.empty?
jobname
end
def get_visualization_parameters(params)
IndiferentHash.setup(params)
format = params.delete :_format
format = "html" if format.nil?
format = format.to_s
if params.include? :_pfield
pfield = params.delete :_pfield
pnum = params.delete :_pnum
psize = params.delete :_psize
pnum = pnum.to_i
case params["_paginate"]
when "Asc"
pnum = pnum.abs
when "Desc"
pnum = - pnum.abs
when "Next"
if pnum < 0
pnum = pnum - 1
else
pnum = pnum + 1
end
when "Prev"
if pnum < 0
pnum = pnum + 1
else
pnum = pnum - 1
end
end
pnum = 1 if pnum == 0
params.delete "_page"
params[:_page] = [pfield, pnum, psize] * "~"
end
if params.include? :_ffield
ffield = params.delete :_ffield
fquery = params.delete :_fquery
if fquery.nil? or fquery.strip.empty?
params[:_filter] = nil
else
params[:_filter] = [ffield, fquery] * "~"
end
end
page = params.delete :_page
filter = params.delete :_filter
size = params.delete(:_size) || params.delete("_size")
layout = params.delete :_layout
layout = "false" if request.xhr?
layout = "true" if layout.nil?
layout = layout == "true"
{ :_format => format,
:_page => page,
:_filter => filter,
:_layout => layout,
:_size => size,
:_xhr => request.xhr?,
}
end
def has_all_inputs(workflow, name, params)
IndiferentHash.setup(params)
workflow.rec_inputs(name).reject{|input| params.include? input}.empty?
end
def fix_input(type, value, param_file = nil)
case type
when nil, :string
value
when :integer
value.to_i
when :float
value.to_f
when :boolean
Persist::TRUE_STRINGS.include? value.chomp.strip
when :text
case
when (param_file.nil? and not (value.nil? or value.empty?))
value
when (not param_file.nil?)
value[:tempfile].read
end
when :array
case
when (param_file.nil? and not (value.nil? or value.empty?))
case
when String === value
value.split(/\n|,/).collect{|l| l.strip}
when Array === value
value
else
raise "Input #{ input } must be Array or String: #{value.class}"
end
when (not param_file.nil?)
text = value[:tempfile].read
text.split(/\n|,/).collect{|l| l.strip}
end
when :tsv
case
when (param_file.nil? and not (value.nil? or value.empty?))
TSV.open(StringIO.new(value))
when (not param_file.nil?)
text = value[:tempfile].read
TSV.open(StringIO.new(text))
end
end
end
def get_inputs(workflow, name, params)
inputs = {}
input_types = workflow.rec_input_types(name)
IndiferentHash.setup(input_types)
params.each do |param,value|
next if param == "noinputs"
if param =~ /(.*)_param_file$/
param_file = param
param = $1
else
param_file = nil
end
next unless input_types.include? param
if authorized? and String === value
value.sub!(/local:(.*):(.*)/, 'local:\1:' + user + '/\2')
end
new_value = fix_input(input_types[param], value, param_file)
inputs[param] = new_value unless new_value.nil?
end
IndiferentHash.setup inputs
end
def clean_jobname(name)
name.sub(/(.*)_.*/,'\1')
end
def continue_job(job, workflow, task_name, inputs = {})
task_info = workflow.task_info(task_name)
job_inputs = job.info[:inputs]
job_input_types = task_info[:input_types]
IndiferentHash.setup(job_inputs)
IndiferentHash.setup(job_input_types)
IndiferentHash.setup(inputs)
fixed_inputs = {}
task_info[:inputs].each do |input|
fixed_inputs[input] = job_inputs[input] if job_inputs.include? input
if inputs.include? input
if Step === inputs[input]
step = inputs[input]
name = step.name
input_task_name = step.task.name
case job_input_types[input]
when :array
fixed_inputs[input] = ["local:#{ input_task_name }:#{name}"]
when :tsv
fixed_inputs[input] = {"local:#{ input_task_name }:#{name}" => nil}
else
fixed_inputs[input] = "local:#{ input_task_name }:#{name}"
end
else
fixed_inputs[input] = inputs[input]
end
end
end
new_job = job_cache workflow.to_s, task_name, job.name do
workflow.job(task_name, clean_jobname(job.name), fixed_inputs)
end
result = result_cache workflow.to_s, task_name, new_job.name do
new_job.run
end
[new_job, result]
end
end
end