puggernaut 0.1.0
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/LICENSE +18 -0
 - data/README.md +93 -0
 - data/Rakefile +90 -0
 - data/bin/puggernaut +5 -0
 - data/config.ru +3 -0
 - data/config/gemsets.yml +5 -0
 - data/config/gemspec.yml +11 -0
 - data/lib/puggernaut.rb +14 -0
 - data/lib/puggernaut/client.rb +66 -0
 - data/lib/puggernaut/gems.rb +154 -0
 - data/lib/puggernaut/logger.rb +25 -0
 - data/lib/puggernaut/server.rb +44 -0
 - data/lib/puggernaut/server/channel.rb +70 -0
 - data/lib/puggernaut/server/http.rb +73 -0
 - data/lib/puggernaut/server/tcp.rb +19 -0
 - data/lib/puggernaut/spec_server.rb +66 -0
 - data/public/jquery.js +7179 -0
 - data/public/puggernaut.js +95 -0
 - data/public/qunit.css +196 -0
 - data/public/qunit.js +1415 -0
 - data/public/spec.html +17 -0
 - data/public/spec.js +95 -0
 - data/puggernaut.gemspec +32 -0
 - data/puggernaut.png +0 -0
 - data/spec/fixtures/gemsets.yml +9 -0
 - data/spec/fixtures/gemspec.yml +15 -0
 - data/spec/puggernaut/gems_spec.rb +249 -0
 - data/spec/puggernaut_spec.rb +4 -0
 - data/spec/spec_helper.rb +11 -0
 - metadata +115 -0
 
    
        data/.gitignore
    ADDED
    
    
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2010
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy of 
         
     | 
| 
      
 4 
     | 
    
         
            +
            this software and associated documentation files (the "Software"), to deal in 
         
     | 
| 
      
 5 
     | 
    
         
            +
            the Software without restriction, including without limitation the rights to 
         
     | 
| 
      
 6 
     | 
    
         
            +
            use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 
         
     | 
| 
      
 7 
     | 
    
         
            +
            the Software, and to permit persons to whom the Software is furnished to do so, 
         
     | 
| 
      
 8 
     | 
    
         
            +
            subject to the following conditions:
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all 
         
     | 
| 
      
 11 
     | 
    
         
            +
            copies or substantial portions of the Software.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
         
     | 
| 
      
 14 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
         
     | 
| 
      
 15 
     | 
    
         
            +
            FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
         
     | 
| 
      
 16 
     | 
    
         
            +
            COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
         
     | 
| 
      
 17 
     | 
    
         
            +
            IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
         
     | 
| 
      
 18 
     | 
    
         
            +
            CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,93 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Puggernaut
         
     | 
| 
      
 2 
     | 
    
         
            +
            ==========
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            Simple server push implementation using eventmachine and long polling.
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Requirements
         
     | 
| 
      
 9 
     | 
    
         
            +
            ------------
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            <pre>
         
     | 
| 
      
 12 
     | 
    
         
            +
            gem install puggernaut
         
     | 
| 
      
 13 
     | 
    
         
            +
            </pre>
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            How it works
         
     | 
| 
      
 16 
     | 
    
         
            +
            ------------
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            Puggernaut consists of three pieces:
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            * TCP client to send push messages
         
     | 
| 
      
 21 
     | 
    
         
            +
            * TCP server to receive push messages
         
     | 
| 
      
 22 
     | 
    
         
            +
            * HTTP server to deliver long poll requests
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            Start it up
         
     | 
| 
      
 25 
     | 
    
         
            +
            -----------
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            Run the <code>puggernaut</code> binary with optional port numbers:
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            <pre>
         
     | 
| 
      
 30 
     | 
    
         
            +
            puggernaut <http port> <tcp port>
         
     | 
| 
      
 31 
     | 
    
         
            +
            </pre>
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            The default HTTP and TCP ports are 8000 and 8001, respectively.
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            Set up proxy pass
         
     | 
| 
      
 36 
     | 
    
         
            +
            -----------------
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            You will need to set up a URL on your public facing web server that points to the Puggernaut HTTP server.
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            If you do not see your web server below, [Google](http://google.com) is your friend.
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            ### Apache
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            *http.conf*
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            <pre>
         
     | 
| 
      
 47 
     | 
    
         
            +
            ProxyPass /long_poll http://localhost:8000/
         
     | 
| 
      
 48 
     | 
    
         
            +
            ProxyPassReverse /long_poll http://localhost:8000/
         
     | 
| 
      
 49 
     | 
    
         
            +
            </pre>
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            ### Nginx
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            *nginx.conf*
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            <pre>
         
     | 
| 
      
 56 
     | 
    
         
            +
            location /long_poll {
         
     | 
| 
      
 57 
     | 
    
         
            +
              proxy_pass http://localhost:8000/;
         
     | 
| 
      
 58 
     | 
    
         
            +
            }
         
     | 
| 
      
 59 
     | 
    
         
            +
            </pre>
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            Send push messages
         
     | 
| 
      
 62 
     | 
    
         
            +
            ------------------
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            <pre>
         
     | 
| 
      
 65 
     | 
    
         
            +
            require 'puggernaut'
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            client = Puggernaut::Client.new("localhost:8001", "localhost:9001")
         
     | 
| 
      
 68 
     | 
    
         
            +
            client.push :channel => "message"
         
     | 
| 
      
 69 
     | 
    
         
            +
            client.push :channel => [ "message 1", "message 2" ], :channel_2 => "message"
         
     | 
| 
      
 70 
     | 
    
         
            +
            </pre>
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            The <code>Client.new</code> initializer accepts any number of TCP server addresses.
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            Receive push messages
         
     | 
| 
      
 75 
     | 
    
         
            +
            ---------------------
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            Include [puggernaut.js](/winton/puggernaut/public/puggernaut.js) into to your HTML page.
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            Javascript client example:
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            <pre>
         
     | 
| 
      
 82 
     | 
    
         
            +
            Puggernaut.path = '/long_poll';
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
            Puggernaut
         
     | 
| 
      
 85 
     | 
    
         
            +
              .watch('channel', function(e, message) {
         
     | 
| 
      
 86 
     | 
    
         
            +
                // do something with message
         
     | 
| 
      
 87 
     | 
    
         
            +
              })
         
     | 
| 
      
 88 
     | 
    
         
            +
              .watch('channel_2', function(e, message) {
         
     | 
| 
      
 89 
     | 
    
         
            +
                // do something with message
         
     | 
| 
      
 90 
     | 
    
         
            +
              });
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            Puggernaut.unwatch('channel');
         
     | 
| 
      
 93 
     | 
    
         
            +
            </pre>
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,90 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/lib/puggernaut/gems'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Puggernaut::Gems.activate %w(rake rspec)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require 'rake'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'spec/rake/spectask'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            def gemspec
         
     | 
| 
      
 9 
     | 
    
         
            +
              @gemspec ||= begin
         
     | 
| 
      
 10 
     | 
    
         
            +
                file = File.expand_path('../puggernaut.gemspec', __FILE__)
         
     | 
| 
      
 11 
     | 
    
         
            +
                eval(File.read(file), binding, file)
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            if defined?(Spec::Rake::SpecTask)
         
     | 
| 
      
 16 
     | 
    
         
            +
              desc "Run specs"
         
     | 
| 
      
 17 
     | 
    
         
            +
              Spec::Rake::SpecTask.new do |t|
         
     | 
| 
      
 18 
     | 
    
         
            +
                t.spec_files = FileList['spec/**/*_spec.rb']
         
     | 
| 
      
 19 
     | 
    
         
            +
                t.spec_opts = %w(-fs --color)
         
     | 
| 
      
 20 
     | 
    
         
            +
                t.warning = true
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
              task :spec
         
     | 
| 
      
 23 
     | 
    
         
            +
              task :default => :spec
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            desc "Build gem(s)"
         
     | 
| 
      
 27 
     | 
    
         
            +
            task :gem do
         
     | 
| 
      
 28 
     | 
    
         
            +
              old_gemset = ENV['GEMSET']
         
     | 
| 
      
 29 
     | 
    
         
            +
              root = File.expand_path('../', __FILE__)
         
     | 
| 
      
 30 
     | 
    
         
            +
              pkg = "#{root}/pkg"
         
     | 
| 
      
 31 
     | 
    
         
            +
              system "rm -Rf #{pkg}"
         
     | 
| 
      
 32 
     | 
    
         
            +
              Puggernaut::Gems.gemset_names.each do |gemset|
         
     | 
| 
      
 33 
     | 
    
         
            +
                ENV['GEMSET'] = gemset.to_s
         
     | 
| 
      
 34 
     | 
    
         
            +
                system "cd #{root} && gem build puggernaut.gemspec"
         
     | 
| 
      
 35 
     | 
    
         
            +
                system "mkdir -p #{pkg} && mv *.gem pkg"
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
              ENV['GEMSET'] = old_gemset
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            namespace :gem do
         
     | 
| 
      
 41 
     | 
    
         
            +
              desc "Install gem(s)"
         
     | 
| 
      
 42 
     | 
    
         
            +
              task :install do
         
     | 
| 
      
 43 
     | 
    
         
            +
                Rake::Task['gem'].invoke
         
     | 
| 
      
 44 
     | 
    
         
            +
                Dir["#{File.dirname(__FILE__)}/pkg/*.gem"].each do |pkg|
         
     | 
| 
      
 45 
     | 
    
         
            +
                  system "gem install #{pkg} --no-ri --no-rdoc"
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
              
         
     | 
| 
      
 49 
     | 
    
         
            +
              desc "Push gem(s)"
         
     | 
| 
      
 50 
     | 
    
         
            +
              task :push do
         
     | 
| 
      
 51 
     | 
    
         
            +
                Rake::Task['gem'].invoke
         
     | 
| 
      
 52 
     | 
    
         
            +
                Dir["#{File.dirname(__FILE__)}/pkg/*.gem"].each do |pkg|
         
     | 
| 
      
 53 
     | 
    
         
            +
                  system "gem push #{pkg}"
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
            end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            namespace :gems do
         
     | 
| 
      
 59 
     | 
    
         
            +
              desc "Install gem dependencies (DEV=0 DOCS=0 GEMSPEC=default SUDO=0)"
         
     | 
| 
      
 60 
     | 
    
         
            +
              task :install do
         
     | 
| 
      
 61 
     | 
    
         
            +
                dev = ENV['DEV'] == '1'
         
     | 
| 
      
 62 
     | 
    
         
            +
                docs = ENV['DOCS'] == '1' ? '' : '--no-ri --no-rdoc'
         
     | 
| 
      
 63 
     | 
    
         
            +
                gemset = ENV['GEMSET']
         
     | 
| 
      
 64 
     | 
    
         
            +
                sudo = ENV['SUDO'] == '1' ? 'sudo' : ''
         
     | 
| 
      
 65 
     | 
    
         
            +
                
         
     | 
| 
      
 66 
     | 
    
         
            +
                Puggernaut::Gems.gemset = gemset if gemset
         
     | 
| 
      
 67 
     | 
    
         
            +
                
         
     | 
| 
      
 68 
     | 
    
         
            +
                if dev
         
     | 
| 
      
 69 
     | 
    
         
            +
                  gems = Puggernaut::Gems.gemspec.development_dependencies
         
     | 
| 
      
 70 
     | 
    
         
            +
                else
         
     | 
| 
      
 71 
     | 
    
         
            +
                  gems = Puggernaut::Gems.gemspec.dependencies
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
                
         
     | 
| 
      
 74 
     | 
    
         
            +
                gems.each do |name|
         
     | 
| 
      
 75 
     | 
    
         
            +
                  name = name.to_s
         
     | 
| 
      
 76 
     | 
    
         
            +
                  version = Puggernaut::Gems.versions[name]
         
     | 
| 
      
 77 
     | 
    
         
            +
                  if Gem.source_index.find_name(name, version).empty?
         
     | 
| 
      
 78 
     | 
    
         
            +
                    version = version ? "-v #{version}" : ''
         
     | 
| 
      
 79 
     | 
    
         
            +
                    system "#{sudo} gem install #{name} #{version} #{docs}"
         
     | 
| 
      
 80 
     | 
    
         
            +
                  else
         
     | 
| 
      
 81 
     | 
    
         
            +
                    puts "already installed: #{name} #{version}"
         
     | 
| 
      
 82 
     | 
    
         
            +
                  end
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
            end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            desc "Validate the gemspec"
         
     | 
| 
      
 88 
     | 
    
         
            +
            task :gemspec do
         
     | 
| 
      
 89 
     | 
    
         
            +
              gemspec.validate
         
     | 
| 
      
 90 
     | 
    
         
            +
            end
         
     | 
    
        data/bin/puggernaut
    ADDED
    
    
    
        data/config.ru
    ADDED
    
    
    
        data/config/gemsets.yml
    ADDED
    
    
    
        data/config/gemspec.yml
    ADDED
    
    | 
         @@ -0,0 +1,11 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            name: puggernaut
         
     | 
| 
      
 2 
     | 
    
         
            +
            version: 0.1.0
         
     | 
| 
      
 3 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 4 
     | 
    
         
            +
              - Winton Welsh
         
     | 
| 
      
 5 
     | 
    
         
            +
            email: mail@wintoni.us
         
     | 
| 
      
 6 
     | 
    
         
            +
            homepage: http://github.com/winton/puggernaut
         
     | 
| 
      
 7 
     | 
    
         
            +
            summary: Simple server push implementation using eventmachine and long polling
         
     | 
| 
      
 8 
     | 
    
         
            +
            description: Simple server push implementation using eventmachine and long polling
         
     | 
| 
      
 9 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 10 
     | 
    
         
            +
              - eventmachine
         
     | 
| 
      
 11 
     | 
    
         
            +
            development_dependencies: null
         
     | 
    
        data/lib/puggernaut.rb
    ADDED
    
    | 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/puggernaut/gems'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Puggernaut::Gems.activate %w(eventmachine)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require 'eventmachine'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            $:.unshift File.dirname(__FILE__)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            require 'puggernaut/logger'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'puggernaut/client'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'puggernaut/server'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            module Puggernaut
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,66 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "#{File.dirname(__FILE__)}/logger"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'socket'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Puggernaut
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Client
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                include Logger
         
     | 
| 
      
 8 
     | 
    
         
            +
                
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_accessor :connections
         
     | 
| 
      
 10 
     | 
    
         
            +
                
         
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize(*servers)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @connections = {}
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @retry = []
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @servers = servers.collect { |s| s.split(':') }
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
                
         
     | 
| 
      
 17 
     | 
    
         
            +
                def close
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @connections.each do |host_port, connection|
         
     | 
| 
      
 19 
     | 
    
         
            +
                    connection.close
         
     | 
| 
      
 20 
     | 
    
         
            +
                    logger.info "Client#close - #{host_port}"
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
                
         
     | 
| 
      
 24 
     | 
    
         
            +
                def push(messages)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  messages = messages.collect do |channel, message|
         
     | 
| 
      
 26 
     | 
    
         
            +
                    if message.is_a?(::Array)
         
     | 
| 
      
 27 
     | 
    
         
            +
                      message.collect { |m| "#{channel}|#{m}" }.join("\n")
         
     | 
| 
      
 28 
     | 
    
         
            +
                    else
         
     | 
| 
      
 29 
     | 
    
         
            +
                      "#{channel}|#{message}"
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  unless messages.empty?
         
     | 
| 
      
 33 
     | 
    
         
            +
                    @servers.each do |(host, port)|
         
     | 
| 
      
 34 
     | 
    
         
            +
                      send host, port, messages.join("\n")
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
                
         
     | 
| 
      
 39 
     | 
    
         
            +
                private
         
     | 
| 
      
 40 
     | 
    
         
            +
                
         
     | 
| 
      
 41 
     | 
    
         
            +
                def send(host, port, data, try_retry=true)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  try if try_retry
         
     | 
| 
      
 43 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 44 
     | 
    
         
            +
                    host_port = "#{host}:#{port}"
         
     | 
| 
      
 45 
     | 
    
         
            +
                    logger.info "Client#send - #{host_port} - #{data}"
         
     | 
| 
      
 46 
     | 
    
         
            +
                    connection = @connections[host_port] ||= TCPSocket.open(host, port)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    connection.print(data)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    response = connection.gets
         
     | 
| 
      
 49 
     | 
    
         
            +
                    raise 'not ok' if !response || !response.include?('OK')
         
     | 
| 
      
 50 
     | 
    
         
            +
                  rescue Exception => e
         
     | 
| 
      
 51 
     | 
    
         
            +
                    logger.info "Client#send - Exception - #{e.message} - #{host_port} - #{data}"
         
     | 
| 
      
 52 
     | 
    
         
            +
                    @retry << [ host, port, data ]
         
     | 
| 
      
 53 
     | 
    
         
            +
                    @retry.shift if @retry.length > 10
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  try if try_retry
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
                
         
     | 
| 
      
 58 
     | 
    
         
            +
                def try
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @retry.length.times do
         
     | 
| 
      
 60 
     | 
    
         
            +
                    host, port, data = @retry.shift
         
     | 
| 
      
 61 
     | 
    
         
            +
                    @connections.delete("#{host}:#{port}")
         
     | 
| 
      
 62 
     | 
    
         
            +
                    send host, port, data, false
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,154 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            unless defined?(Puggernaut::Gems)
         
     | 
| 
      
 2 
     | 
    
         
            +
              
         
     | 
| 
      
 3 
     | 
    
         
            +
              require 'yaml'
         
     | 
| 
      
 4 
     | 
    
         
            +
              
         
     | 
| 
      
 5 
     | 
    
         
            +
              module Puggernaut
         
     | 
| 
      
 6 
     | 
    
         
            +
                module Gems
         
     | 
| 
      
 7 
     | 
    
         
            +
                  class <<self
         
     | 
| 
      
 8 
     | 
    
         
            +
                    
         
     | 
| 
      
 9 
     | 
    
         
            +
                    attr_accessor :config
         
     | 
| 
      
 10 
     | 
    
         
            +
                    attr_reader :gemset, :gemsets, :versions
         
     | 
| 
      
 11 
     | 
    
         
            +
                    
         
     | 
| 
      
 12 
     | 
    
         
            +
                    class SimpleStruct
         
     | 
| 
      
 13 
     | 
    
         
            +
                      attr_reader :hash
         
     | 
| 
      
 14 
     | 
    
         
            +
                      
         
     | 
| 
      
 15 
     | 
    
         
            +
                      def initialize(hash)
         
     | 
| 
      
 16 
     | 
    
         
            +
                        @hash = hash
         
     | 
| 
      
 17 
     | 
    
         
            +
                        @hash.each do |key, value|
         
     | 
| 
      
 18 
     | 
    
         
            +
                          self.class.send(:define_method, key) { @hash[key] }
         
     | 
| 
      
 19 
     | 
    
         
            +
                          self.class.send(:define_method, "#{key}=") { |v| @hash[key] = v }
         
     | 
| 
      
 20 
     | 
    
         
            +
                        end
         
     | 
| 
      
 21 
     | 
    
         
            +
                      end
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                    
         
     | 
| 
      
 24 
     | 
    
         
            +
                    Gems.config = SimpleStruct.new(
         
     | 
| 
      
 25 
     | 
    
         
            +
                      :gemsets => [ "#{File.expand_path('../../../', __FILE__)}/config/gemsets.yml" ],
         
     | 
| 
      
 26 
     | 
    
         
            +
                      :gemspec => "#{File.expand_path('../../../', __FILE__)}/config/gemspec.yml",
         
     | 
| 
      
 27 
     | 
    
         
            +
                      :warn => true
         
     | 
| 
      
 28 
     | 
    
         
            +
                    )
         
     | 
| 
      
 29 
     | 
    
         
            +
                    
         
     | 
| 
      
 30 
     | 
    
         
            +
                    def activate(*gems)
         
     | 
| 
      
 31 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 32 
     | 
    
         
            +
                        require 'rubygems' unless defined?(::Gem)
         
     | 
| 
      
 33 
     | 
    
         
            +
                      rescue LoadError
         
     | 
| 
      
 34 
     | 
    
         
            +
                        puts "rubygems library could not be required" if @config.warn
         
     | 
| 
      
 35 
     | 
    
         
            +
                      end
         
     | 
| 
      
 36 
     | 
    
         
            +
                      
         
     | 
| 
      
 37 
     | 
    
         
            +
                      self.gemset ||= gemset_from_loaded_specs
         
     | 
| 
      
 38 
     | 
    
         
            +
                      
         
     | 
| 
      
 39 
     | 
    
         
            +
                      gems.flatten.collect(&:to_sym).each do |name|
         
     | 
| 
      
 40 
     | 
    
         
            +
                        version = @versions[name]
         
     | 
| 
      
 41 
     | 
    
         
            +
                        vendor = File.expand_path("../../../vendor/#{name}/lib", __FILE__)
         
     | 
| 
      
 42 
     | 
    
         
            +
                        if File.exists?(vendor)
         
     | 
| 
      
 43 
     | 
    
         
            +
                          $:.unshift vendor
         
     | 
| 
      
 44 
     | 
    
         
            +
                        elsif defined?(gem)
         
     | 
| 
      
 45 
     | 
    
         
            +
                          gem name.to_s, version
         
     | 
| 
      
 46 
     | 
    
         
            +
                        else
         
     | 
| 
      
 47 
     | 
    
         
            +
                          puts "#{name} #{"(#{version})" if version} failed to activate" if @config.warn
         
     | 
| 
      
 48 
     | 
    
         
            +
                        end
         
     | 
| 
      
 49 
     | 
    
         
            +
                      end
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                    
         
     | 
| 
      
 52 
     | 
    
         
            +
                    def dependencies
         
     | 
| 
      
 53 
     | 
    
         
            +
                      dependency_filter(@gemspec.dependencies, @gemset)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                    
         
     | 
| 
      
 56 
     | 
    
         
            +
                    def development_dependencies
         
     | 
| 
      
 57 
     | 
    
         
            +
                      dependency_filter(@gemspec.development_dependencies, @gemset)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
                    
         
     | 
| 
      
 60 
     | 
    
         
            +
                    def gemset=(gemset)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      if gemset
         
     | 
| 
      
 62 
     | 
    
         
            +
                        @gemset = gemset.to_sym
         
     | 
| 
      
 63 
     | 
    
         
            +
                    
         
     | 
| 
      
 64 
     | 
    
         
            +
                        @gemsets = @config.gemsets.reverse.collect { |config|
         
     | 
| 
      
 65 
     | 
    
         
            +
                          if config.is_a?(::String)
         
     | 
| 
      
 66 
     | 
    
         
            +
                            YAML::load(File.read(config)) rescue {}
         
     | 
| 
      
 67 
     | 
    
         
            +
                          elsif config.is_a?(::Hash)
         
     | 
| 
      
 68 
     | 
    
         
            +
                            config
         
     | 
| 
      
 69 
     | 
    
         
            +
                          end
         
     | 
| 
      
 70 
     | 
    
         
            +
                        }.inject({}) do |hash, config|
         
     | 
| 
      
 71 
     | 
    
         
            +
                          deep_merge(hash, symbolize_keys(config))
         
     | 
| 
      
 72 
     | 
    
         
            +
                        end
         
     | 
| 
      
 73 
     | 
    
         
            +
                        
         
     | 
| 
      
 74 
     | 
    
         
            +
                        @versions = (@gemsets[gemspec.name.to_sym] || {}).inject({}) do |hash, (key, value)|
         
     | 
| 
      
 75 
     | 
    
         
            +
                          if !value.is_a?(::Hash) && value
         
     | 
| 
      
 76 
     | 
    
         
            +
                            hash[key] = value
         
     | 
| 
      
 77 
     | 
    
         
            +
                          elsif key == @gemset
         
     | 
| 
      
 78 
     | 
    
         
            +
                            (value || {}).each { |k, v| hash[k] = v }
         
     | 
| 
      
 79 
     | 
    
         
            +
                          end
         
     | 
| 
      
 80 
     | 
    
         
            +
                          hash
         
     | 
| 
      
 81 
     | 
    
         
            +
                        end
         
     | 
| 
      
 82 
     | 
    
         
            +
                      else
         
     | 
| 
      
 83 
     | 
    
         
            +
                        @gemset = nil
         
     | 
| 
      
 84 
     | 
    
         
            +
                        @gemsets = nil
         
     | 
| 
      
 85 
     | 
    
         
            +
                        @versions = nil
         
     | 
| 
      
 86 
     | 
    
         
            +
                      end
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
                    
         
     | 
| 
      
 89 
     | 
    
         
            +
                    def gemset_names
         
     | 
| 
      
 90 
     | 
    
         
            +
                      (
         
     | 
| 
      
 91 
     | 
    
         
            +
                        [ :default ] +
         
     | 
| 
      
 92 
     | 
    
         
            +
                        @gemsets[gemspec.name.to_sym].inject([]) { |array, (key, value)|
         
     | 
| 
      
 93 
     | 
    
         
            +
                          array.push(key) if value.is_a?(::Hash) || value.nil?
         
     | 
| 
      
 94 
     | 
    
         
            +
                          array
         
     | 
| 
      
 95 
     | 
    
         
            +
                        }
         
     | 
| 
      
 96 
     | 
    
         
            +
                      ).uniq
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
                    
         
     | 
| 
      
 99 
     | 
    
         
            +
                    def gemspec(reload=false)
         
     | 
| 
      
 100 
     | 
    
         
            +
                      if @gemspec && !reload
         
     | 
| 
      
 101 
     | 
    
         
            +
                        @gemspec
         
     | 
| 
      
 102 
     | 
    
         
            +
                      else
         
     | 
| 
      
 103 
     | 
    
         
            +
                        data = YAML::load(File.read(@config.gemspec)) rescue {}
         
     | 
| 
      
 104 
     | 
    
         
            +
                        @gemspec = SimpleStruct.new(data)
         
     | 
| 
      
 105 
     | 
    
         
            +
                      end
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
                  
         
     | 
| 
      
 108 
     | 
    
         
            +
                    private
         
     | 
| 
      
 109 
     | 
    
         
            +
                  
         
     | 
| 
      
 110 
     | 
    
         
            +
                    def deep_merge(first, second)
         
     | 
| 
      
 111 
     | 
    
         
            +
                      merger = lambda do |key, v1, v2|
         
     | 
| 
      
 112 
     | 
    
         
            +
                        Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2
         
     | 
| 
      
 113 
     | 
    
         
            +
                      end
         
     | 
| 
      
 114 
     | 
    
         
            +
                      first.merge(second, &merger)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
                    
         
     | 
| 
      
 117 
     | 
    
         
            +
                    def dependency_filter(dependencies, match)
         
     | 
| 
      
 118 
     | 
    
         
            +
                      (dependencies || []).inject([]) { |array, value|
         
     | 
| 
      
 119 
     | 
    
         
            +
                        if value.is_a?(::Hash)
         
     | 
| 
      
 120 
     | 
    
         
            +
                          array += value[match.to_s] if value[match.to_s]
         
     | 
| 
      
 121 
     | 
    
         
            +
                        else
         
     | 
| 
      
 122 
     | 
    
         
            +
                          array << value
         
     | 
| 
      
 123 
     | 
    
         
            +
                        end
         
     | 
| 
      
 124 
     | 
    
         
            +
                        array
         
     | 
| 
      
 125 
     | 
    
         
            +
                      }.uniq.collect(&:to_sym)
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
      
 127 
     | 
    
         
            +
                    
         
     | 
| 
      
 128 
     | 
    
         
            +
                    def gemset_from_loaded_specs
         
     | 
| 
      
 129 
     | 
    
         
            +
                      if defined?(Gem)
         
     | 
| 
      
 130 
     | 
    
         
            +
                        Gem.loaded_specs.each do |name, spec|
         
     | 
| 
      
 131 
     | 
    
         
            +
                          if name == gemspec.name
         
     | 
| 
      
 132 
     | 
    
         
            +
                            return :default
         
     | 
| 
      
 133 
     | 
    
         
            +
                          elsif name[0..gemspec.name.length] == "#{gemspec.name}-"
         
     | 
| 
      
 134 
     | 
    
         
            +
                            return name[gemspec.name.length+1..-1].to_sym
         
     | 
| 
      
 135 
     | 
    
         
            +
                          end
         
     | 
| 
      
 136 
     | 
    
         
            +
                        end
         
     | 
| 
      
 137 
     | 
    
         
            +
                        :default
         
     | 
| 
      
 138 
     | 
    
         
            +
                      else
         
     | 
| 
      
 139 
     | 
    
         
            +
                        :none
         
     | 
| 
      
 140 
     | 
    
         
            +
                      end
         
     | 
| 
      
 141 
     | 
    
         
            +
                    end
         
     | 
| 
      
 142 
     | 
    
         
            +
                  
         
     | 
| 
      
 143 
     | 
    
         
            +
                    def symbolize_keys(hash)
         
     | 
| 
      
 144 
     | 
    
         
            +
                      return {} unless hash.is_a?(::Hash)
         
     | 
| 
      
 145 
     | 
    
         
            +
                      hash.inject({}) do |options, (key, value)|
         
     | 
| 
      
 146 
     | 
    
         
            +
                        value = symbolize_keys(value) if value.is_a?(::Hash)
         
     | 
| 
      
 147 
     | 
    
         
            +
                        options[(key.to_sym rescue key) || key] = value
         
     | 
| 
      
 148 
     | 
    
         
            +
                        options
         
     | 
| 
      
 149 
     | 
    
         
            +
                      end
         
     | 
| 
      
 150 
     | 
    
         
            +
                    end
         
     | 
| 
      
 151 
     | 
    
         
            +
                  end
         
     | 
| 
      
 152 
     | 
    
         
            +
                end
         
     | 
| 
      
 153 
     | 
    
         
            +
              end
         
     | 
| 
      
 154 
     | 
    
         
            +
            end
         
     |