<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -11,78 +11,75 @@ require &quot;testjour/result&quot;
 
 module Testjour
 module Commands
-    
+
   class Run &lt; Command
-    
+
     def execute
       configuration.unshift_args(testjour_yml_args)
       configuration.parse!
-      
-      HttpQueue.with_queue_server do
-        configuration.setup
-        
-        if configuration.feature_files.any?
-          queue_features
-          
-          @started_slaves = 0
-          start_slaves
-          
-          puts &quot;Requested build from #{@started_slaves} slaves... (Waiting for #{step_counter.count} results)&quot;
-          puts
-          
-          print_results
-        else
-          Testjour.logger.info(&quot;No feature files. Quitting.&quot;)
-        end
+      configuration.setup
+
+      if configuration.feature_files.any?
+        RedisQueue.reset_all
+        queue_features
+
+        @started_slaves = 0
+        start_slaves
+
+        puts &quot;Requested build from #{@started_slaves} slaves... (Waiting for #{step_counter.count} results)&quot;
+        puts
+
+        print_results
+      else
+        Testjour.logger.info(&quot;No feature files. Quitting.&quot;)
       end
     end
-    
+
     def queue_features
       Testjour.logger.info(&quot;Queuing features...&quot;)
-      
-      HttpQueue.with_queue(queue_uri) do |queue|
-        configuration.feature_files.each do |feature_file|
-          queue.push(:feature_files, feature_file)
-          Testjour.logger.info &quot;Queued: #{feature_file}&quot;
-        end
+      queue = RedisQueue.new
+
+      configuration.feature_files.each do |feature_file|
+        queue.push(:feature_files, feature_file)
+        Testjour.logger.info &quot;Queued: #{feature_file}&quot;
       end
     end
-    
+
     def start_slaves
       start_local_slaves
       start_remote_slaves
     end
-    
+
     def start_local_slaves
       configuration.local_slave_count.times do
         @started_slaves += 1
         start_slave
       end
     end
-    
+
     def start_remote_slaves
       configuration.remote_slaves.each do |remote_slave|
         @started_slaves += 1
         start_remote_slave(remote_slave)
       end
     end
-    
+
     def start_remote_slave(remote_slave)
       uri = URI.parse(remote_slave)
       cmd = remote_slave_run_command(uri.host, uri.path)
       Testjour.logger.info &quot;Starting remote slave: #{cmd}&quot;
       detached_exec(cmd)
     end
-    
+
     def remote_slave_run_command(host, path)
       &quot;ssh #{host} testjour run:remote --in=#{path} #{configuration.run_slave_args.join(' ')} #{testjour_uri}&quot;.squeeze(&quot; &quot;)
     end
-    
+
     def start_slave
       Testjour.logger.info &quot;Starting slave: #{local_run_command}&quot;
       detached_exec(local_run_command)
     end
-    
+
     def testjour_yml_args
       @testjour_yml_args ||= begin
         if File.exist?(&quot;testjour.yml&quot;)
@@ -92,62 +89,52 @@ module Commands
         end
       end
     end
-    
+
     def print_results
       results_formatter = ResultsFormatter.new(step_counter, configuration.options)
-      
-      HttpQueue.with_queue(queue_uri) do |queue|
-        step_counter.count.times do
-          results_formatter.result(queue.pop(:results))
+      queue = RedisQueue.new
+      results_count = 0
+
+      Timeout.timeout(180) do
+        while results_count &lt; step_counter.count
+          if (result = queue.pop(:results))
+            results_formatter.result(result)
+            results_count += 1
+          else
+            sleep 0.1
+          end
         end
       end
-      
+
       results_formatter.finish
-      
       return results_formatter.failed? ? 1 : 0
-    rescue =&gt; ex
-      if ex.message =~ /result overdue/
-        $stderr.puts
-        $stderr.puts &quot;Missing steps:&quot;
-        $stderr.puts
-        results_formatter.missing_backtrace_lines.each do |line|
-          $stderr.puts &quot;    #{line}&quot;
-        end
-        $stderr.puts
-      end
-      
-      raise
     end
-    
+
     def step_counter
       return @step_counter if @step_counter
-      
+
       features = load_plain_text_features(configuration.feature_files)
       @step_counter = Testjour::StepCounter.new(step_mother)
       @step_counter.options = configuration.cucumber_configuration.options
       @step_counter.visit_features(features)
       return @step_counter
     end
-    
+
     def local_run_command
       &quot;testjour run:slave #{configuration.run_slave_args.join(' ')} #{testjour_uri}&quot;.squeeze(&quot; &quot;)
     end
-    
-    def queue_uri
-      &quot;http://localhost:#{Testjour::HttpQueue.port}/&quot;
-    end
-    
+
     def testjour_uri
       user = `whoami`.strip
       host = Socket.gethostname
-      &quot;http://#{user}@#{host}:#{Testjour::HttpQueue.port}&quot; + File.expand_path(&quot;.&quot;)
+      &quot;http://#{user}@#{host}&quot; + File.expand_path(&quot;.&quot;)
     end
-    
+
     def testjour_path
       File.expand_path(File.dirname(__FILE__) + &quot;/../../../bin/testjour&quot;)
     end
-    
+
   end
-  
+
 end
 end
\ No newline at end of file</diff>
      <filename>lib/testjour/commands/run.rb</filename>
    </modified>
    <modified>
      <diff>@@ -31,31 +31,30 @@ module Commands
     end
 
     def work
-      HttpQueue.with_queue(configuration.queue_uri) do |queue|
-        feature_file = true
+      queue = RedisQueue.new
+      feature_file = true
 
-        while feature_file
-          begin
-            feature_file = queue.pop(:feature_files)
-          rescue Curl::Err::ConnectionFailedError
-            feature_file = false
-          end
+      while feature_file
+        begin
+          feature_file = queue.pop(:feature_files)
+        rescue Curl::Err::ConnectionFailedError
+          feature_file = false
+        end
 
-          if feature_file
-            Testjour.logger.info &quot;Running: #{feature_file}&quot;
-            features = load_plain_text_features(feature_file)
-            Testjour.logger.info &quot;Loaded: #{feature_file}&quot;
-            execute_features(features)
-            Testjour.logger.info &quot;Finished running: #{feature_file}&quot;
-          else
-            Testjour.logger.info &quot;No feature file found. Finished&quot;
-          end
+        if feature_file
+          Testjour.logger.info &quot;Running: #{feature_file}&quot;
+          features = load_plain_text_features(feature_file)
+          Testjour.logger.info &quot;Loaded: #{feature_file}&quot;
+          execute_features(features)
+          Testjour.logger.info &quot;Finished running: #{feature_file}&quot;
+        else
+          Testjour.logger.info &quot;No feature file found. Finished&quot;
         end
       end
     end
 
     def execute_features(features)
-      visitor = Testjour::HttpFormatter.new(step_mother, StringIO.new, configuration.queue_uri)
+      visitor = Testjour::HttpFormatter.new(step_mother)
       visitor.options = configuration.cucumber_configuration.options
       Testjour.logger.info &quot;Visiting...&quot;
       visitor.visit_features(features)</diff>
      <filename>lib/testjour/commands/run_slave.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,11 +7,6 @@ module Testjour
 
   class HttpFormatter &lt; ::Cucumber::Ast::Visitor
 
-    def initialize(step_mother, io, queue_uri)
-      super(step_mother)
-      @queue_uri = queue_uri
-    end
-
     def visit_multiline_arg(multiline_arg)
       @multiline_arg = true
       super
@@ -36,9 +31,8 @@ module Testjour
   private
 
     def progress(time, step_invocation, status = nil)
-      HttpQueue.with_queue(@queue_uri) do |queue|
-        queue.push(:results, Result.new(time, step_invocation, status))
-      end
+      queue = RedisQueue.new
+      queue.push(:results, Result.new(time, step_invocation, status))
     end
 
   end</diff>
      <filename>lib/testjour/cucumber_extensions/http_formatter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,191 +1,32 @@
 require &quot;testjour/core_extensions/wait_for_service&quot;
-require &quot;curb&quot;
+require &quot;redis&quot;
 
 module Testjour
-  class HttpQueue
-    class ResultOverdueError &lt; StandardError; end
-    
-    class QueueProxy
-      
-      def initialize(uri = nil)
-        @uri = uri
-      end
-      
-      def uri
-        @uri || &quot;http://0.0.0.0:#{Testjour::HttpQueue.port}/&quot;
-      end
-      
-      def push(queue_name, data)
-        c = Curl::Easy.http_post(uri + queue_name.to_s,
-          Curl::PostField.content(&quot;data&quot;,  Marshal.dump(data)))
-          
-        c.response_code == 200
-      end
-      
-      def pop(queue_name)
-        c = Curl::Easy.new(uri + queue_name.to_s)
-        c.perform
-        
-        if c.response_code == 200
-          return Marshal.load(c.body_str)
-        elsif c.response_code == 404
-          return nil
-        else
-          raise &quot;Bad response: #{c.body_str}&quot;
-        end
-      end
-      
-    protected
-    
-      def self.with_net_http(&amp;block)
-        Net::HTTP.start(&quot;0.0.0.0&quot;, HttpQueue.port, &amp;block)
-      end
-      
-    end
-    
-    def self.timeout_in_seconds
-      180
-    end
-    
-    def self.run_on(handler)
-      handler.run self, :Port =&gt; port
-    end
-    
-    def self.wait_for_service
-      TCPSocket.wait_for_service :host =&gt; &quot;0.0.0.0&quot;, :port =&gt; port
-    end
-    
-    def self.wait_for_no_service
-      TCPSocket.wait_for_no_service :host =&gt; &quot;0.0.0.0&quot;, :port =&gt; port
-    end
-    
-    def self.with_queue(uri = nil, &amp;block)
-      yield QueueProxy.new(uri)
-    end
-    
-    def self.with_queue_server
-      existing_pid = `ps | grep httpq | grep -v grep`.strip.split.first
-      
-      if existing_pid
-        Testjour.logger.info &quot;Killing running httpq PID #{existing_pid}...&quot;
-        Process.kill(9, existing_pid.to_i)
-        HttpQueue.wait_for_no_service
-      end
-      
-      Testjour.logger.info &quot;Starting httpq...&quot;
-      pid = detached_exec(File.expand_path(File.dirname(__FILE__) + &quot;/../../bin/httpq&quot;))
-      kill_at_exit(pid)
-      wait_for_service
-      
-      Testjour.logger.info &quot;Started httpq.&quot;
-      
-      yield
-    end
-    
-    def self.kill_at_exit(pid)
-      at_exit do
-        Process.kill(&quot;INT&quot;, pid)
-      end
-    end
-    
-    def self.port
-      15434
-    end
-    
-    def self.queues
-      @queues ||= {
-        :feature_files  =&gt; Queue.new,
-        :results        =&gt; Queue.new
-      }
-    end
 
-    def self.call(env)
-      new(env).call
-    end
-  
-    def initialize(env)
-      @request = Rack::Request.new(env)
-    end
-  
-    def call
-      if request.post?
-        handle_post
-      else
-        handle_get
-      end
-    end
-  
-  protected
-  
-    def request
-      @request
-    end
-  
-    def handle_get
-      case request.path_info
-      when &quot;/reset&quot;         then reset
-      when &quot;/feature_files&quot; then pop(:feature_files)
-      when &quot;/results&quot;       then pop(:results, false)
-      else error(&quot;unknown path: #{request.path_info}&quot;)
-      end
-    end
-  
-    def handle_post
-      case request.path_info
-      when &quot;/feature_files&quot; then push(:feature_files)
-      when &quot;/results&quot;       then push(:results)
-      else error(&quot;unknown path: #{request.path_info}&quot;)
-      end
-    end
-  
-    def reset
-      self.class.queues.each do |name, queue|
-        queue.clear
-      end
-      
-      ok
-    end
-  
-    def pop(queue_name, non_block = true)
-      data = nil
-      
-      begin
-        data = Timeout.timeout(self.class.timeout_in_seconds, ResultOverdueError) do
-          queue(queue_name).pop(non_block)
-        end
-      rescue ResultOverdueError
-        return error(&quot;result overdue&quot;)
-      end
-      
-      [200, { &quot;Content-Type&quot; =&gt; &quot;text/plain&quot; }, data]
-    rescue ThreadError =&gt; ex
-      if ex.message =~ /queue empty/
-        missing
-      else
-        error(&quot;uncaught exception&quot;)
-      end
-    end
-  
-    def push(queue_name)
-      queue(queue_name).push(request.POST[&quot;data&quot;])
-      ok
+  class RedisQueue
+
+    def self.reset_all
+      redis.del &quot;testjour:feature_files&quot;
+      redis.del &quot;testjour:results&quot;
     end
-  
-    def queue(name)
-      self.class.queues[name]
+
+    def self.redis
+      @redis ||= Redis.new
     end
-    
-    def ok
-      [200, { &quot;Content-Type&quot; =&gt; &quot;text/plain&quot; }, &quot;OK&quot;]
+
+    def redis
+      self.class.redis
     end
-  
-    def missing
-      [404, { &quot;Content-Type&quot; =&gt; &quot;text/plain&quot; }, &quot;Not Found&quot;]
+
+    def push(queue_name, data)
+      redis.lpush(&quot;testjour:#{queue_name}&quot;, Marshal.dump(data))
     end
-  
-    def error(message = nil)
-      [500, { &quot;Content-Type&quot; =&gt; &quot;text/plain&quot; }, &quot;Server error: #{message}&quot;]
+
+    def pop(queue_name)
+      result = redis.rpop(&quot;testjour:#{queue_name}&quot;)
+      result ? Marshal.load(result) : nil
     end
-  
+
   end
+
 end
\ No newline at end of file</diff>
      <filename>lib/testjour/http_queue.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>bin/httpq</filename>
    </removed>
    <removed>
      <filename>spec/httpq_spec.rb</filename>
    </removed>
    <removed>
      <filename>spec/spec_helper.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>f0902bff629742fdcf72b3f88af0e56d47beecfd</id>
    </parent>
  </parents>
  <author>
    <name>Bryan Helmkamp</name>
    <email>bryan@brynary.com</email>
  </author>
  <url>http://github.com/brynary/testjour/commit/4ab92d077e68c25e30704378a0b3121fca437d65</url>
  <id>4ab92d077e68c25e30704378a0b3121fca437d65</id>
  <committed-date>2009-09-14T12:02:18-07:00</committed-date>
  <authored-date>2009-09-14T11:58:25-07:00</authored-date>
  <message>Swapping out httpq for Redis</message>
  <tree>293d4fb11665d0dc354f2d7cfa0c680aee765f0f</tree>
  <committer>
    <name>Bryan Helmkamp</name>
    <email>bryan@brynary.com</email>
  </committer>
</commit>
