cloud-crowd 0.2.3 → 0.2.4
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/cloud-crowd.gemspec
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            Gem::Specification.new do |s|
         | 
| 2 2 | 
             
              s.name      = 'cloud-crowd'
         | 
| 3 | 
            -
              s.version   = '0.2. | 
| 4 | 
            -
              s.date      = '2009-09- | 
| 3 | 
            +
              s.version   = '0.2.4'         # Keep version in sync with cloud-cloud.rb
         | 
| 4 | 
            +
              s.date      = '2009-09-28'
         | 
| 5 5 |  | 
| 6 6 | 
             
              s.homepage    = "http://wiki.github.com/documentcloud/cloud-crowd"
         | 
| 7 7 | 
             
              s.summary     = "Parallel Processing for the Rest of Us"
         | 
    
        data/lib/cloud-crowd.rb
    CHANGED
    
    | @@ -44,7 +44,7 @@ module CloudCrowd | |
| 44 44 | 
             
              autoload :WorkUnit,     'cloud_crowd/models'
         | 
| 45 45 |  | 
| 46 46 | 
             
              # Keep this version in sync with the gemspec.
         | 
| 47 | 
            -
              VERSION        = '0.2. | 
| 47 | 
            +
              VERSION        = '0.2.4'
         | 
| 48 48 |  | 
| 49 49 | 
             
              # Increment the schema version when there's a backwards incompatible change.
         | 
| 50 50 | 
             
              SCHEMA_VERSION = 3
         | 
| @@ -162,6 +162,9 @@ module CloudCrowd | |
| 162 162 | 
             
                    @actions[name] = Module.const_get(Inflector.camelize(name))
         | 
| 163 163 | 
             
                  end
         | 
| 164 164 | 
             
                  @actions
         | 
| 165 | 
            +
                rescue NameError => e
         | 
| 166 | 
            +
                  adjusted_message = "One of your actions failed to load. Please ensure that the name of your action class can be deduced from the name of the file. ex: 'word_count.rb' => 'WordCount'\n#{e.message}" 
         | 
| 167 | 
            +
                  raise NameError.new(adjusted_message, e.name)
         | 
| 165 168 | 
             
                end
         | 
| 166 169 | 
             
              end
         | 
| 167 170 |  | 
| @@ -39,11 +39,12 @@ module CloudCrowd | |
| 39 39 | 
             
                  result = node['/work'].post(:work_unit => unit.to_json)
         | 
| 40 40 | 
             
                  unit.assign_to(self, JSON.parse(result)['pid'])
         | 
| 41 41 | 
             
                  touch && true
         | 
| 42 | 
            -
                rescue Errno::ECONNREFUSED # Couldn't post to node, assume it's gone away.
         | 
| 43 | 
            -
                  destroy && false
         | 
| 44 42 | 
             
                rescue RestClient::RequestFailed => e
         | 
| 45 43 | 
             
                  raise e unless e.http_code == 503 && e.http_body == Node::OVERLOADED_MESSAGE
         | 
| 46 44 | 
             
                  update_attribute(:busy, true) && false
         | 
| 45 | 
            +
                rescue RestClient::Exception, Errno::ECONNREFUSED 
         | 
| 46 | 
            +
                  # Couldn't post to node, assume it's gone away.
         | 
| 47 | 
            +
                  destroy && false
         | 
| 47 48 | 
             
                end
         | 
| 48 49 |  | 
| 49 50 | 
             
                # What Actions is this Node able to run?
         | 
| @@ -7,6 +7,10 @@ module CloudCrowd | |
| 7 7 | 
             
              class WorkUnit < ActiveRecord::Base
         | 
| 8 8 | 
             
                include ModelStatus
         | 
| 9 9 |  | 
| 10 | 
            +
                # We use a random number in (0...MAX_RESERVATION) to reserve work units.
         | 
| 11 | 
            +
                # The size of the maximum signed integer in MySQL -- SQLite has no limit.
         | 
| 12 | 
            +
                MAX_RESERVATION = 2147483647
         | 
| 13 | 
            +
                
         | 
| 10 14 | 
             
                belongs_to :job
         | 
| 11 15 | 
             
                belongs_to :node_record
         | 
| 12 16 |  | 
| @@ -15,7 +19,9 @@ module CloudCrowd | |
| 15 19 | 
             
                # Available WorkUnits are waiting to be distributed to Nodes for processing.
         | 
| 16 20 | 
             
                named_scope :available, {:conditions => {:reservation => nil, :worker_pid => nil, :status => INCOMPLETE}}
         | 
| 17 21 | 
             
                # Reserved WorkUnits have been marked for distribution by a central server process.
         | 
| 18 | 
            -
                named_scope :reserved,   | 
| 22 | 
            +
                named_scope :reserved,  lambda {|reservation_number| 
         | 
| 23 | 
            +
                  {:conditions => {:reservation => reservation_number}, :order => 'updated_at asc'}
         | 
| 24 | 
            +
                }
         | 
| 19 25 |  | 
| 20 26 | 
             
                # Attempt to send a list of WorkUnits to nodes with available capacity.
         | 
| 21 27 | 
             
                # A single central server process stops the same WorkUnit from being
         | 
| @@ -27,8 +33,8 @@ module CloudCrowd | |
| 27 33 | 
             
                # from the availability list when they are successfully sent, and Nodes get
         | 
| 28 34 | 
             
                # removed when they are busy or have the action in question disabled.
         | 
| 29 35 | 
             
                def self.distribute_to_nodes
         | 
| 30 | 
            -
                  return unless WorkUnit.reserve_available
         | 
| 31 | 
            -
                  work_units = WorkUnit.reserved
         | 
| 36 | 
            +
                  return unless reservation_number = WorkUnit.reserve_available
         | 
| 37 | 
            +
                  work_units = WorkUnit.reserved(reservation_number)
         | 
| 32 38 | 
             
                  available_nodes = NodeRecord.available
         | 
| 33 39 | 
             
                  while node = available_nodes.shift and unit = work_units.shift do
         | 
| 34 40 | 
             
                    if node.actions.include? unit.action
         | 
| @@ -40,18 +46,20 @@ module CloudCrowd | |
| 40 46 | 
             
                    work_units.push(unit)
         | 
| 41 47 | 
             
                  end
         | 
| 42 48 | 
             
                ensure
         | 
| 43 | 
            -
                  WorkUnit.cancel_reservations
         | 
| 49 | 
            +
                  WorkUnit.cancel_reservations(reservation_number)
         | 
| 44 50 | 
             
                end
         | 
| 45 51 |  | 
| 46 52 | 
             
                # Reserves all available WorkUnits for this process. Returns false if there 
         | 
| 47 53 | 
             
                # were none available.
         | 
| 48 54 | 
             
                def self.reserve_available
         | 
| 49 | 
            -
                   | 
| 55 | 
            +
                  reservation_number = ActiveSupport::SecureRandom.random_number(MAX_RESERVATION)
         | 
| 56 | 
            +
                  any = WorkUnit.available.update_all("reservation = #{reservation_number}") > 0
         | 
| 57 | 
            +
                  any && reservation_number
         | 
| 50 58 | 
             
                end
         | 
| 51 59 |  | 
| 52 60 | 
             
                # Cancels all outstanding WorkUnit reservations for this process.
         | 
| 53 | 
            -
                def self.cancel_reservations
         | 
| 54 | 
            -
                  WorkUnit.reserved.update_all('reservation = null')
         | 
| 61 | 
            +
                def self.cancel_reservations(reservation_number)
         | 
| 62 | 
            +
                  WorkUnit.reserved(reservation_number).update_all('reservation = null')
         | 
| 55 63 | 
             
                end
         | 
| 56 64 |  | 
| 57 65 | 
             
                # Cancels all outstanding WorkUnit reservations for all processes. (Useful
         | 
    
        data/lib/cloud_crowd/node.rb
    CHANGED
    
    | @@ -24,6 +24,9 @@ module CloudCrowd | |
| 24 24 | 
             
                # (if configured to do so in config.yml).
         | 
| 25 25 | 
             
                MONITOR_INTERVAL    = 3
         | 
| 26 26 |  | 
| 27 | 
            +
                # The interval at which the node regularly checks in with central (5 min).
         | 
| 28 | 
            +
                CHECK_IN_INTERVAL   = 300
         | 
| 29 | 
            +
                
         | 
| 27 30 | 
             
                # The response sent back when this node is overloaded.
         | 
| 28 31 | 
             
                OVERLOADED_MESSAGE  = 'Node Overloaded'
         | 
| 29 32 |  | 
| @@ -86,6 +89,7 @@ module CloudCrowd | |
| 86 89 | 
             
                  asset_store
         | 
| 87 90 | 
             
                  @server_thread   = Thread.new { @server.start }
         | 
| 88 91 | 
             
                  check_in(true)
         | 
| 92 | 
            +
                  check_in_periodically
         | 
| 89 93 | 
             
                  monitor_system if @max_load || @min_memory
         | 
| 90 94 | 
             
                  @server_thread.join
         | 
| 91 95 | 
             
                end
         | 
| @@ -100,7 +104,7 @@ module CloudCrowd | |
| 100 104 | 
             
                    :max_workers      => CloudCrowd.config[:max_workers],
         | 
| 101 105 | 
             
                    :enabled_actions  => @enabled_actions.join(',')
         | 
| 102 106 | 
             
                  )
         | 
| 103 | 
            -
                rescue Errno::ECONNREFUSED
         | 
| 107 | 
            +
                rescue RestClient::Exception, Errno::ECONNREFUSED
         | 
| 104 108 | 
             
                  puts "Failed to connect to the central server (#{@central.to_s})."
         | 
| 105 109 | 
             
                  raise SystemExit if critical
         | 
| 106 110 | 
             
                end
         | 
| @@ -160,6 +164,18 @@ module CloudCrowd | |
| 160 164 | 
             
                  end
         | 
| 161 165 | 
             
                end
         | 
| 162 166 |  | 
| 167 | 
            +
                # If communication is interrupted for external reasons, the central server 
         | 
| 168 | 
            +
                # will assume that the node has gone down. Checking in will let central know 
         | 
| 169 | 
            +
                # it's still online.
         | 
| 170 | 
            +
                def check_in_periodically
         | 
| 171 | 
            +
                  @check_in_thread = Thread.new do
         | 
| 172 | 
            +
                    loop do
         | 
| 173 | 
            +
                      sleep CHECK_IN_INTERVAL
         | 
| 174 | 
            +
                      check_in
         | 
| 175 | 
            +
                    end
         | 
| 176 | 
            +
                  end
         | 
| 177 | 
            +
                end
         | 
| 178 | 
            +
                
         | 
| 163 179 | 
             
                # Trap exit signals in order to shut down cleanly.
         | 
| 164 180 | 
             
                def trap_signals
         | 
| 165 181 | 
             
                  Signal.trap('QUIT') { shut_down }
         | 
| @@ -170,6 +186,7 @@ module CloudCrowd | |
| 170 186 |  | 
| 171 187 | 
             
                # At shut down, de-register with the central server before exiting.
         | 
| 172 188 | 
             
                def shut_down
         | 
| 189 | 
            +
                  @check_in_thread.kill if @check_in_thread
         | 
| 173 190 | 
             
                  @monitor_thread.kill if @monitor_thread
         | 
| 174 191 | 
             
                  check_out
         | 
| 175 192 | 
             
                  @server_thread.kill if @server_thread
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: cloud-crowd
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              version: 0.2. | 
| 4 | 
            +
              version: 0.2.4
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors: 
         | 
| 7 7 | 
             
            - Jeremy Ashkenas
         | 
| @@ -9,7 +9,7 @@ autorequire: | |
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 11 |  | 
| 12 | 
            -
            date: 2009-09- | 
| 12 | 
            +
            date: 2009-09-28 00:00:00 -04:00
         | 
| 13 13 | 
             
            default_executable: 
         | 
| 14 14 | 
             
            dependencies: 
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency 
         |