From 9de546053378e72c0f43afb900397541f977a70a Mon Sep 17 00:00:00 2001 From: John Bintz Date: Wed, 21 Mar 2012 18:41:29 -0400 Subject: [PATCH] websockets is just a hair faster and easier to implement. just sayin'. --- flowerbox.gemspec | 1 + lib/assets/javascripts/flowerbox.js.coffee | 65 +--------------------- lib/flowerbox/rack.rb | 4 -- lib/flowerbox/runner/base.rb | 2 +- lib/flowerbox/runner/node.rb | 35 ++++++------ lib/flowerbox/runner/selenium.rb | 6 +- lib/flowerbox/server.rb | 59 +++++++++++++++----- 7 files changed, 70 insertions(+), 102 deletions(-) diff --git a/flowerbox.gemspec b/flowerbox.gemspec index 75adbe7..2423b1b 100644 --- a/flowerbox.gemspec +++ b/flowerbox.gemspec @@ -33,5 +33,6 @@ Gem::Specification.new do |gem| gem.add_dependency 'sprockets' gem.add_dependency 'sprockets-vendor_gems' gem.add_dependency 'thin' + gem.add_dependency 'em-websocket' end diff --git a/lib/assets/javascripts/flowerbox.js.coffee b/lib/assets/javascripts/flowerbox.js.coffee index ebbd648..ecc8c6e 100644 --- a/lib/assets/javascripts/flowerbox.js.coffee +++ b/lib/assets/javascripts/flowerbox.js.coffee @@ -3,77 +3,18 @@ #= require flowerbox/exception # Flowerbox = - baseUrl: '/' debug: false ping: -> Flowerbox.contact('ping') - contactQueue: [] - contact: (url, data...) -> + Flowerbox.started = true if !Flowerbox.debug - Flowerbox.contactQueue.push([url, data]) + Flowerbox.socket.send(JSON.stringify([ url, data ])) + Flowerbox.done = true if url == 'results' - queueIndex: 0 - delay: 40 started: false done: false - xhrObjects: {} - - onQueueStateChange: -> - - queueRunner: (failsafe = 5) -> - Flowerbox.onQueueStateChange("checking queue") - if Flowerbox.contactQueue.length > 0 - Flowerbox.started = true - - info = Flowerbox.contactQueue.shift() - - [ url, data ] = info - - xhr = new XMLHttpRequest() - xhr.open("POST", Flowerbox.baseUrl + url, true) - xhr.setRequestHeader("Accept", "application/json") - done = false - xhr.onreadystatechange = -> - if xhr.readyState == 4 - done = true - Flowerbox.onQueueStateChange("done #{url}") - if url == "results" - Flowerbox.onQueueStateChange("finsihed all tests") - Flowerbox.done = true - else - setTimeout( - -> - Flowerbox.queueRunner() - , 1 - ) - Flowerbox.onQueueStateChange("running #{url}") - - setTimeout( - -> - if xhr.readyState != 4 - xhr.abort() - Flowerbox.onQueueStateChange("aborted #{url}, rerunning") - Flowerbox.contactQueue.unshift(info) - - if failsafe > 0 - failsafe -= 1 - Flowerbox.queueRunner(failsafe) - , Flowerbox.delay * 5 - ) - - xhr.send(JSON.stringify(data)) - else - Flowerbox.startQueueRunner() - - startQueueRunner: -> - setTimeout( - -> - Flowerbox.queueRunner() - , Flowerbox.delay - ) - fail: -> diff --git a/lib/flowerbox/rack.rb b/lib/flowerbox/rack.rb index 060bf80..70dd28d 100644 --- a/lib/flowerbox/rack.rb +++ b/lib/flowerbox/rack.rb @@ -48,19 +48,15 @@ module Flowerbox end command :ping do - runner.ping end command :pause_timer do - runner.pause_timer end command :unpause_timer do - runner.unpause_timer end command :starting do - runner.did_start! end get %r{^/__F__/(.*)$} do |file| diff --git a/lib/flowerbox/runner/base.rb b/lib/flowerbox/runner/base.rb index 84e1167..dc22a33 100644 --- a/lib/flowerbox/runner/base.rb +++ b/lib/flowerbox/runner/base.rb @@ -140,7 +140,7 @@ module Flowerbox server_options[:logging] = true if options[:verbose_server] server_options[:port] = Flowerbox.port - Flowerbox.server = Flowerbox::Server.new(server_options) + Flowerbox.server = Flowerbox::Server.new(self, server_options) end def log(message) diff --git a/lib/flowerbox/runner/node.rb b/lib/flowerbox/runner/node.rb index f0fc59b..e83206b 100644 --- a/lib/flowerbox/runner/node.rb +++ b/lib/flowerbox/runner/node.rb @@ -22,13 +22,13 @@ module Flowerbox def configured? File.directory?(File.join(Dir.pwd, 'node_modules/jsdom')) && - File.directory?(File.join(Dir.pwd, 'node_modules/xmlhttprequest')) + File.directory?(File.join(Dir.pwd, 'node_modules/ws')) end def cleanup ; end def configure - system %{bash -c "mkdir -p node_modules && npm link jsdom && npm link xmlhttprequest"} + system %{bash -c "mkdir -p node_modules && npm link jsdom && npm link ws"} end def run(sprockets, spec_files, options) @@ -53,7 +53,7 @@ var fs = require('fs'), vm = require('vm'), http = require('http'), jsdom = require('jsdom'), - xhr = require('xmlhttprequest') + ws = require('ws') // expand the sandbox a bit var context = function() {}; @@ -62,7 +62,7 @@ for (method in global) { context[method] = global[method]; } jsdom.env( "", [], function(errors, window) { context.window = window; - context.XMLHttpRequest = xhr.XMLHttpRequest; + context.WebSocket = ws; var gotFlowerbox = false; @@ -106,23 +106,20 @@ jsdom.env( request.end(); } else { - #{env} + context.Flowerbox.socket = new ws('ws://localhost:#{server.port + 1}/'); + context.Flowerbox.socket.onopen = function() { + #{env} - context.Flowerbox.onQueueStateChange = function(msg) { - //console.log(msg); + var waitForFinish; + waitForFinish = function() { + if (!context.Flowerbox.started || !context.Flowerbox.done) { + process.nextTick(waitForFinish); + } else { + process.exit(0); + } + }; + waitForFinish(); }; - - context.Flowerbox.startQueueRunner() - - var waitForFinish; - waitForFinish = function() { - if (!context.Flowerbox.started || !context.Flowerbox.done) { - process.nextTick(waitForFinish); - } else { - process.exit(0); - } - }; - waitForFinish(); } }; fileRunner(); diff --git a/lib/flowerbox/runner/selenium.rb b/lib/flowerbox/runner/selenium.rb index fc19017..116d867 100644 --- a/lib/flowerbox/runner/selenium.rb +++ b/lib/flowerbox/runner/selenium.rb @@ -70,8 +70,10 @@ console.log = function(msg) { var context = this; window.addEventListener('DOMContentLoaded', function() { - #{env} - Flowerbox.startQueueRunner() + Flowerbox.socket = new WebSocket('ws://localhost:#{server.port + 1}/'); + Flowerbox.socket.onopen = function() { + #{env} + }; }, false); diff --git a/lib/flowerbox/server.rb b/lib/flowerbox/server.rb index 9a6e8ce..51129f1 100644 --- a/lib/flowerbox/server.rb +++ b/lib/flowerbox/server.rb @@ -3,16 +3,19 @@ require 'net/http' require 'socket' require 'rack/builder' require 'thin' -require 'eventmachine' +require 'em-websocket' module Flowerbox class Server attr_reader :options + attr_reader :runner + class MissingRackApp < StandardError ; end class ServerDiedError < StandardError ; end - def initialize(options = {}) + def initialize(runner, options = {}) + @runner = runner @options = { :logging => false }.merge(options || {}) end @@ -22,23 +25,51 @@ module Flowerbox def start @server_thread = Thread.new do - server_options = { :Port => port, :Host => interface } + EventMachine.run do + server_options = { :Port => port, :Host => interface } - Thin::Logging.silent = !options[:logging] + Thin::Logging.silent = !options[:logging] - rack_app = app + rack_app = app - if options[:logging] - rack_app = ::Rack::Builder.new do - use ::Rack::CommonLogger, STDOUT - run app + if options[:logging] + rack_app = ::Rack::Builder.new do + use ::Rack::CommonLogger, STDOUT + run app + end end - end - ::Rack::Handler::Thin.run(rack_app, server_options) do |server| - Thread.current[:server] = server + EventMachine::WebSocket.start(:host => interface, :port => port + 1) do |ws| + ws.onmessage { |message| + command, data = JSON.parse(message) - trap('QUIT') { server.stop } + case command + when 'starting' + runner.did_start! + when 'unpause_timer' + runner.unpause_timer + when 'pause_timer' + runner.pause_timer + when 'ping' + runner.ping + when 'log' + runner.log(data.first) + when 'finish_test' + runner.add_results(data.flatten) + when 'start_test' + runner.add_tests(data.flatten) + when 'results' + runner.finish!(data.flatten.first) + end + } + end + + + ::Rack::Handler::Thin.run(rack_app, server_options) do |server| + Thread.current[:server] = server + + trap('QUIT') { server.stop } + end end end @@ -69,7 +100,7 @@ module Flowerbox begin attempts -= 1 - current_port = random_port + current_port = (random_port / 2).floor * 2 begin socket = TCPSocket.new(interface, current_port)