websockets is just a hair faster and easier to implement. just sayin'.
This commit is contained in:
parent
ed00ba476a
commit
9de5460533
@ -33,5 +33,6 @@ Gem::Specification.new do |gem|
|
|||||||
gem.add_dependency 'sprockets'
|
gem.add_dependency 'sprockets'
|
||||||
gem.add_dependency 'sprockets-vendor_gems'
|
gem.add_dependency 'sprockets-vendor_gems'
|
||||||
gem.add_dependency 'thin'
|
gem.add_dependency 'thin'
|
||||||
|
gem.add_dependency 'em-websocket'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3,77 +3,18 @@
|
|||||||
#= require flowerbox/exception
|
#= require flowerbox/exception
|
||||||
#
|
#
|
||||||
Flowerbox =
|
Flowerbox =
|
||||||
baseUrl: '/'
|
|
||||||
debug: false
|
debug: false
|
||||||
ping: ->
|
ping: ->
|
||||||
Flowerbox.contact('ping')
|
Flowerbox.contact('ping')
|
||||||
|
|
||||||
contactQueue: []
|
|
||||||
|
|
||||||
contact: (url, data...) ->
|
contact: (url, data...) ->
|
||||||
|
Flowerbox.started = true
|
||||||
if !Flowerbox.debug
|
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
|
started: false
|
||||||
done: 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: ->
|
fail: ->
|
||||||
|
|
||||||
|
@ -48,19 +48,15 @@ module Flowerbox
|
|||||||
end
|
end
|
||||||
|
|
||||||
command :ping do
|
command :ping do
|
||||||
runner.ping
|
|
||||||
end
|
end
|
||||||
|
|
||||||
command :pause_timer do
|
command :pause_timer do
|
||||||
runner.pause_timer
|
|
||||||
end
|
end
|
||||||
|
|
||||||
command :unpause_timer do
|
command :unpause_timer do
|
||||||
runner.unpause_timer
|
|
||||||
end
|
end
|
||||||
|
|
||||||
command :starting do
|
command :starting do
|
||||||
runner.did_start!
|
|
||||||
end
|
end
|
||||||
|
|
||||||
get %r{^/__F__/(.*)$} do |file|
|
get %r{^/__F__/(.*)$} do |file|
|
||||||
|
@ -140,7 +140,7 @@ module Flowerbox
|
|||||||
server_options[:logging] = true if options[:verbose_server]
|
server_options[:logging] = true if options[:verbose_server]
|
||||||
server_options[:port] = Flowerbox.port
|
server_options[:port] = Flowerbox.port
|
||||||
|
|
||||||
Flowerbox.server = Flowerbox::Server.new(server_options)
|
Flowerbox.server = Flowerbox::Server.new(self, server_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def log(message)
|
def log(message)
|
||||||
|
@ -22,13 +22,13 @@ module Flowerbox
|
|||||||
|
|
||||||
def configured?
|
def configured?
|
||||||
File.directory?(File.join(Dir.pwd, 'node_modules/jsdom')) &&
|
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
|
end
|
||||||
|
|
||||||
def cleanup ; end
|
def cleanup ; end
|
||||||
|
|
||||||
def configure
|
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
|
end
|
||||||
|
|
||||||
def run(sprockets, spec_files, options)
|
def run(sprockets, spec_files, options)
|
||||||
@ -53,7 +53,7 @@ var fs = require('fs'),
|
|||||||
vm = require('vm'),
|
vm = require('vm'),
|
||||||
http = require('http'),
|
http = require('http'),
|
||||||
jsdom = require('jsdom'),
|
jsdom = require('jsdom'),
|
||||||
xhr = require('xmlhttprequest')
|
ws = require('ws')
|
||||||
|
|
||||||
// expand the sandbox a bit
|
// expand the sandbox a bit
|
||||||
var context = function() {};
|
var context = function() {};
|
||||||
@ -62,7 +62,7 @@ for (method in global) { context[method] = global[method]; }
|
|||||||
jsdom.env(
|
jsdom.env(
|
||||||
"<html><head><title></title></head><body></body></html>", [], function(errors, window) {
|
"<html><head><title></title></head><body></body></html>", [], function(errors, window) {
|
||||||
context.window = window;
|
context.window = window;
|
||||||
context.XMLHttpRequest = xhr.XMLHttpRequest;
|
context.WebSocket = ws;
|
||||||
|
|
||||||
var gotFlowerbox = false;
|
var gotFlowerbox = false;
|
||||||
|
|
||||||
@ -106,23 +106,20 @@ jsdom.env(
|
|||||||
|
|
||||||
request.end();
|
request.end();
|
||||||
} else {
|
} else {
|
||||||
#{env}
|
context.Flowerbox.socket = new ws('ws://localhost:#{server.port + 1}/');
|
||||||
|
context.Flowerbox.socket.onopen = function() {
|
||||||
|
#{env}
|
||||||
|
|
||||||
context.Flowerbox.onQueueStateChange = function(msg) {
|
var waitForFinish;
|
||||||
//console.log(msg);
|
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();
|
fileRunner();
|
||||||
|
@ -70,8 +70,10 @@ console.log = function(msg) {
|
|||||||
var context = this;
|
var context = this;
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', function() {
|
window.addEventListener('DOMContentLoaded', function() {
|
||||||
#{env}
|
Flowerbox.socket = new WebSocket('ws://localhost:#{server.port + 1}/');
|
||||||
Flowerbox.startQueueRunner()
|
Flowerbox.socket.onopen = function() {
|
||||||
|
#{env}
|
||||||
|
};
|
||||||
}, false);
|
}, false);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -3,16 +3,19 @@ require 'net/http'
|
|||||||
require 'socket'
|
require 'socket'
|
||||||
require 'rack/builder'
|
require 'rack/builder'
|
||||||
require 'thin'
|
require 'thin'
|
||||||
require 'eventmachine'
|
require 'em-websocket'
|
||||||
|
|
||||||
module Flowerbox
|
module Flowerbox
|
||||||
class Server
|
class Server
|
||||||
attr_reader :options
|
attr_reader :options
|
||||||
|
|
||||||
|
attr_reader :runner
|
||||||
|
|
||||||
class MissingRackApp < StandardError ; end
|
class MissingRackApp < StandardError ; end
|
||||||
class ServerDiedError < StandardError ; end
|
class ServerDiedError < StandardError ; end
|
||||||
|
|
||||||
def initialize(options = {})
|
def initialize(runner, options = {})
|
||||||
|
@runner = runner
|
||||||
@options = { :logging => false }.merge(options || {})
|
@options = { :logging => false }.merge(options || {})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -22,23 +25,51 @@ module Flowerbox
|
|||||||
|
|
||||||
def start
|
def start
|
||||||
@server_thread = Thread.new do
|
@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]
|
if options[:logging]
|
||||||
rack_app = ::Rack::Builder.new do
|
rack_app = ::Rack::Builder.new do
|
||||||
use ::Rack::CommonLogger, STDOUT
|
use ::Rack::CommonLogger, STDOUT
|
||||||
run app
|
run app
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
::Rack::Handler::Thin.run(rack_app, server_options) do |server|
|
EventMachine::WebSocket.start(:host => interface, :port => port + 1) do |ws|
|
||||||
Thread.current[:server] = server
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -69,7 +100,7 @@ module Flowerbox
|
|||||||
begin
|
begin
|
||||||
attempts -= 1
|
attempts -= 1
|
||||||
|
|
||||||
current_port = random_port
|
current_port = (random_port / 2).floor * 2
|
||||||
|
|
||||||
begin
|
begin
|
||||||
socket = TCPSocket.new(interface, current_port)
|
socket = TCPSocket.new(interface, current_port)
|
||||||
|
Loading…
Reference in New Issue
Block a user