cloud-crowd 0.6.2 → 0.7.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b642c04c5f924a808fb7e8877db3f784f4150345
4
+ data.tar.gz: ca7630f054708dc5ed088eb36019cd2587047cb0
5
+ SHA512:
6
+ metadata.gz: 440f76dc31892df07de7549ac985a4bd9fbca89b656a66340979a7fd9469685112f73a807fd1b256ec773a15c12798bf78c9d73f660e4d7f9c705a892153410c
7
+ data.tar.gz: 0b92287c1c6aa436dafd1a4f38e9a9bbe312c12967b67dfd08d272bafc16277696715ea3d46c2e8d22500e6087cc07b693e40338950d5c7da9f887cfa8063d42
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'cloud-crowd'
3
- s.version = '0.6.2' # Keep version in sync with cloud-cloud.rb
4
- s.date = '2011-04-14'
3
+ s.version = '0.7.0.pre' # Keep version in sync with cloud-cloud.rb
4
+ s.date = '2014-03-08'
5
5
 
6
6
  s.homepage = "http://wiki.github.com/documentcloud/cloud-crowd"
7
7
  s.summary = "Parallel Processing for the Rest of Us"
@@ -12,9 +12,11 @@ Gem::Specification.new do |s|
12
12
  everywhere is black with people and more come streaming from all sides as though
13
13
  streets had only one direction.
14
14
  EOS
15
+
16
+ s.license = "MIT"
15
17
 
16
- s.authors = ['Jeremy Ashkenas']
17
- s.email = 'jeremy@documentcloud.org'
18
+ s.authors = ['Jeremy Ashkenas', 'Ted Han']
19
+ s.email = 'opensource@documentcloud.org'
18
20
  s.rubyforge_project = 'cloud-crowd'
19
21
 
20
22
  s.require_paths = ['lib']
@@ -26,20 +28,6 @@ Gem::Specification.new do |s|
26
28
  '--main' << 'README' <<
27
29
  '--all'
28
30
 
29
- s.add_dependency 'sinatra', ['~> 0.9']
30
- s.add_dependency 'activerecord', ['~> 2.3']
31
- s.add_dependency 'json', ['>= 1.1.7']
32
- s.add_dependency 'rest-client', ['>= 1.4']
33
- s.add_dependency 'thin', ['>= 1.2.4']
34
-
35
- if s.respond_to?(:add_development_dependency)
36
- s.add_development_dependency 'faker', ['>= 0.3.1']
37
- s.add_development_dependency 'thoughtbot-shoulda', ['>= 2.10.2']
38
- s.add_development_dependency 'notahat-machinist', ['>= 1.0.3']
39
- s.add_development_dependency 'rack-test', ['>= 0.4.1']
40
- s.add_development_dependency 'mocha', ['>= 0.9.7']
41
- end
42
-
43
31
  s.files = %w(
44
32
  actions/graphics_magick.rb
45
33
  actions/process_pdfs.rb
@@ -4,9 +4,8 @@ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))
4
4
 
5
5
  # Common Gems:
6
6
  require 'rubygems'
7
- gem 'activerecord', '~> 2.0'
7
+ gem 'activerecord'
8
8
  gem 'json'
9
- gem 'rest-client'
10
9
  gem 'sinatra'
11
10
  gem 'thin'
12
11
 
@@ -17,7 +16,6 @@ autoload :Digest, 'digest'
17
16
  autoload :ERB, 'erb'
18
17
  autoload :FileUtils, 'fileutils'
19
18
  autoload :JSON, 'json'
20
- autoload :RestClient, 'rest_client'
21
19
  autoload :RightAws, 'right_aws'
22
20
  autoload :CloudFiles, 'cloudfiles'
23
21
  autoload :Sinatra, 'sinatra'
@@ -28,6 +26,10 @@ autoload :YAML, 'yaml'
28
26
  require 'socket'
29
27
  require 'net/http'
30
28
  require 'cloud_crowd/exceptions'
29
+ require 'rest_client'
30
+
31
+ require 'active_model_serializers'
32
+ ActiveModel::Serializer.root = false
31
33
 
32
34
  module CloudCrowd
33
35
 
@@ -45,7 +47,7 @@ module CloudCrowd
45
47
  autoload :WorkUnit, 'cloud_crowd/models'
46
48
 
47
49
  # Keep this version in sync with the gemspec.
48
- VERSION = '0.6.2'
50
+ VERSION = '0.7.0'
49
51
 
50
52
  # Increment the schema version when there's a backwards incompatible change.
51
53
  SCHEMA_VERSION = 4
@@ -7,7 +7,7 @@ module CloudCrowd
7
7
  def json(obj)
8
8
  content_type :json
9
9
  return status(204) && '' if obj.nil?
10
- obj.to_json
10
+ (obj.respond_to?(:as_json) ? obj.as_json : obj).to_json
11
11
  end
12
12
 
13
13
  # Lazy-fetch the job specified by <tt>job_id</tt>.
@@ -8,13 +8,13 @@ module CloudCrowd
8
8
 
9
9
  klass.class_eval do
10
10
  # Note that COMPLETE and INCOMPLETE are unions of other states.
11
- named_scope 'processing', :conditions => {:status => PROCESSING}
12
- named_scope 'succeeded', :conditions => {:status => SUCCEEDED}
13
- named_scope 'failed', :conditions => {:status => FAILED}
14
- named_scope 'splitting', :conditions => {:status => SPLITTING}
15
- named_scope 'merging', :conditions => {:status => MERGING}
16
- named_scope 'complete', :conditions => {:status => COMPLETE}
17
- named_scope 'incomplete', :conditions => {:status => INCOMPLETE}
11
+ scope 'processing', -> { where( :status => PROCESSING )}
12
+ scope 'succeeded', -> { where( :status => SUCCEEDED )}
13
+ scope 'failed', -> { where( :status => FAILED )}
14
+ scope 'splitting', -> { where( :status => SPLITTING )}
15
+ scope 'merging', -> { where( :status => MERGING )}
16
+ scope 'complete', -> { where( :status => COMPLETE )}
17
+ scope 'incomplete', -> { where( :status => INCOMPLETE )}
18
18
  end
19
19
 
20
20
  end
@@ -13,12 +13,17 @@ module CloudCrowd
13
13
 
14
14
  validates_presence_of :status, :inputs, :action, :options
15
15
 
16
- before_validation_on_create :set_initial_status
16
+ # Set initial status
17
+ # A Job starts out either splitting or processing, depending on its action.
18
+ before_validation(:on => :create) do
19
+ self.status = self.splittable? ? SPLITTING : PROCESSING
20
+ end
21
+
17
22
  after_create :queue_for_workers
18
23
  before_destroy :cleanup_assets
19
24
 
20
25
  # Jobs that were last updated more than N days ago.
21
- named_scope :older_than, lambda {|num| {:conditions => ['updated_at < ?', num.days.ago]} }
26
+ scope :older_than, lambda {|num| {:conditions => ['updated_at < ?', num.days.ago]} }
22
27
 
23
28
  # Create a Job from an incoming JSON request, and add it to the queue.
24
29
  def self.create_from_request(h)
@@ -86,7 +91,7 @@ module CloudCrowd
86
91
  # separate thread to get out of the transaction's way.
87
92
  # TODO: Convert this into a 'cleanup' work unit that gets run by a worker.
88
93
  def cleanup_assets
89
- AssetStore.new.cleanup(self)
94
+ # AssetStore.new.cleanup(self)
90
95
  end
91
96
 
92
97
  # Have all of the WorkUnits finished?
@@ -147,7 +152,7 @@ module CloudCrowd
147
152
 
148
153
  # A JSON representation of this job includes the statuses of its component
149
154
  # WorkUnits, as well as any completed outputs.
150
- def to_json(opts={})
155
+ def as_json(opts={})
151
156
  atts = {
152
157
  'id' => id,
153
158
  'color' => color,
@@ -158,7 +163,7 @@ module CloudCrowd
158
163
  }
159
164
  atts['outputs'] = JSON.parse(outputs) if outputs
160
165
  atts['email'] = email if email
161
- atts.to_json
166
+ atts
162
167
  end
163
168
 
164
169
 
@@ -182,10 +187,5 @@ module CloudCrowd
182
187
  self
183
188
  end
184
189
 
185
- # A Job starts out either splitting or processing, depending on its action.
186
- def set_initial_status
187
- self.status = self.splittable? ? SPLITTING : PROCESSING
188
- end
189
-
190
190
  end
191
191
  end
@@ -12,9 +12,9 @@ module CloudCrowd
12
12
  after_destroy :redistribute_work_units
13
13
 
14
14
  # Available Nodes haven't used up their maxiumum number of workers yet.
15
- named_scope :available, {
16
- :conditions => ['(max_workers is null or (select count(*) from work_units where node_record_id = node_records.id) < max_workers)'],
17
- :order => 'updated_at asc'
15
+ scope :available, -> {
16
+ where('(max_workers is null or (select count(*) from work_units where node_record_id = node_records.id) < max_workers)').
17
+ order('updated_at asc')
18
18
  }
19
19
 
20
20
  # Extract the port number from the host id.
@@ -32,7 +32,7 @@ module CloudCrowd
32
32
  :max_workers => params[:max_workers],
33
33
  :enabled_actions => params[:enabled_actions]
34
34
  }
35
- self.find_or_create_by_host(params[:host]).update_attributes!(attrs)
35
+ self.find_or_create_by(:host => params[:host]).update_attributes!(attrs)
36
36
  end
37
37
 
38
38
  # Dispatch a WorkUnit to this node. Places the node at back at the end of
@@ -82,23 +82,33 @@ module CloudCrowd
82
82
 
83
83
  # A list of the process ids of the workers currently being run by the Node.
84
84
  def worker_pids
85
- work_units.all(:select => 'worker_pid').map(&:worker_pid)
85
+ work_units.pluck('worker_pid')
86
86
  end
87
87
 
88
88
  # Release all of this Node's WorkUnits for other nodes to take.
89
89
  def release_work_units
90
- WorkUnit.update_all('node_record_id = null, worker_pid = null', "node_record_id = #{id}")
90
+ WorkUnit.where("node_record_id = #{id}").update_all('node_record_id = null, worker_pid = null')
91
91
  end
92
92
 
93
93
  # The JSON representation of a NodeRecord includes its worker_pids.
94
- def to_json(opts={})
95
- { 'host' => host,
96
- 'workers' => worker_pids,
97
- 'status' => display_status,
98
- 'tag' => tag
99
- }.to_json
94
+
95
+ class Serializer < ActiveModel::Serializer
96
+ attributes :host, :tag, :workers, :status
97
+
98
+ def workers
99
+ object.worker_pids
100
+ end
101
+
102
+ def status
103
+ object.display_status
104
+ end
100
105
  end
106
+
107
+ def active_model_serializer; Serializer; end
101
108
 
109
+ def to_json
110
+ Serializer.new(self).to_json
111
+ end
102
112
 
103
113
  private
104
114
 
@@ -6,7 +6,7 @@ module CloudCrowd
6
6
  # are each run as a single WorkUnit.
7
7
  class WorkUnit < ActiveRecord::Base
8
8
  include ModelStatus
9
-
9
+
10
10
  # We use a random number in (0...MAX_RESERVATION) to reserve work units.
11
11
  # The size of the maximum signed integer in MySQL -- SQLite has no limit.
12
12
  MAX_RESERVATION = 2147483647
@@ -21,11 +21,9 @@ module CloudCrowd
21
21
  validates_presence_of :job_id, :status, :input, :action
22
22
 
23
23
  # Available WorkUnits are waiting to be distributed to Nodes for processing.
24
- named_scope :available, {:conditions => {:reservation => nil, :worker_pid => nil, :status => INCOMPLETE}}
24
+ scope :available, -> { where(:reservation => nil, :worker_pid => nil, :status => INCOMPLETE) }
25
25
  # Reserved WorkUnits have been marked for distribution by a central server process.
26
- named_scope :reserved, lambda {|reservation|
27
- {:conditions => {:reservation => reservation}, :order => 'updated_at asc'}
28
- }
26
+ scope :reserved, ->(reservation) { where(:reservation => reservation).order('updated_at asc') }
29
27
 
30
28
  # Attempt to send a list of WorkUnits to nodes with available capacity.
31
29
  # A single central server process stops the same WorkUnit from being
@@ -43,27 +41,25 @@ module CloudCrowd
43
41
 
44
42
  # Find the available nodes, and determine what actions we're capable
45
43
  # of running at the moment.
46
- available_nodes = NodeRecord.available
44
+ available_nodes = NodeRecord.available.to_a
47
45
  available_actions = available_nodes.map {|node| node.actions }.flatten.uniq
48
46
  filter = "action in (#{available_actions.map{|a| "'#{a}'"}.join(',')})"
49
47
 
50
48
  # Reserve a handful of available work units.
51
49
  WorkUnit.cancel_reservations(reservation) if reservation
52
50
  return unless reservation = WorkUnit.reserve_available(:limit => RESERVATION_LIMIT, :conditions => filter)
53
- work_units = WorkUnit.reserved(reservation)
51
+ work_units = WorkUnit.reserved(reservation).to_a
54
52
 
55
53
  # Round robin through the nodes and units, sending the unit if the node
56
54
  # is able to process it.
57
- work_units.each do |unit|
58
- available_nodes.each do |node|
59
- if node.actions.include? unit.action
60
- if node.send_work_unit unit
61
- work_units.delete unit
62
- available_nodes.delete node if node.busy?
63
- break
64
- end
55
+ while (unit = work_units.shift) and available_nodes.any? do
56
+ while node = available_nodes.shift do
57
+ if node.actions.include?(unit.action) and node.send_work_unit(unit)
58
+ available_nodes.push(node) unless node.busy?
59
+ break
65
60
  end
66
61
  end
62
+ work_units.push(unit) unless unit.assigned?
67
63
  end
68
64
 
69
65
  # If we still have units at this point, or we're fresh out of nodes,
@@ -77,9 +73,11 @@ module CloudCrowd
77
73
  # Reserves all available WorkUnits for this process. Returns false if there
78
74
  # were none available.
79
75
  def self.reserve_available(options={})
80
- reservation = ActiveSupport::SecureRandom.random_number(MAX_RESERVATION)
76
+ reservation = SecureRandom.random_number(MAX_RESERVATION)
81
77
  conditions = "reservation is null and node_record_id is null and status in (#{INCOMPLETE.join(',')}) and #{options[:conditions]}"
82
- any = WorkUnit.update_all("reservation = #{reservation}", conditions, options) > 0
78
+ query = WorkUnit.where(conditions)
79
+ query.limit(options[:limit]) if options[:limit]
80
+ any = query.update_all("reservation = #{reservation}") > 0
83
81
  any && reservation
84
82
  end
85
83
 
@@ -166,6 +164,10 @@ module CloudCrowd
166
164
  def assign_to(node_record, worker_pid)
167
165
  update_attributes!(:node_record => node_record, :worker_pid => worker_pid)
168
166
  end
167
+
168
+ def assigned?
169
+ !!(node_record_id && worker_pid)
170
+ end
169
171
 
170
172
  # All output needs to be wrapped in a JSON object for consistency
171
173
  # (unfortunately, JSON.parse needs the top-level to be an object or array).
@@ -176,17 +178,15 @@ module CloudCrowd
176
178
 
177
179
  # The JSON representation of a WorkUnit shares the Job's options with all
178
180
  # its cousin WorkUnits.
179
- def to_json
180
- {
181
- 'id' => self.id,
182
- 'job_id' => self.job_id,
183
- 'input' => self.input,
184
- 'attempts' => self.attempts,
185
- 'action' => self.action,
186
- 'options' => JSON.parse(self.job.options),
187
- 'status' => self.status
188
- }.to_json
181
+ class Serializer < ActiveModel::Serializer
182
+ attributes :id, :job_id, :input, :attempts, :action, :options, :status
183
+
184
+ def options; JSON.parse(object.job.options); end
189
185
  end
186
+
187
+ def active_model_serializer; Serializer; end
188
+ def to_json; Serializer.new(self).to_json; end
190
189
 
191
190
  end
192
191
  end
192
+ require 'securerandom'
@@ -7,6 +7,7 @@ module CloudCrowd
7
7
  # [get /heartbeat] Returns 200 OK to let monitoring tools know the server's up.
8
8
  # [post /work] The central server hits <tt>/work</tt> to dispatch a WorkUnit to this Node.
9
9
  class Node < Sinatra::Base
10
+ use ActiveRecord::ConnectionAdapters::ConnectionManagement
10
11
 
11
12
  # A Node's default port. You only run a single node per machine, so they
12
13
  # can all use the same port without any problems.
@@ -76,7 +77,7 @@ module CloudCrowd
76
77
  @overloaded = false
77
78
  @max_load = CloudCrowd.config[:max_load]
78
79
  @min_memory = CloudCrowd.config[:min_free_memory]
79
- start unless test?
80
+ start unless ENV['RACK_ENV'] == 'test'
80
81
  end
81
82
 
82
83
  # Starting up a Node registers with the central server and begins to listen
@@ -18,6 +18,7 @@ module CloudCrowd
18
18
  # [delete /node/:host] Removes a Node from the registry, freeing up any WorkUnits that it had checked out.
19
19
  # [put /work/:unit_id] Mark a finished WorkUnit as completed or failed, with results.
20
20
  class Server < Sinatra::Base
21
+ use ActiveRecord::ConnectionAdapters::ConnectionManagement
21
22
 
22
23
  set :root, ROOT
23
24
  set :authorization_realm, "CloudCrowd"
@@ -42,7 +43,7 @@ module CloudCrowd
42
43
  # larger -- keep it in mind.
43
44
  get '/status' do
44
45
  json(
45
- 'nodes' => NodeRecord.all(:order => 'host desc'),
46
+ 'nodes' => NodeRecord.order('host desc').map{ |node| NodeRecord::Serializer.new(node).as_json },
46
47
  'job_count' => Job.incomplete.count,
47
48
  'work_unit_count' => WorkUnit.incomplete.count
48
49
  )
@@ -12,7 +12,7 @@ class ServerTest < Test::Unit::TestCase
12
12
 
13
13
  setup do
14
14
  Job.destroy_all
15
- 2.times { Job.make }
15
+ 2.times { Job.make! }
16
16
  end
17
17
 
18
18
  should "set the identity of the Ruby instance" do
@@ -1,6 +1,3 @@
1
- Sham.url { Faker::Internet.domain_name + "/" + Faker::Internet.domain_word + ".jpg" }
2
- Sham.host { Faker::Internet.domain_name + '.local' }
3
-
4
1
  CloudCrowd::Job.blueprint do
5
2
  status { CloudCrowd::PROCESSING }
6
3
  inputs { ['http://www.google.com/intl/en_ALL/images/logo.gif'].to_json }
@@ -10,7 +7,7 @@ CloudCrowd::Job.blueprint do
10
7
  end
11
8
 
12
9
  CloudCrowd::NodeRecord.blueprint do
13
- host
10
+ host { "hostname-#{sn}" }
14
11
  ip_address { '127.0.0.1' }
15
12
  port { 6093 }
16
13
  enabled_actions { 'graphics_magick,word_count' }
@@ -18,7 +15,7 @@ CloudCrowd::NodeRecord.blueprint do
18
15
  end
19
16
 
20
17
  CloudCrowd::WorkUnit.blueprint do
21
- job { CloudCrowd::Job.make }
18
+ job { CloudCrowd::Job.make! }
22
19
  status { CloudCrowd::PROCESSING }
23
20
  input { '{"key":"value"}' }
24
21
  action { 'graphics_magick' }
@@ -1,19 +1,28 @@
1
1
  ENV['RACK_ENV'] = 'test'
2
2
  require 'rubygems'
3
3
 
4
+ require 'pry'
5
+ require 'faker'
6
+ require 'sham'
7
+ require 'rack/test'
8
+ require 'shoulda'
9
+ require 'shoulda/context'
10
+ require 'shoulda/matchers/active_record'
11
+ require 'shoulda/matchers/active_model'
12
+ require 'machinist/active_record'
13
+ require 'mocha/setup'
14
+
4
15
  here = File.dirname(__FILE__)
5
16
  require File.expand_path(here + "/../lib/cloud-crowd")
6
17
  CloudCrowd.configure(here + '/config/config.yml')
7
18
  CloudCrowd.configure_database(here + '/config/database.yml')
8
19
 
9
- require 'faker'
10
- require 'sham'
11
- require 'rack/test'
12
- require 'shoulda/active_record'
13
- require 'machinist/active_record'
14
- require 'mocha'
15
20
  require "#{CloudCrowd::ROOT}/test/blueprints.rb"
16
21
 
17
22
  class Test::Unit::TestCase
18
23
  include CloudCrowd
24
+ include Shoulda::Matchers::ActiveRecord
25
+ extend Shoulda::Matchers::ActiveRecord
26
+ include Shoulda::Matchers::ActiveModel
27
+ extend Shoulda::Matchers::ActiveModel
19
28
  end
@@ -8,11 +8,11 @@ class ConfigurationTest < Test::Unit::TestCase
8
8
 
9
9
  should "have read in config.yml" do
10
10
  assert CloudCrowd.config[:max_workers] == 10
11
- assert CloudCrowd.config[:storage] == 'filesystem'
11
+ #assert CloudCrowd.config[:storage] == 'filesystem'
12
12
  end
13
13
 
14
14
  should "allow config.yml to configure the implementation of AssetStore" do
15
- assert CloudCrowd::AssetStore.ancestors.include?(CloudCrowd::AssetStore::FilesystemStore)
15
+ #assert CloudCrowd::AssetStore.ancestors.include?(CloudCrowd::AssetStore::FilesystemStore)
16
16
  end
17
17
 
18
18
  should "have properly configured the ActiveRecord database" do
@@ -5,15 +5,17 @@ class JobTest < Test::Unit::TestCase
5
5
  context "A CloudCrowd Job" do
6
6
 
7
7
  setup do
8
- @job = Job.make
8
+ @job = Job.make!
9
9
  @unit = @job.work_units.first
10
10
  end
11
11
 
12
12
  subject { @job }
13
13
 
14
- should_have_many :work_units
14
+ should have_many(:work_units)
15
15
 
16
- should_validate_presence_of :status, :inputs, :action, :options
16
+ [:status, :inputs, :action, :options].each do |field|
17
+ should validate_presence_of(field)
18
+ end
17
19
 
18
20
  should "create all of its work units as soon as the job is created" do
19
21
  assert @job.work_units.count >= 1
@@ -87,12 +89,10 @@ class JobTest < Test::Unit::TestCase
87
89
  end
88
90
 
89
91
  should "be able to clean up jobs that have aged beyond their use" do
90
- count = Job.count
91
92
  Job.cleanup_all
92
- assert count == Job.count
93
- Job.record_timestamps = false
94
- @job.update_attributes :status => SUCCEEDED, :updated_at => 10.days.ago
95
- Job.record_timestamps = true
93
+ count = Job.count
94
+ @job.update_attributes({:status => SUCCEEDED, :updated_at => 10.days.ago })
95
+ assert @job.status == SUCCEEDED
96
96
  Job.cleanup_all
97
97
  assert count > Job.count
98
98
  assert !Job.find_by_id(@job.id)
@@ -5,7 +5,7 @@ class NodeUnitTest < Test::Unit::TestCase
5
5
  context "A Node" do
6
6
 
7
7
  setup do
8
- @node = Node.new(:port => 11011, :tag => "nodule").instance_variable_get(:@app)
8
+ @node = Node.new(:port => 11011, :tag => "nodule").instance_variable_get(:@instance)
9
9
  end
10
10
 
11
11
  should "set the identity of the Ruby instance" do
@@ -5,14 +5,16 @@ class NodeRecordTest < Test::Unit::TestCase
5
5
  context "A NodeRecord" do
6
6
 
7
7
  setup do
8
- @node = CloudCrowd::NodeRecord.make
8
+ @node = CloudCrowd::NodeRecord.make!
9
9
  end
10
10
 
11
11
  subject { @node }
12
12
 
13
- should_have_many :work_units
13
+ should have_many :work_units
14
14
 
15
- should_validate_presence_of :host, :ip_address, :port, :enabled_actions
15
+ [:host, :ip_address, :port, :enabled_actions].each do |field|
16
+ should validate_presence_of(field)
17
+ end
16
18
 
17
19
  should "be available" do
18
20
  assert NodeRecord.available.map(&:id).include? @node.id
@@ -26,7 +28,7 @@ class NodeRecordTest < Test::Unit::TestCase
26
28
  should "know if the node is busy" do
27
29
  assert !@node.busy?
28
30
  assert @node.display_status == 'available'
29
- (@node.max_workers + 1).times { WorkUnit.make(:node_record => @node) }
31
+ (@node.max_workers + 1).times { WorkUnit.make!(:node_record => @node) }
30
32
  assert @node.busy?
31
33
  assert @node.display_status == 'busy'
32
34
  @node.release_work_units
@@ -5,15 +5,17 @@ class WorkUnitTest < Test::Unit::TestCase
5
5
  context "A WorkUnit" do
6
6
 
7
7
  setup do
8
- @unit = CloudCrowd::WorkUnit.make
8
+ @unit = CloudCrowd::WorkUnit.make!
9
9
  @job = @unit.job
10
10
  end
11
11
 
12
12
  subject { @unit }
13
13
 
14
- should_belong_to :job
14
+ should belong_to :job
15
15
 
16
- should_validate_presence_of :job_id, :status, :input, :action
16
+ [:job_id, :status, :input, :action].each do |field|
17
+ should validate_presence_of(field)
18
+ end
17
19
 
18
20
  should "know if its done" do
19
21
  assert !@unit.complete?
@@ -24,7 +26,7 @@ class WorkUnitTest < Test::Unit::TestCase
24
26
  end
25
27
 
26
28
  should "have JSON that includes job attributes" do
27
- job = Job.make
29
+ job = Job.make!
28
30
  unit_data = JSON.parse(job.work_units.first.to_json)
29
31
  assert unit_data['job_id'] == job.id
30
32
  assert unit_data['action'] == job.action
@@ -5,8 +5,8 @@ class WorkerTest < Test::Unit::TestCase
5
5
  context "A CloudCrowd::Worker" do
6
6
 
7
7
  setup do
8
- @node = Node.new.instance_variable_get(:@app)
9
- @unit = WorkUnit.make
8
+ @node = Node.new.instance_variable_get(:"@instance")
9
+ @unit = WorkUnit.make!
10
10
  @worker = Worker.new(@node, JSON.parse(@unit.to_json))
11
11
  end
12
12
 
metadata CHANGED
@@ -1,220 +1,63 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: cloud-crowd
3
- version: !ruby/object:Gem::Version
4
- hash: 3
5
- prerelease:
6
- segments:
7
- - 0
8
- - 6
9
- - 2
10
- version: 0.6.2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.0.pre
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Jeremy Ashkenas
8
+ - Ted Han
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-04-14 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: sinatra
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ~>
27
- - !ruby/object:Gem::Version
28
- hash: 25
29
- segments:
30
- - 0
31
- - 9
32
- version: "0.9"
33
- type: :runtime
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: activerecord
37
- prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
39
- none: false
40
- requirements:
41
- - - ~>
42
- - !ruby/object:Gem::Version
43
- hash: 5
44
- segments:
45
- - 2
46
- - 3
47
- version: "2.3"
48
- type: :runtime
49
- version_requirements: *id002
50
- - !ruby/object:Gem::Dependency
51
- name: json
52
- prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
54
- none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- hash: 29
59
- segments:
60
- - 1
61
- - 1
62
- - 7
63
- version: 1.1.7
64
- type: :runtime
65
- version_requirements: *id003
66
- - !ruby/object:Gem::Dependency
67
- name: rest-client
68
- prerelease: false
69
- requirement: &id004 !ruby/object:Gem::Requirement
70
- none: false
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- hash: 7
75
- segments:
76
- - 1
77
- - 4
78
- version: "1.4"
79
- type: :runtime
80
- version_requirements: *id004
81
- - !ruby/object:Gem::Dependency
82
- name: thin
83
- prerelease: false
84
- requirement: &id005 !ruby/object:Gem::Requirement
85
- none: false
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- hash: 23
90
- segments:
91
- - 1
92
- - 2
93
- - 4
94
- version: 1.2.4
95
- type: :runtime
96
- version_requirements: *id005
97
- - !ruby/object:Gem::Dependency
98
- name: faker
99
- prerelease: false
100
- requirement: &id006 !ruby/object:Gem::Requirement
101
- none: false
102
- requirements:
103
- - - ">="
104
- - !ruby/object:Gem::Version
105
- hash: 17
106
- segments:
107
- - 0
108
- - 3
109
- - 1
110
- version: 0.3.1
111
- type: :development
112
- version_requirements: *id006
113
- - !ruby/object:Gem::Dependency
114
- name: thoughtbot-shoulda
115
- prerelease: false
116
- requirement: &id007 !ruby/object:Gem::Requirement
117
- none: false
118
- requirements:
119
- - - ">="
120
- - !ruby/object:Gem::Version
121
- hash: 35
122
- segments:
123
- - 2
124
- - 10
125
- - 2
126
- version: 2.10.2
127
- type: :development
128
- version_requirements: *id007
129
- - !ruby/object:Gem::Dependency
130
- name: notahat-machinist
131
- prerelease: false
132
- requirement: &id008 !ruby/object:Gem::Requirement
133
- none: false
134
- requirements:
135
- - - ">="
136
- - !ruby/object:Gem::Version
137
- hash: 17
138
- segments:
139
- - 1
140
- - 0
141
- - 3
142
- version: 1.0.3
143
- type: :development
144
- version_requirements: *id008
145
- - !ruby/object:Gem::Dependency
146
- name: rack-test
147
- prerelease: false
148
- requirement: &id009 !ruby/object:Gem::Requirement
149
- none: false
150
- requirements:
151
- - - ">="
152
- - !ruby/object:Gem::Version
153
- hash: 13
154
- segments:
155
- - 0
156
- - 4
157
- - 1
158
- version: 0.4.1
159
- type: :development
160
- version_requirements: *id009
161
- - !ruby/object:Gem::Dependency
162
- name: mocha
163
- prerelease: false
164
- requirement: &id010 !ruby/object:Gem::Requirement
165
- none: false
166
- requirements:
167
- - - ">="
168
- - !ruby/object:Gem::Version
169
- hash: 53
170
- segments:
171
- - 0
172
- - 9
173
- - 7
174
- version: 0.9.7
175
- type: :development
176
- version_requirements: *id010
177
- description: " The crowd, suddenly there where there was nothing before, is a mysterious and\n universal phenomenon. A few people may have been standing together -- five, ten\n or twelve, nor more; nothing has been announced, nothing is expected. Suddenly\n everywhere is black with people and more come streaming from all sides as though\n streets had only one direction.\n"
178
- email: jeremy@documentcloud.org
179
- executables:
12
+ date: 2014-03-08 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: |2
15
+ The crowd, suddenly there where there was nothing before, is a mysterious and
16
+ universal phenomenon. A few people may have been standing together -- five, ten
17
+ or twelve, nor more; nothing has been announced, nothing is expected. Suddenly
18
+ everywhere is black with people and more come streaming from all sides as though
19
+ streets had only one direction.
20
+ email: opensource@documentcloud.org
21
+ executables:
180
22
  - crowd
181
23
  extensions: []
182
-
183
- extra_rdoc_files:
24
+ extra_rdoc_files:
25
+ - README
26
+ files:
27
+ - EPIGRAPHS
28
+ - LICENSE
184
29
  - README
185
- files:
186
30
  - actions/graphics_magick.rb
187
31
  - actions/process_pdfs.rb
188
32
  - actions/word_count.rb
33
+ - bin/crowd
189
34
  - cloud-crowd.gemspec
190
35
  - config/config.example.ru
191
36
  - config/config.example.yml
192
37
  - config/database.example.yml
193
- - EPIGRAPHS
194
38
  - examples/graphics_magick_example.rb
195
39
  - examples/process_pdfs_example.rb
196
40
  - examples/word_count_example.rb
197
41
  - lib/cloud-crowd.rb
198
42
  - lib/cloud_crowd/action.rb
43
+ - lib/cloud_crowd/asset_store.rb
44
+ - lib/cloud_crowd/asset_store/cloudfiles_store.rb
199
45
  - lib/cloud_crowd/asset_store/filesystem_store.rb
200
46
  - lib/cloud_crowd/asset_store/s3_store.rb
201
- - lib/cloud_crowd/asset_store/cloudfiles_store.rb
202
- - lib/cloud_crowd/asset_store.rb
203
47
  - lib/cloud_crowd/command_line.rb
204
48
  - lib/cloud_crowd/exceptions.rb
49
+ - lib/cloud_crowd/helpers.rb
205
50
  - lib/cloud_crowd/helpers/authorization.rb
206
51
  - lib/cloud_crowd/helpers/resources.rb
207
- - lib/cloud_crowd/helpers.rb
208
52
  - lib/cloud_crowd/inflector.rb
53
+ - lib/cloud_crowd/models.rb
209
54
  - lib/cloud_crowd/models/job.rb
210
55
  - lib/cloud_crowd/models/node_record.rb
211
56
  - lib/cloud_crowd/models/work_unit.rb
212
- - lib/cloud_crowd/models.rb
213
57
  - lib/cloud_crowd/node.rb
214
58
  - lib/cloud_crowd/schema.rb
215
59
  - lib/cloud_crowd/server.rb
216
60
  - lib/cloud_crowd/worker.rb
217
- - LICENSE
218
61
  - public/css/admin_console.css
219
62
  - public/css/reset.css
220
63
  - public/images/bullet_green.png
@@ -234,64 +77,53 @@ files:
234
77
  - public/js/excanvas.js
235
78
  - public/js/flot.js
236
79
  - public/js/jquery.js
237
- - README
238
- - test/acceptance/test_node.rb
239
80
  - test/acceptance/test_failing_work_units.rb
81
+ - test/acceptance/test_node.rb
240
82
  - test/acceptance/test_server.rb
241
83
  - test/acceptance/test_word_count.rb
242
84
  - test/blueprints.rb
85
+ - test/config/actions/failure_testing.rb
243
86
  - test/config/config.ru
244
87
  - test/config/config.yml
245
88
  - test/config/database.yml
246
- - test/config/actions/failure_testing.rb
247
89
  - test/test_helper.rb
248
90
  - test/unit/test_action.rb
249
91
  - test/unit/test_configuration.rb
92
+ - test/unit/test_job.rb
250
93
  - test/unit/test_node.rb
251
94
  - test/unit/test_node_record.rb
252
- - test/unit/test_job.rb
253
- - test/unit/test_worker.rb
254
95
  - test/unit/test_work_unit.rb
96
+ - test/unit/test_worker.rb
255
97
  - views/operations_center.erb
256
- - bin/crowd
257
98
  homepage: http://wiki.github.com/documentcloud/cloud-crowd
258
- licenses: []
259
-
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
260
102
  post_install_message:
261
- rdoc_options:
262
- - --title
103
+ rdoc_options:
104
+ - "--title"
263
105
  - CloudCrowd | Parallel Processing for the Rest of Us
264
- - --exclude
106
+ - "--exclude"
265
107
  - test
266
- - --main
108
+ - "--main"
267
109
  - README
268
- - --all
269
- require_paths:
110
+ - "--all"
111
+ require_paths:
270
112
  - lib
271
- required_ruby_version: !ruby/object:Gem::Requirement
272
- none: false
273
- requirements:
274
- - - ">="
275
- - !ruby/object:Gem::Version
276
- hash: 3
277
- segments:
278
- - 0
279
- version: "0"
280
- required_rubygems_version: !ruby/object:Gem::Requirement
281
- none: false
282
- requirements:
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
283
115
  - - ">="
284
- - !ruby/object:Gem::Version
285
- hash: 3
286
- segments:
287
- - 0
288
- version: "0"
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">"
121
+ - !ruby/object:Gem::Version
122
+ version: 1.3.1
289
123
  requirements: []
290
-
291
124
  rubyforge_project: cloud-crowd
292
- rubygems_version: 1.7.2
125
+ rubygems_version: 2.2.1
293
126
  signing_key:
294
- specification_version: 3
127
+ specification_version: 4
295
128
  summary: Parallel Processing for the Rest of Us
296
129
  test_files: []
297
-