class Flack::App
/executions/*
helpers
/
/message
/messages/*
/pointers/*
/*.html /*.css /*.js
Constants
- CURIES
- METHS
- STATIC_FILE
Attributes
unit[R]
Public Class Methods
new(root, opts={})
click to toggle source
# File lib/flack/app.rb, line 17 def initialize(root, opts={}) @root = root conf_path = root.end_with?(File::SEPARATOR + 'conf.json') ? root : File.join(@root, 'etc', 'conf.json') @unit = Flor::Unit.new(conf_path) @unit.start unless opts[:start] == false self.class.unit = @unit @unit end
unit()
click to toggle source
# File lib/flack/app.rb, line 40 def self.unit @unit end
unit=(u)
click to toggle source
# File lib/flack/app.rb, line 43 def self.unit=(u) @unit = u end
Public Instance Methods
call(env)
click to toggle source
# File lib/flack/app.rb, line 47 def call(env) flack_path_info = (env['PATH_INFO'][1..-1] || '') .split('/') flack_path_info = [ 'index' ] if flack_path_info.empty? env['flack.path_info'] = flack_path_info METHS.each do |m| next if env['REQUEST_METHOD'] != m[1] next if flack_path_info.length != m[2].length match = true args = [] for i in 0..(flack_path_info.length - 1) break unless match pi = flack_path_info[i] mi = m[2][i] break if mi == 'plus' || mi == 'star' if mi == 'i' match = pi.match(/\A\d+\z/) args << pi.to_i elsif mi == 's' args << pi elsif mi.is_a?(Regexp) match = pi.match(mi) else match = (pi == mi) end end next unless match env['flack.args'] = args env['flack.query_string'] = Rack::Utils.parse_query(env['QUERY_STRING']) env['flack.root_uri'] = determine_root_uri(env) return send(m[0], env) end respond_not_found(env) rescue => err $stderr.puts '=' * 80 $stderr.puts Time.now.to_s $stderr.puts '-' * 80 $stderr.puts err.inspect $stderr.puts err.backtrace $stderr.puts '-' * 80 PP.pp(env, $stderr) $stderr.puts ('=' * 79) + '.' respond_internal_server_error(env, err) end
delete_executions_s(env)
click to toggle source
DELETE /executions/<exid>
# File lib/flack/app/executions.rb, line 55 def delete_executions_s(env) exid = env['flack.args'][0] return respond_not_found(env) \ unless @unit.executions.where(exid: exid).count > 0 r = { exid: exid, counts: {} } cs = r[:counts] @unit.storage.db.transaction do cs[:messages] = @unit.messages.where(exid: exid).count cs[:executions] = @unit.executions.where(exid: exid).count cs[:pointers] = @unit.pointers.where(exid: exid).count cs[:timers] = @unit.timers.where(exid: exid).count cs[:traps] = @unit.traps.where(exid: exid).count # # not sure if the DB adapter returns the DELETE count, # so counting first @unit.messages.where(exid: exid).delete @unit.executions.where(exid: exid).delete @unit.pointers.where(exid: exid).delete @unit.timers.where(exid: exid).delete @unit.traps.where(exid: exid).delete end respond(env, r) end
get_debug(env)
click to toggle source
# File lib/flack/app.rb, line 110 def get_debug(env); debug_respond(env); end
Also aliased as: get_debug_i
get_executions(env)
click to toggle source
GET /executions
# File lib/flack/app/executions.rb, line 9 def get_executions(env) # TODO implement paging env['flack.rel'] = 'flack:executions' qs = CGI.parse(env['QUERY_STRING'] || '') statuses = qs['status'] statuses = nil if statuses == [] q = @unit.executions q = q.where(status: statuses) if statuses respond(env, q.all) end
get_executions_i(env)
click to toggle source
GET /executions/<id>
# File lib/flack/app/executions.rb, line 26 def get_executions_i(env) env['flack.rel'] = 'flack:executions/id' if exe = @unit.executions[env['flack.args'][0]] respond(env, exe) else respond_not_found(env) end end
get_executions_s(env)
click to toggle source
GET /executions/<exid> GET /executions/<domain> GET /executions/<domain>* GET /executions/<domain>.*
# File lib/flack/app/executions.rb, line 42 def get_executions_s(env) arg = env['flack.args'][0] if arg.count('-') == 0 get_executions_by_domain(env, arg) else get_executions_by_exid(env, arg) end end
get_index(env)
click to toggle source
# File lib/flack/app/index.rb, line 7 def get_index(env) # TODO respond(env, nil) end
get_messages(env)
click to toggle source
GET /messages
# File lib/flack/app/messages.rb, line 8 def get_messages(env) # TODO implement paging env['flack.rel'] = 'flack:messages' respond(env, @unit.messages.all) end
get_messages_i(env)
click to toggle source
GET /messages/<id>
# File lib/flack/app/messages.rb, line 17 def get_messages_i(env) env['flack.rel'] = 'flack:messages' if exe = @unit.messages[env['flack.args'][0]] respond(env, exe) else respond_not_found(env) end end
get_messages_s(env)
click to toggle source
GET /messages/<exid>
# File lib/flack/app/messages.rb, line 29 def get_messages_s(env) # TODO implement paging arg = env['flack.args'][0] if Flor.point?(arg) get_messages_by_point(env, arg) else get_messages_by_exid(env, arg) end end
get_messages_s_s(env)
click to toggle source
GET /messages/<exid>/<point>
# File lib/flack/app/messages.rb, line 42 def get_messages_s_s(env) env['flack.rel'] = 'flack:messages/exid/point' exid, point = env['flack.args'] respond( env, @unit.messages.where(exid: exid, point: point).all) end
get_pointers(env)
click to toggle source
GET /pointers
# File lib/flack/app/pointers.rb, line 9 def get_pointers(env) # TODO implement paging env['flack.rel'] = 'flack:pointers' qs = CGI.parse(env['QUERY_STRING'] || '') types = qs['types'].collect { |e| e.split(',') }.flatten types = nil if types == [] q = @unit.pointers q = q.where(type: types) if types respond(env, q.all) end
get_pointers_s(env)
click to toggle source
GET /pointers/<exid> GET /pointers/<domain> GET /pointers/<domain>* GET /pointers/<domain>.*
# File lib/flack/app/pointers.rb, line 29 def get_pointers_s(env) arg = env['flack.args'][0] qs = CGI.parse(env['QUERY_STRING'] || '') types = qs['types'].collect { |e| e.split(',') }.flatten types = nil if types == [] if arg.count('-') == 0 get_pointers_by_domain(env, arg, types) else get_pointers_by_exid(env, arg, types) end end
post_message(env)
click to toggle source
# File lib/flack/app/message.rb, line 7 def post_message(env) msg = JSON.load(env['rack.input'].read) pt = msg['point'] return respond_bad_request(env, 'missing msg point') \ unless pt return respond_bad_request(env, "bad msg point #{pt.inspect}") \ unless %w[ launch cancel reply ].include?(pt) r = self.send("queue_#{pt}", env, msg, { point: pt }) respond(env, r) end
serve_file(env)
click to toggle source
# File lib/flack/app/static.rb, line 14 def serve_file(env) STATIC_FILE.call(env) end
shutdown()
click to toggle source
# File lib/flack/app.rb, line 35 def shutdown @unit.shutdown end
Protected Instance Methods
abs(env, href)
click to toggle source
# File lib/flack/app/helpers.rb, line 94 def abs(env, href) return href if href[0, 4] == 'http' "#{env['flack.root_uri']}#{href[0, 1] == '/' ? '': '/'}#{href}" end
debug_respond(env)
click to toggle source
# File lib/flack/app/helpers.rb, line 9 def debug_respond(env) [ 200, { 'Content-Type' => 'application/json' }, [ JSON.dump(env) ] ] end
determine_root_uri(env)
click to toggle source
# File lib/flack/app/helpers.rb, line 87 def determine_root_uri(env) hh = env['HTTP_HOST'] || "#{env['SERVER_NAME']}:#{env['SERVER_PORT']}" "#{env['rack.url_scheme']}://#{hh}#{env['SCRIPT_NAME']}" end
forms(env)
click to toggle source
# File lib/flack/app/helpers.rb, line 158 def forms(env) h = {} h['curies'] = CURIES h['flack:forms/message'] = { action: rel(env, '/message'), method: 'POST', _inputs: { 'flack:forms/message-content' => { type: 'json' } } } h['flack:forms/execution-deletion'] = { action: rel(env, '/executions/{exid}'), method: 'DELETE', _inputs: {}, templated: true } h end
get_executions_by_domain(env, dom)
click to toggle source
# File lib/flack/app/executions.rb, line 99 def get_executions_by_domain(env, dom) qs = CGI.parse(env['QUERY_STRING'] || '') statuses = qs['status'] statuses = nil if statuses == [] q = @unit.executions if m = dom.match(/\A([^*]+)\*+\z/) if m[1][-1, 1] == '.' env['flack.rel'] = 'flack:executions/domain-dot-star' q = q.where(Sequel.like(:domain, "#{m[1]}%")) else env['flack.rel'] = 'flack:executions/domain-star' q = q.where( Sequel[{ domain: m[1] }] | Sequel.like(:domain, "#{m[1]}.%")) end else env['flack.rel'] = 'flack:executions/domain' q = q.where(domain: dom) end q = q.where(status: statuses) if statuses respond(env, q.all) end
get_executions_by_exid(env, exid)
click to toggle source
# File lib/flack/app/executions.rb, line 88 def get_executions_by_exid(env, exid) env['flack.rel'] = 'flack:executions/exid' if exe = @unit.executions[exid: exid] respond(env, exe) else respond_not_found(env) end end
get_messages_by_exid(env, exid)
click to toggle source
# File lib/flack/app/messages.rb, line 55 def get_messages_by_exid(env, exid) env['flack.rel'] = 'flack:messages/exid' respond(env, @unit.messages.where(exid: exid).all) end
get_messages_by_point(env, point)
click to toggle source
# File lib/flack/app/messages.rb, line 62 def get_messages_by_point(env, point) env['flack.rel'] = 'flack:messages/point' respond(env, @unit.messages.where(point: point).all) end
get_pointers_by_domain(env, dom, types)
click to toggle source
# File lib/flack/app/pointers.rb, line 57 def get_pointers_by_domain(env, dom, types) q = @unit.pointers q = q.where(type: types) if types if m = dom.match(/\A([^*]+)\*+\z/) if m[1][-1, 1] == '.' env['flack.rel'] = 'flack:pointers/domain-dot-star' q = q.where(Sequel.like(:domain, "#{m[1]}%")) else env['flack.rel'] = 'flack:pointers/domain-star' q = q.where( Sequel[{ domain: m[1] }] | Sequel.like(:domain, "#{m[1]}.%")) end else env['flack.rel'] = 'flack:pointers/domain' q = q.where(domain: dom) end respond(env, q.all) end
get_pointers_by_exid(env, exid, types)
click to toggle source
# File lib/flack/app/pointers.rb, line 47 def get_pointers_by_exid(env, exid, types) env['flack.rel'] = 'flack:pointers/exid' q = @unit.pointers.where(exid: exid) q = q.where(type: types) if types respond(env, q.all) end
is_response?(o)
click to toggle source
# File lib/flack/app/helpers.rb, line 14 def is_response?(o) o.is_a?(Array) && o.length == 3 && o[0].is_a?(Integer) && o[1].is_a?(Hash) && o[2].is_a?(Array) end
key(env)
click to toggle source
# File lib/flack/app/helpers.rb, line 82 def key(env) env['flack.rel'] || 'flack:unspecified-rel' end
link(env, h, type)
click to toggle source
# File lib/flack/app/helpers.rb, line 106 def link(env, h, type) l = { href: rel(env, "/#{type}") } l[:templated] = true if type.index('{') rel_right_part = type .gsub(/\{\?[^}]*\}/, '') .gsub(/[{}]/, '') .gsub(/\./, '-dot') .gsub(/\*/, '-star') h["flack:#{rel_right_part}"] = l end
links(env)
click to toggle source
# File lib/flack/app/helpers.rb, line 125 def links(env) h = {} h['self'] = { href: rel(env, env['REQUEST_PATH'] || env['PATH_INFO']) } m = env['REQUEST_METHOD'] h['self'][:method] = m unless %w[ GET HEAD ].include?(m) h['curies'] = CURIES link(env, h, 'executions{?status}') link(env, h, 'executions/{domain}{?status}') link(env, h, 'executions/{domain}*{?status}') link(env, h, 'executions/{domain}.*{?status}') link(env, h, 'executions/{exid}') link(env, h, 'executions/{id}') link(env, h, 'messages') link(env, h, 'messages/{point}') link(env, h, 'messages/{exid}/{point}') link(env, h, 'messages/{exid}') link(env, h, 'messages/{id}') link(env, h, 'pointers{?type}') link(env, h, 'pointers/{exid}{?type}') link(env, h, 'pointers/{domain}{?type}') link(env, h, 'pointers/{domain}*{?type}') link(env, h, 'pointers/{domain}.*{?type}') h end
queue_cancel(env, msg, ret)
click to toggle source
# File lib/flack/app/message.rb, line 52 def queue_cancel(env, msg, ret) exid = msg['exid'] nid = msg['nid'] || '0' return respond_bad_request(env, 'missing exid') \ unless exid exe = @unit.executions[exid: exid] return respond_not_found(env, 'missing execution') \ unless exe return respond_not_found(env, 'missing execution node') \ unless exe.nodes[nid] ret['xxx'] = @unit.queue({ 'point' => 'cancel', 'exid' => exid, 'nid' => nid }) # FIXME change me ret['_status'] = 202 ret['_location'] = rel(env, '/executions/' + exid) ret['_links'] = { 'flack:execution' => { 'href' => ret['_location'] } } ret end
queue_launch(env, msg, ret)
click to toggle source
# File lib/flack/app/message.rb, line 25 def queue_launch(env, msg, ret) dom = msg['domain'] || 'domain0' src = msg['tree'] || msg['name'] vars = msg['vars'] || {} fields = msg['fields'] || {} return respond_bad_request(env, 'missing "tree" or "name" in launch msg') \ unless src opts = {} opts[:domain] = dom opts[:vars] = vars opts[:fields] = fields r = @unit.launch(src, opts) ret['exid'] = r ret['_status'] = 201 ret['_location'] = rel(env, '/executions/' + r) ret['_links'] = { 'flack:forms/message-created' => { 'href' => ret['_location'] } } ret end
queue_reply(env, msg, ret)
click to toggle source
# File lib/flack/app/message.rb, line 76 def queue_reply(env, msg, ret) exid = msg['exid'] nid = msg['nid'] payload = msg['payload'] || {} return respond_bad_request(env, 'missing exid') \ unless exid return respond_bad_request(env, 'missing nid') \ unless nid exe = @unit.executions[exid: exid] return respond_not_found(env, 'missing execution') \ unless exe return respond_not_found(env, 'missing execution node') \ unless exe.nodes[nid] ret['xxx'] = @unit.queue({ 'point' => 'return', 'exid' => exid, 'nid' => nid, 'payload' => payload}) # FIXME change me ret['_status'] = 202 ret['_location'] = rel(env, '/executions/' + exid) ret['_links'] = { 'flack:execution' => { 'href' => ret['_location'] } } ret end
rel(env, href)
click to toggle source
# File lib/flack/app/helpers.rb, line 100 def rel(env, href) return href if href[0, 4] == 'http' "#{env['SCRIPT_NAME']}#{href[0, 1] == '/' ? '': '/'}#{href}" end
respond(env, data, opts={})
click to toggle source
# File lib/flack/app/helpers.rb, line 23 def respond(env, data, opts={}) return data if opts == {} && is_response?(data) status = nil links = nil location = nil if data.is_a?(Hash) status = data['_status'] || data[:_status] links = data.delete('_links') || data.delete(:_links) location = data['_location'] || data[:_location] end status = status || opts[:code] || opts[:status] || 200 headers = { 'Content-Type' => 'application/json' } headers['Location'] = location if location json = serialize(env, data, opts) json['_links'].merge!(links) if links json['_status'] = status json['_status_text'] = Rack::Utils::HTTP_STATUS_CODES[status] if e = opts[:error]; json['error'] = e; end [ status, headers, [ JSON.dump(json) ] ] end
respond_bad_request(env, error=nil)
click to toggle source
# File lib/flack/app/helpers.rb, line 178 def respond_bad_request(env, error=nil) respond(env, {}, code: 400, error: error) end
respond_internal_server_error(env, error=nil)
click to toggle source
# File lib/flack/app/helpers.rb, line 188 def respond_internal_server_error(env, error=nil) respond(env, {}, code: 500, error: error) end
respond_not_found(env, error=nil)
click to toggle source
# File lib/flack/app/helpers.rb, line 183 def respond_not_found(env, error=nil) respond(env, {}, code: 404, error: error) end
serialize(env, data, opts)
click to toggle source
# File lib/flack/app/helpers.rb, line 59 def serialize(env, data, opts) return serialize_array(env, data, opts) if data.is_a?(Array) r = (data.is_a?(Hash) ? Flor.dup(data) : nil) || (data.nil? ? {} : nil) || data.to_h #r['_klass'] = data.class.to_s # too rubyish r['_links'] = links(env) r['_forms'] = forms(env) r end
serialize_array(env, data, opts)
click to toggle source
# File lib/flack/app/helpers.rb, line 75 def serialize_array(env, data, opts) { '_links' => links(env), '_embedded' => { key(env) => data.collect { |e| serialize(env, e, opts) } } } end
try(o, meth)
click to toggle source
# File lib/flack/app/helpers.rb, line 54 def try(o, meth) o.respond_to?(meth) ? o.send(meth) : nil end