buster 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
 - data/Gemfile +8 -0
 - data/README.md +36 -0
 - data/Rakefile +4 -0
 - data/buster.gemspec +23 -0
 - data/lib/buster.rb +40 -0
 - data/lib/buster/command_handler.rb +11 -0
 - data/lib/buster/context.rb +25 -0
 - data/lib/buster/host.rb +36 -0
 - data/lib/buster/poller.rb +40 -0
 - data/lib/buster/router.rb +34 -0
 - data/lib/buster/sender.rb +20 -0
 - data/lib/buster/version.rb +3 -0
 - data/lib/buster/worker.rb +49 -0
 - data/spec/integration_spec.rb +82 -0
 - data/spec/spec_helper.rb +51 -0
 - data/spec/test_endpoints/mars.rb +14 -0
 - data/spec/test_endpoints/pluto.rb +14 -0
 - data/spec/test_endpoints/station.rb +14 -0
 - metadata +97 -0
 
    
        data/.gitignore
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Buster
         
     | 
| 
      
 2 
     | 
    
         
            +
            ---
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            A Ruby Service Bus
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            License
         
     | 
| 
      
 7 
     | 
    
         
            +
            ---
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Copyright (c) 2012, Jason Staten, PeerIntel
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            All rights reserved.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Redistribution and use in source and binary forms, with or without
         
     | 
| 
      
 14 
     | 
    
         
            +
            modification, are permitted provided that the following conditions are met:
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            - Redistributions of source code must retain the above copyright notice, this
         
     | 
| 
      
 17 
     | 
    
         
            +
              list of conditions and the following disclaimer.
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            - Redistributions in binary form must reproduce the above copyright notice,
         
     | 
| 
      
 20 
     | 
    
         
            +
              this list of conditions and the following disclaimer in the documentation
         
     | 
| 
      
 21 
     | 
    
         
            +
              and/or other materials provided with the distribution.
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            - Neither the name of PeerIntel nor the names of its contributors may be used
         
     | 
| 
      
 24 
     | 
    
         
            +
              to endorse or promote products derived from this software without specific
         
     | 
| 
      
 25 
     | 
    
         
            +
              prior written permission.
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
         
     | 
| 
      
 28 
     | 
    
         
            +
            ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
         
     | 
| 
      
 29 
     | 
    
         
            +
            WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
         
     | 
| 
      
 30 
     | 
    
         
            +
            DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
         
     | 
| 
      
 31 
     | 
    
         
            +
            FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
         
     | 
| 
      
 32 
     | 
    
         
            +
            DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
         
     | 
| 
      
 33 
     | 
    
         
            +
            SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
         
     | 
| 
      
 34 
     | 
    
         
            +
            CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
         
     | 
| 
      
 35 
     | 
    
         
            +
            OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
         
     | 
| 
      
 36 
     | 
    
         
            +
            THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         
     | 
    
        data/Rakefile
    ADDED
    
    
    
        data/buster.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            $:.push File.expand_path("../lib", __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "buster/version"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.name        = "buster"
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.version     = Buster::VERSION
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.authors     = ["Jason Staten"]
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.email       = ["jstaten07@gmail.com"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.homepage    = ""
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.summary     = %q{Service Bus}
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.description = %q{Service Bus}
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              s.rubyforge_project = "buster"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              s.files         = `git ls-files`.split("\n")
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
         
     | 
| 
      
 18 
     | 
    
         
            +
              s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         
     | 
| 
      
 19 
     | 
    
         
            +
              s.require_paths = ["lib"]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              s.add_runtime_dependency "ffi-rzmq"
         
     | 
| 
      
 22 
     | 
    
         
            +
              s.add_runtime_dependency "msgpack"
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/buster.rb
    ADDED
    
    | 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            %w{host sender worker poller command_handler router context version}.each { |r| require "buster/#{r}" }
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'ffi-rzmq'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'msgpack'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Buster
         
     | 
| 
      
 7 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_accessor :local_endpoint
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def routes
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @routes ||= {}
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def start
         
     | 
| 
      
 15 
     | 
    
         
            +
                  raise "Bus is already started" if @host
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @host = Buster::Host.new(routes, context, self.local_endpoint)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @host.start
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def stop
         
     | 
| 
      
 21 
     | 
    
         
            +
                  raise "Bus is not running" unless @host
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @host.stop
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @host = nil
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def fire(name, props = {})
         
     | 
| 
      
 27 
     | 
    
         
            +
                  sender.fire(name, props)
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                private
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def sender
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @sender ||= Buster::Sender.new(context)
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def context
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @context ||= Buster::Context.new(ZMQ::Context.create)
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Buster
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Context
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                attr_accessor :context
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize(context)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @context = context
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @sockets = []
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def socket(type)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  socket = @context.socket(type)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @sockets << socket
         
     | 
| 
      
 14 
     | 
    
         
            +
                  socket
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def terminate
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @sockets.reverse.each do |s|
         
     | 
| 
      
 19 
     | 
    
         
            +
                    s.setsockopt(ZMQ::LINGER, 0)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    s.close
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @context.terminate
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/buster/host.rb
    ADDED
    
    | 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Buster
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Host
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize(routes, context, local_endpoint = nil)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @local_endpoint = local_endpoint ||"inproc://local_endpoint"
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @context = context
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @router = Buster::Router.new(@context, routes)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @poller = Buster::Poller.new
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def start
         
     | 
| 
      
 12 
     | 
    
         
            +
                  frontend = @context.socket(ZMQ::ROUTER)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  frontend.bind(@local_endpoint)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  backend = @context.socket(ZMQ::DEALER)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  backend.bind("inproc://workers")
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  @router.connect_routes backend, @poller
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  Buster::Worker.start_worker @context
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  @poller.pipe frontend, backend
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @poller.pipe backend, frontend
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  poll_thread = Thread.new { @poller.start }
         
     | 
| 
      
 26 
     | 
    
         
            +
                  poll_thread.join
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  @context.terminate
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def stop
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @poller.stop
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Buster
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Poller
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 4 
     | 
    
         
            +
                  @poller = ZMQ::Poller.new
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def start
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @run = true
         
     | 
| 
      
 9 
     | 
    
         
            +
                  while @run
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @poller.poll(500)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @poller.readables.each do |socket|
         
     | 
| 
      
 12 
     | 
    
         
            +
                      action = @readable_actions[socket]
         
     | 
| 
      
 13 
     | 
    
         
            +
                      action.call(socket) if action
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def stop
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @run = false
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def register(socket, &block)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @poller.register(socket, ZMQ::POLLIN)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  readable_actions[socket] = block
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def pipe(incoming, outgoing)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  register(incoming) do |s|
         
     | 
| 
      
 29 
     | 
    
         
            +
                    s.recv_strings(msgs = [])
         
     | 
| 
      
 30 
     | 
    
         
            +
                    outgoing.send_strings(msgs, ZMQ::NOBLOCK)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                private
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def readable_actions
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @readable_actions ||= {}
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Buster
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Router
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize(context, routes = {})
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @context = context
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @routes = routes
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def connect_routes(reply_socket, poller)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  local = @context.socket(ZMQ::DEALER)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  local.bind("inproc://routes")
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  sockets = @routes.map do |pattern, uri|
         
     | 
| 
      
 14 
     | 
    
         
            +
                    remote = @context.socket(ZMQ::DEALER)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    result = remote.connect(uri)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    poller.pipe remote, reply_socket
         
     | 
| 
      
 18 
     | 
    
         
            +
                    [pattern, remote]
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  poller.register(local) do |s|
         
     | 
| 
      
 22 
     | 
    
         
            +
                    s.recv_strings(msgs = [])
         
     | 
| 
      
 23 
     | 
    
         
            +
                    message_name = msgs[0]
         
     | 
| 
      
 24 
     | 
    
         
            +
                    #TODO: More robust routing
         
     | 
| 
      
 25 
     | 
    
         
            +
                    remote = sockets.detect([nil,nil]){|x| x[0].match message_name}[1]
         
     | 
| 
      
 26 
     | 
    
         
            +
                    if remote.nil?
         
     | 
| 
      
 27 
     | 
    
         
            +
                      puts "No remote matching '#{message_name}'"
         
     | 
| 
      
 28 
     | 
    
         
            +
                      return
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                    remote.send_strings(msgs)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Buster
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Sender
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(context)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  @context = context
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def fire(name, props = {})
         
     | 
| 
      
 8 
     | 
    
         
            +
                  bin = MessagePack.pack(props)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  sender.send_strings([name.to_s, bin])
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                private
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def sender
         
     | 
| 
      
 15 
     | 
    
         
            +
                  s = @context.socket(ZMQ::DEALER)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  s.connect("inproc://routes")
         
     | 
| 
      
 17 
     | 
    
         
            +
                  s
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,49 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Buster
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Worker
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(context)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  @context = context
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def run
         
     | 
| 
      
 8 
     | 
    
         
            +
                  worker = @context.socket(ZMQ::DEALER)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  worker.connect("inproc://workers")
         
     | 
| 
      
 10 
     | 
    
         
            +
                  while true
         
     | 
| 
      
 11 
     | 
    
         
            +
                    worker.recv_strings(msgs = [])
         
     | 
| 
      
 12 
     | 
    
         
            +
                    return if msgs.length < 2
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    body = MessagePack.unpack(msgs.pop)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    message_name = msgs.pop
         
     | 
| 
      
 16 
     | 
    
         
            +
                    reply_id = msgs.pop
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    handler = find_handler message_name
         
     | 
| 
      
 19 
     | 
    
         
            +
                    if handler.nil?
         
     | 
| 
      
 20 
     | 
    
         
            +
                      puts "No handler found for #{message_name}"
         
     | 
| 
      
 21 
     | 
    
         
            +
                      return
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    handler.reply_action = lambda do |name,props|
         
     | 
| 
      
 25 
     | 
    
         
            +
                      worker.send_strings([reply_id, name.to_s, MessagePack.pack(props)])
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    handler.execute body
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  worker.close
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def self.start_worker(context)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  worker = Worker.new(context)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  t = Thread.new { worker.run }
         
     | 
| 
      
 37 
     | 
    
         
            +
                  t.run
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                private
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def find_handler(name)
         
     | 
| 
      
 43 
     | 
    
         
            +
                 camelized = name.split(/[^a-z0-9]/i).map{|w| w.capitalize}.join
         
     | 
| 
      
 44 
     | 
    
         
            +
                 const_name = "#{camelized}Handler"
         
     | 
| 
      
 45 
     | 
    
         
            +
                 Object.const_get(const_name).new if Object.const_defined?(const_name)
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe 'integration' do
         
     | 
| 
      
 4 
     | 
    
         
            +
              before :all do
         
     | 
| 
      
 5 
     | 
    
         
            +
                start_endpoint :mars
         
     | 
| 
      
 6 
     | 
    
         
            +
                start_endpoint :pluto
         
     | 
| 
      
 7 
     | 
    
         
            +
                Buster.local_endpoint = 'ipc://earth.ipc'
         
     | 
| 
      
 8 
     | 
    
         
            +
                Buster.routes[/mars/] = 'ipc://mars.ipc'
         
     | 
| 
      
 9 
     | 
    
         
            +
                Buster.routes[/pluto/] = 'ipc://pluto.ipc'
         
     | 
| 
      
 10 
     | 
    
         
            +
                Buster.routes[/station/] = 'ipc://station.ipc'
         
     | 
| 
      
 11 
     | 
    
         
            +
                Thread.new { Buster.start }
         
     | 
| 
      
 12 
     | 
    
         
            +
                sleep 1 #bus startup delay
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              after :all do
         
     | 
| 
      
 16 
     | 
    
         
            +
                Buster.stop
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              let(:mutex) { Mutex.new }
         
     | 
| 
      
 20 
     | 
    
         
            +
              let(:baton) { ConditionVariable.new }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              describe 'when sending a hello_mars' do
         
     | 
| 
      
 23 
     | 
    
         
            +
                before do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  Handler 'HelloEarth' do |props|
         
     | 
| 
      
 25 
     | 
    
         
            +
                    mutex.synchronize do
         
     | 
| 
      
 26 
     | 
    
         
            +
                      @response = props['name']
         
     | 
| 
      
 27 
     | 
    
         
            +
                      baton.signal
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                it 'should respond in the mars uppercase style' do
         
     | 
| 
      
 33 
     | 
    
         
            +
                  name = 'Major Tom'
         
     | 
| 
      
 34 
     | 
    
         
            +
                  Buster.fire :hello_mars, :name => name
         
     | 
| 
      
 35 
     | 
    
         
            +
                  mutex.synchronize do
         
     | 
| 
      
 36 
     | 
    
         
            +
                    baton.wait(mutex, 1)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @response.should == name.upcase
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              describe 'when sending a hello_pluto' do
         
     | 
| 
      
 43 
     | 
    
         
            +
                before do
         
     | 
| 
      
 44 
     | 
    
         
            +
                  Handler 'HelloEarth' do |props|
         
     | 
| 
      
 45 
     | 
    
         
            +
                    mutex.synchronize do
         
     | 
| 
      
 46 
     | 
    
         
            +
                      @response = props['name']
         
     | 
| 
      
 47 
     | 
    
         
            +
                      baton.signal
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                it 'should respond in the pluto reversed style' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                  name = 'Ground Control'
         
     | 
| 
      
 54 
     | 
    
         
            +
                  Buster.fire :hello_pluto, :name => name
         
     | 
| 
      
 55 
     | 
    
         
            +
                  mutex.synchronize do
         
     | 
| 
      
 56 
     | 
    
         
            +
                    baton.wait(mutex, 1)
         
     | 
| 
      
 57 
     | 
    
         
            +
                    @response.should == name.reverse
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              describe 'when sending to a powered down space station' do
         
     | 
| 
      
 63 
     | 
    
         
            +
                before do
         
     | 
| 
      
 64 
     | 
    
         
            +
                  Handler 'TenFour' do |props|
         
     | 
| 
      
 65 
     | 
    
         
            +
                    mutex.synchronize do
         
     | 
| 
      
 66 
     | 
    
         
            +
                      @ten_foured = true
         
     | 
| 
      
 67 
     | 
    
         
            +
                      baton.signal
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                it 'should receive response when the station powers up' do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  Buster.fire :adjust_station_temperature
         
     | 
| 
      
 74 
     | 
    
         
            +
                  sleep 1 #Oh no! Station isn't started!
         
     | 
| 
      
 75 
     | 
    
         
            +
                  start_endpoint :station
         
     | 
| 
      
 76 
     | 
    
         
            +
                  mutex.synchronize do
         
     | 
| 
      
 77 
     | 
    
         
            +
                    baton.wait(mutex, 1)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    @ten_foured.should == true
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'bundler/setup'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            $:.unshift File.expand_path('../../lib', __FILE__)
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'buster'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Bundler.require :development
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Dir[File.join(File.dirname(__FILE__), 'support', '*.rb')].each { |d| require d }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            Thread.abort_on_exception = true
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            $endpoint_pids = []
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            RSpec.configure do |config|
         
     | 
| 
      
 16 
     | 
    
         
            +
              config.mock_with :rspec
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              config.after(:all) do
         
     | 
| 
      
 19 
     | 
    
         
            +
                $endpoint_pids.each { |p| Process.kill("TERM", p) }
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            def Handler(name, &block)
         
     | 
| 
      
 24 
     | 
    
         
            +
              const_name = "#{name}Handler"
         
     | 
| 
      
 25 
     | 
    
         
            +
              if Object.const_defined?(const_name)
         
     | 
| 
      
 26 
     | 
    
         
            +
                klass = Object.const_get(const_name)
         
     | 
| 
      
 27 
     | 
    
         
            +
              else
         
     | 
| 
      
 28 
     | 
    
         
            +
                klass = Class.new do
         
     | 
| 
      
 29 
     | 
    
         
            +
                  include Buster::CommandHandler
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def execute(props)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @@execute_action.call(props,self)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def self.execute_action=(action)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @@execute_action = action
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
                Object.const_set(const_name, klass)
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              klass.execute_action = block
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              klass
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            def start_endpoint(name)
         
     | 
| 
      
 48 
     | 
    
         
            +
              pid =  Process.spawn("ruby #{File.join(File.dirname(__FILE__),'test_endpoints', "#{name}.rb")}")
         
     | 
| 
      
 49 
     | 
    
         
            +
              $endpoint_pids << pid
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path('../../spec_helper.rb', __FILE__)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class HelloMarsHandler
         
     | 
| 
      
 4 
     | 
    
         
            +
              include Buster::CommandHandler
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def execute(props)
         
     | 
| 
      
 7 
     | 
    
         
            +
                reply :hello_earth, 'name' => props['name'].upcase
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            trap("TERM") { Buster.stop }
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Buster.local_endpoint = 'ipc://mars.ipc'
         
     | 
| 
      
 14 
     | 
    
         
            +
            Buster.start
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path('../../spec_helper.rb', __FILE__)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class HelloPlutoHandler
         
     | 
| 
      
 4 
     | 
    
         
            +
              include Buster::CommandHandler
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def execute(props)
         
     | 
| 
      
 7 
     | 
    
         
            +
                reply :hello_earth, 'name' => props['name'].reverse
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            trap("TERM") { Buster.stop }
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Buster.local_endpoint = 'ipc://pluto.ipc'
         
     | 
| 
      
 14 
     | 
    
         
            +
            Buster.start
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path('../../spec_helper.rb', __FILE__)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class AdjustStationTemperatureHandler
         
     | 
| 
      
 4 
     | 
    
         
            +
              include Buster::CommandHandler
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def execute(props)
         
     | 
| 
      
 7 
     | 
    
         
            +
                reply :ten_four
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            trap("TERM") { Buster.stop }
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Buster.local_endpoint = 'ipc://station.ipc'
         
     | 
| 
      
 14 
     | 
    
         
            +
            Buster.start
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,97 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: buster
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.1
         
     | 
| 
      
 5 
     | 
    
         
            +
              prerelease: 
         
     | 
| 
      
 6 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 7 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 8 
     | 
    
         
            +
            - Jason Staten
         
     | 
| 
      
 9 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 10 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 11 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2012-01-13 00:00:00.000000000Z
         
     | 
| 
      
 13 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 14 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 15 
     | 
    
         
            +
              name: ffi-rzmq
         
     | 
| 
      
 16 
     | 
    
         
            +
              requirement: &11559360 !ruby/object:Gem::Requirement
         
     | 
| 
      
 17 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 18 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 19 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 20 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 21 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 22 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 23 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 24 
     | 
    
         
            +
              version_requirements: *11559360
         
     | 
| 
      
 25 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 26 
     | 
    
         
            +
              name: msgpack
         
     | 
| 
      
 27 
     | 
    
         
            +
              requirement: &11558760 !ruby/object:Gem::Requirement
         
     | 
| 
      
 28 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 29 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 30 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 31 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 32 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 33 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 34 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 35 
     | 
    
         
            +
              version_requirements: *11558760
         
     | 
| 
      
 36 
     | 
    
         
            +
            description: Service Bus
         
     | 
| 
      
 37 
     | 
    
         
            +
            email:
         
     | 
| 
      
 38 
     | 
    
         
            +
            - jstaten07@gmail.com
         
     | 
| 
      
 39 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 40 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 41 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 42 
     | 
    
         
            +
            files:
         
     | 
| 
      
 43 
     | 
    
         
            +
            - .gitignore
         
     | 
| 
      
 44 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 45 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 46 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 47 
     | 
    
         
            +
            - buster.gemspec
         
     | 
| 
      
 48 
     | 
    
         
            +
            - lib/buster.rb
         
     | 
| 
      
 49 
     | 
    
         
            +
            - lib/buster/command_handler.rb
         
     | 
| 
      
 50 
     | 
    
         
            +
            - lib/buster/context.rb
         
     | 
| 
      
 51 
     | 
    
         
            +
            - lib/buster/host.rb
         
     | 
| 
      
 52 
     | 
    
         
            +
            - lib/buster/poller.rb
         
     | 
| 
      
 53 
     | 
    
         
            +
            - lib/buster/router.rb
         
     | 
| 
      
 54 
     | 
    
         
            +
            - lib/buster/sender.rb
         
     | 
| 
      
 55 
     | 
    
         
            +
            - lib/buster/version.rb
         
     | 
| 
      
 56 
     | 
    
         
            +
            - lib/buster/worker.rb
         
     | 
| 
      
 57 
     | 
    
         
            +
            - spec/integration_spec.rb
         
     | 
| 
      
 58 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 59 
     | 
    
         
            +
            - spec/test_endpoints/mars.rb
         
     | 
| 
      
 60 
     | 
    
         
            +
            - spec/test_endpoints/pluto.rb
         
     | 
| 
      
 61 
     | 
    
         
            +
            - spec/test_endpoints/station.rb
         
     | 
| 
      
 62 
     | 
    
         
            +
            homepage: ''
         
     | 
| 
      
 63 
     | 
    
         
            +
            licenses: []
         
     | 
| 
      
 64 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 65 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 66 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 67 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 68 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 69 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 70 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 71 
     | 
    
         
            +
              - - ! '>='
         
     | 
| 
      
 72 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 73 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 74 
     | 
    
         
            +
                  segments:
         
     | 
| 
      
 75 
     | 
    
         
            +
                  - 0
         
     | 
| 
      
 76 
     | 
    
         
            +
                  hash: 1543500698659680995
         
     | 
| 
      
 77 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 78 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 79 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 80 
     | 
    
         
            +
              - - ! '>='
         
     | 
| 
      
 81 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 82 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 83 
     | 
    
         
            +
                  segments:
         
     | 
| 
      
 84 
     | 
    
         
            +
                  - 0
         
     | 
| 
      
 85 
     | 
    
         
            +
                  hash: 1543500698659680995
         
     | 
| 
      
 86 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 87 
     | 
    
         
            +
            rubyforge_project: buster
         
     | 
| 
      
 88 
     | 
    
         
            +
            rubygems_version: 1.8.13
         
     | 
| 
      
 89 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 90 
     | 
    
         
            +
            specification_version: 3
         
     | 
| 
      
 91 
     | 
    
         
            +
            summary: Service Bus
         
     | 
| 
      
 92 
     | 
    
         
            +
            test_files:
         
     | 
| 
      
 93 
     | 
    
         
            +
            - spec/integration_spec.rb
         
     | 
| 
      
 94 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 95 
     | 
    
         
            +
            - spec/test_endpoints/mars.rb
         
     | 
| 
      
 96 
     | 
    
         
            +
            - spec/test_endpoints/pluto.rb
         
     | 
| 
      
 97 
     | 
    
         
            +
            - spec/test_endpoints/station.rb
         
     |