lib/softwear/library/light_server.rb in softwear-lib-3.1.5 vs lib/softwear/library/light_server.rb in softwear-lib-3.3.5

- old
+ new

@@ -1,121 +1,145 @@ require 'rbczmq' -def split(string, limit = nil) - string.split(/\s+/, limit) -end +module Softwear + module Library + class LightServer + def self.test!(file_path) + Object.class_eval do + def start_server!(*args) + Thread.new do + Softwear::Library::LightServer.new.start_server!(*args) + end + end + end + load file_path + end -def report_error(rep, whole_command, error) - $stderr.puts "=== ERROR WHILE PROCESSING THE COMMAND \"#{whole_command}\" ===\n"\ - "#{error.class.name}: #{error.message}\n#{error.backtrace.join("\n")}" + def split(string, limit = nil) + string.split(/\s+/, limit) + end - begin - rep.send "sorry" if rep - rescue StandardError => e - $stderr.puts "(could not send 'sorry' message: \"#{e.class} #{e.message}\")" - end -end + def report_error(rep, whole_command, error) + $stderr.puts "=== ERROR WHILE PROCESSING THE COMMAND \"#{whole_command}\" ===\n"\ + "#{error.class.name}: #{error.message}\n#{error.backtrace.join("\n")}" -def dev_log(*a) - $stdout.puts(*a) #if Rails.env.development? -end + begin + rep.send "sorry" if rep + rescue StandardError => e + $stderr.puts "(could not send 'sorry' message: \"#{e.class} #{e.message}\")" + end + end -def log(*a) - $stdout.puts(*a) #unless Rails.env.test? -end + def dev_log(*a) + $stdout.puts(*a) #if Rails.env.development? + end -# ==== Send Format: ======= -# One line strings: "#{command} #{arg1} #{arg2} #{etc}" -# The last argument, depending on the command, may contain spaces (but usually does not need to) -# ========================= -# === Receive Format: ===== -# Usually one string, like "yes", or "no". -# Returns "denied" if an unauthorized command was attempted. -# Returns "invalid" if an invalid command was attempted. -# Returns "sorry" if an error was raised while processing the command. -# Can be a json argument, often following "yes ". -# ========================= -def start_server!(*args) - log "Connecting...!" - - if args.size > 1 - port = args.first - else - port = ENV['port'] || ENV['PORT'] || 2900 - end - address = ENV['SOCKET_ADDR'] || "tcp://*" + def log(*a) + $stdout.puts(*a) #unless Rails.env.test? + end - if address =~ /:$/ - socket_address = address - else - socket_address = "#{address}:#{port}" - end + # ==== Send Format: ======= + # One line strings: "#{command} #{arg1} #{arg2} #{etc}" + # The last argument, depending on the command, may contain spaces (but usually does not need to) + # ========================= + # === Receive Format: ===== + # Usually one string, like "yes", or "no". + # Returns "denied" if an unauthorized command was attempted. + # Returns "invalid" if an invalid command was attempted. + # Returns "sorry" if an error was raised while processing the command. + # Can be a json argument, often following "yes ". + # ========================= + def start_server!(*args) + log "Connecting...!" + + if args.size > 1 + port = args.first + else + port = ENV['port'] || ENV['PORT'] || 2900 + end + address = ENV['SOCKET_ADDR'] || "tcp://*" - ctx = ZMQ::Context.new - rep = ctx.bind(:REP, socket_address) + if address =~ /:$/ + socket_address = address + else + socket_address = "#{address}:#{port}" + end - log "Ready! Using \"#{ActiveRecord::Base.connection.current_database}\" database" + rep = zmq.bind(:REP, socket_address) - commands = args.last + log "Ready! Using \"#{ActiveRecord::Base.connection.try(:current_database) || 'in-memory'}\" database" - loop do - begin - loop do - line_in = rep.recv - raise "Got nil response (ZMQ REP/REQ out of sync?)" if line_in.nil? - command, rest_of_command = split(line_in, 2) + commands = args.last - before = Time.now - begin - command = commands[command.downcase.to_sym] + loop do + begin + loop do + line_in = rep.recv + raise "Got nil response (ZMQ REP/REQ out of sync?)" if line_in.nil? + command, rest_of_command = split(line_in, 2) - if command.nil? - log "Received invalid command: \"#{line_in}\"" - else - dev_log "<== #{line_in}" - ActiveRecord::Base.connection_pool.with_connection do + before = Time.now + begin + command = commands[command.downcase.to_sym] - # The ZMQ socket requires that a reply be send after every - # message -- so we pass a lambda for the client code to - # call to send a message and make sure it only happens - # once. - replied = false - reply = lambda do |msg| - if replied - raise "Reply sent twice" + if command.nil? + log "Received invalid command: \"#{line_in}\"" else - rep.send(msg) - replied = true + dev_log "<== #{line_in}" + ActiveRecord::Base.connection_pool.with_connection do + + # The ZMQ socket requires that a reply be send after every + # message -- so we pass a lambda for the client code to + # call to send a message and make sure it only happens + # once. + replied = false + reply = lambda do |msg| + if replied + raise "Reply sent twice" + else + rep.send(msg) + replied = true + end + end + instance_exec(reply, rest_of_command, &command) + + if !replied + rep.send "noreply" + end + + end end - end - command.call(reply, rest_of_command) - if !replied - rep.send "noreply" + rescue StandardError => e + report_error(rep, line_in, e) + rescue Exception => e + report_error(rep, line_in, e) + break end + after = Time.now + ms = (after - before) * 1000 + dev_log %[(#{'%.2f' % ms}ms)] + dev_log "" end - end - rescue StandardError => e - report_error(rep, line_in, e) - rescue Exception => e - report_error(rep, line_in, e) - break - end - after = Time.now + rescue StandardError => error + $stderr.puts "=== ERROR -- RESTARTING SERVER ===\n"\ + "#{error.class.name}: #{error.message}\n#{error.backtrace.join("\n")}" - ms = (after - before) * 1000 - dev_log %[(#{'%.2f' % ms}ms)] - dev_log "" + rep.destroy + log "Reconnecting...!" + rep = zmq.bind(:REP, socket_address) + end + end end - rescue StandardError => error - $stderr.puts "=== ERROR -- RESTARTING SERVER ===\n"\ - "#{error.class.name}: #{error.message}\n#{error.backtrace.join("\n")}" - - rep.destroy - log "Reconnecting...!" - rep = ctx.bind(:REP, socket_address) + def zmq + $zmq_context ||= ZMQ::Context.new + end end end +end + +def start_server!(*args) + Softwear::Library::LightServer.new.start_server!(*args) end