mooktakim-cloud-crowd 0.3.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.
Files changed (71) hide show
  1. data/EPIGRAPHS +17 -0
  2. data/LICENSE +22 -0
  3. data/README +93 -0
  4. data/actions/graphics_magick.rb +43 -0
  5. data/actions/process_pdfs.rb +92 -0
  6. data/actions/word_count.rb +16 -0
  7. data/bin/crowd +5 -0
  8. data/config/config.example.ru +23 -0
  9. data/config/config.example.yml +55 -0
  10. data/config/database.example.yml +16 -0
  11. data/examples/graphics_magick_example.rb +44 -0
  12. data/examples/process_pdfs_example.rb +40 -0
  13. data/examples/word_count_example.rb +42 -0
  14. data/lib/cloud-crowd.rb +188 -0
  15. data/lib/cloud_crowd/action.rb +125 -0
  16. data/lib/cloud_crowd/asset_store/filesystem_store.rb +39 -0
  17. data/lib/cloud_crowd/asset_store/s3_store.rb +43 -0
  18. data/lib/cloud_crowd/asset_store.rb +41 -0
  19. data/lib/cloud_crowd/command_line.rb +242 -0
  20. data/lib/cloud_crowd/exceptions.rb +46 -0
  21. data/lib/cloud_crowd/helpers/authorization.rb +52 -0
  22. data/lib/cloud_crowd/helpers/resources.rb +25 -0
  23. data/lib/cloud_crowd/helpers.rb +8 -0
  24. data/lib/cloud_crowd/inflector.rb +19 -0
  25. data/lib/cloud_crowd/models/job.rb +190 -0
  26. data/lib/cloud_crowd/models/node_record.rb +107 -0
  27. data/lib/cloud_crowd/models/work_unit.rb +170 -0
  28. data/lib/cloud_crowd/models.rb +40 -0
  29. data/lib/cloud_crowd/node.rb +199 -0
  30. data/lib/cloud_crowd/schema.rb +50 -0
  31. data/lib/cloud_crowd/server.rb +123 -0
  32. data/lib/cloud_crowd/worker.rb +149 -0
  33. data/mooktakim-cloud-crowd.gemspec +116 -0
  34. data/public/css/admin_console.css +243 -0
  35. data/public/css/reset.css +42 -0
  36. data/public/images/bullet_green.png +0 -0
  37. data/public/images/bullet_white.png +0 -0
  38. data/public/images/cloud_hand.png +0 -0
  39. data/public/images/header_back.png +0 -0
  40. data/public/images/logo.png +0 -0
  41. data/public/images/queue_fill.png +0 -0
  42. data/public/images/server.png +0 -0
  43. data/public/images/server_busy.png +0 -0
  44. data/public/images/server_error.png +0 -0
  45. data/public/images/sidebar_bottom.png +0 -0
  46. data/public/images/sidebar_top.png +0 -0
  47. data/public/images/worker_info.png +0 -0
  48. data/public/images/worker_info_loading.gif +0 -0
  49. data/public/js/admin_console.js +197 -0
  50. data/public/js/excanvas.js +1 -0
  51. data/public/js/flot.js +1 -0
  52. data/public/js/jquery.js +19 -0
  53. data/test/acceptance/test_failing_work_units.rb +33 -0
  54. data/test/acceptance/test_node.rb +20 -0
  55. data/test/acceptance/test_server.rb +66 -0
  56. data/test/acceptance/test_word_count.rb +40 -0
  57. data/test/blueprints.rb +25 -0
  58. data/test/config/actions/failure_testing.rb +13 -0
  59. data/test/config/config.ru +17 -0
  60. data/test/config/config.yml +6 -0
  61. data/test/config/database.yml +3 -0
  62. data/test/test_helper.rb +19 -0
  63. data/test/unit/test_action.rb +70 -0
  64. data/test/unit/test_configuration.rb +48 -0
  65. data/test/unit/test_job.rb +103 -0
  66. data/test/unit/test_node.rb +41 -0
  67. data/test/unit/test_node_record.rb +42 -0
  68. data/test/unit/test_work_unit.rb +53 -0
  69. data/test/unit/test_worker.rb +48 -0
  70. data/views/operations_center.erb +82 -0
  71. metadata +290 -0
@@ -0,0 +1,41 @@
1
+ require 'test_helper'
2
+
3
+ class NodeUnitTest < Test::Unit::TestCase
4
+
5
+ context "A Node" do
6
+
7
+ setup do
8
+ @node = Node.new(11011).instance_variable_get(:@app)
9
+ end
10
+
11
+ should "set the identity of the Ruby instance" do
12
+ assert CloudCrowd.node?
13
+ end
14
+
15
+ should "instantiate correctly" do
16
+ assert @node.central.to_s == "http://localhost:9173"
17
+ assert @node.port == 11011
18
+ assert @node.host == Socket.gethostname
19
+ assert @node.enabled_actions.length > 2
20
+ assert @node.asset_store.is_a? AssetStore::FilesystemStore
21
+ end
22
+
23
+ should "trap signals and launch a server at start" do
24
+ Thin::Server.any_instance.expects(:start)
25
+ @node.expects(:check_in)
26
+ @node.start
27
+ end
28
+
29
+ should "be able to determine if the node is overloaded" do
30
+ assert !@node.overloaded?
31
+ @node.instance_variable_set :@max_load, 0.01
32
+ assert @node.overloaded?
33
+ @node.instance_variable_set :@max_load, nil
34
+ assert !@node.overloaded?
35
+ @node.instance_variable_set :@min_memory, 8000
36
+ assert @node.overloaded?
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,42 @@
1
+ require 'test_helper'
2
+
3
+ class NodeRecordTest < Test::Unit::TestCase
4
+
5
+ context "A NodeRecord" do
6
+
7
+ setup do
8
+ @node = CloudCrowd::NodeRecord.make
9
+ end
10
+
11
+ subject { @node }
12
+
13
+ should_have_many :work_units
14
+
15
+ should_validate_presence_of :host, :ip_address, :port, :enabled_actions
16
+
17
+ should "be available" do
18
+ assert NodeRecord.available.map(&:id).include? @node.id
19
+ end
20
+
21
+ should "know its enabled actions" do
22
+ assert @node.actions.include? 'graphics_magick'
23
+ assert @node.actions.include? 'word_count'
24
+ end
25
+
26
+ should "know if the node is busy" do
27
+ assert !@node.busy?
28
+ assert @node.display_status == 'available'
29
+ (@node.max_workers + 1).times { WorkUnit.make(:node_record => @node) }
30
+ assert @node.busy?
31
+ assert @node.display_status == 'busy'
32
+ @node.release_work_units
33
+ assert !@node.busy?
34
+ end
35
+
36
+ should "be reachable at a URL" do
37
+ assert !!URI.parse(@node.url)
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+
3
+ class WorkUnitTest < Test::Unit::TestCase
4
+
5
+ context "A WorkUnit" do
6
+
7
+ setup do
8
+ @unit = CloudCrowd::WorkUnit.make
9
+ @job = @unit.job
10
+ end
11
+
12
+ subject { @unit }
13
+
14
+ should_belong_to :job
15
+
16
+ should_validate_presence_of :job_id, :status, :input, :action
17
+
18
+ should "know if its done" do
19
+ assert !@unit.complete?
20
+ @unit.status = SUCCEEDED
21
+ assert @unit.complete?
22
+ @unit.status = FAILED
23
+ assert @unit.complete?
24
+ end
25
+
26
+ should "have JSON that includes job attributes" do
27
+ job = Job.make
28
+ unit_data = JSON.parse(job.work_units.first.to_json)
29
+ assert unit_data['job_id'] == job.id
30
+ assert unit_data['action'] == job.action
31
+ assert JSON.parse(job.inputs).include? unit_data['input']
32
+ end
33
+
34
+ should "be able to retry, on failure" do
35
+ @unit.update_attribute :worker_pid, 7337
36
+ assert @unit.attempts == 0
37
+ @unit.fail('oops', 10)
38
+ assert @unit.worker_pid == nil
39
+ assert @unit.attempts == 1
40
+ assert @unit.processing?
41
+ @unit.fail('oops again', 10)
42
+ assert @unit.attempts == 2
43
+ assert @unit.processing?
44
+ assert @unit.job.processing?
45
+ @unit.fail('oops one last time', 10)
46
+ assert @unit.attempts == 3
47
+ assert @unit.failed?
48
+ assert @unit.job.any_work_units_failed?
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,48 @@
1
+ require 'test_helper'
2
+
3
+ class WorkerTest < Test::Unit::TestCase
4
+
5
+ context "A CloudCrowd::Worker" do
6
+
7
+ setup do
8
+ @node = Node.new.instance_variable_get(:@app)
9
+ @unit = WorkUnit.make
10
+ @worker = Worker.new(@node, JSON.parse(@unit.to_json))
11
+ end
12
+
13
+ should "instantiate correctly" do
14
+ assert @worker.pid == $$
15
+ assert @worker.unit['id'] == @unit.id
16
+ assert @worker.status == @unit.status
17
+ assert @worker.node == @node
18
+ assert @worker.time_taken > 0
19
+ end
20
+
21
+ should "be able to retry operations that must succeed" do
22
+ @worker.instance_variable_set :@retry_wait, 0.01
23
+ @worker.expects(:log).at_least(3)
24
+ tries = 0
25
+ @worker.keep_trying_to("do something critical") do
26
+ tries += 1;
27
+ raise 'hell' unless tries > 3
28
+ assert "made it through"
29
+ end
30
+ end
31
+
32
+ should "be able to run an action and try to complete it" do
33
+ GraphicsMagick.any_instance.expects(:process).returns('the answer')
34
+ GraphicsMagick.any_instance.expects(:cleanup_work_directory)
35
+ @worker.expects(:complete_work_unit).with({'output' => 'the answer'}.to_json)
36
+ @worker.run_work_unit
37
+ end
38
+
39
+ should "enchance the options that an action receives with extra info" do
40
+ opts = @worker.enhanced_unit_options
41
+ assert opts['work_unit_id'] == @unit.id
42
+ assert opts['job_id'] == @unit.job.id
43
+ assert opts['attempts'] == @unit.attempts
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,82 @@
1
+ <!DOCTYPE html>
2
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
5
+ <title>Operations Center | CloudCrowd</title>
6
+ <link href="css/reset.css" media="screen" rel="stylesheet" type="text/css" />
7
+ <link href="css/admin_console.css" media="screen" rel="stylesheet" type="text/css" />
8
+ <script src="js/jquery.js" type="text/javascript"></script>
9
+ <!--[if IE]><script src="js/excanvas.js" type="text/javascript"></script><![endif]-->
10
+ <script src="js/flot.js" type="text/javascript"></script>
11
+ <script src="js/admin_console.js" type="text/javascript"></script>
12
+ </head>
13
+
14
+ <body>
15
+ <div id="container">
16
+
17
+ <div id="header">
18
+ <div id="logo"></div>
19
+ </div>
20
+
21
+ <div id="disconnected" class="small_caps" style="display:none;">
22
+ <div class="server_error"></div>
23
+ Disconnected. Attempting to reconnect&hellip;
24
+ </div>
25
+
26
+ <div id="queue">
27
+ <div id="no_jobs" class="small_caps">no jobs running&hellip;</div>
28
+ <div id="jobs">
29
+ <%# Render target for jobs. %>
30
+ </div>
31
+ <div id="queue_fill"></div>
32
+ </div>
33
+
34
+ <div id="sidebar">
35
+ <div id="sidebar_top" class="sidebar_back"></div>
36
+ <div id="sidebar_background"></div>
37
+ <div id="sidebar_bottom" class="sidebar_back"></div>
38
+ <div id="sidebar_header" class="small_caps">
39
+ <span class="has_nodes"></span>
40
+ <span class="no_nodes">No Nodes Online&hellip;</span>
41
+ </div>
42
+ <div id="nodes">
43
+ <%# Render target for nodes and workers. %>
44
+ </div>
45
+ </div>
46
+
47
+ <div id="graphs">
48
+ <div class="graph_container">
49
+ <div class="graph_title">Work Units in Queue</div>
50
+ <div id="work_units_graph" class="graph"></div>
51
+ </div>
52
+ <div class="graph_container">
53
+ <div class="graph_title">Jobs in Queue</div>
54
+ <div id="jobs_graph" class="graph"></div>
55
+ </div>
56
+ <div class="graph_container">
57
+ <div class="graph_title">
58
+ Active Nodes
59
+ (<span id="nodes_legend" class="legend_box"></span>)
60
+ and Workers
61
+ (<span id="workers_legend" class="legend_box"></span>)
62
+ </div>
63
+ <div id="workers_graph" class="graph"></div>
64
+ </div>
65
+ </div>
66
+
67
+ <div id="worker_info" style="display:none;">
68
+ <div id="worker_info_inner" class="small_caps">
69
+ <div id="worker_details">
70
+ <div id="worker_status">status: <span class="status"></span></div>
71
+ <div id="worker_action">action:&nbsp;<span class="action"></span></div>
72
+ <div id="worker_job_id">job #<span class="job_id"></span> / unit #<span class="work_unit_id"></span></div>
73
+ </div>
74
+ <div id="worker_sleeping">
75
+ worker exiting&hellip;
76
+ </div>
77
+ </div>
78
+ </div>
79
+
80
+ </div>
81
+ </body>
82
+ </html>
metadata ADDED
@@ -0,0 +1,290 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mooktakim-cloud-crowd
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 4
9
+ version: 0.3.4
10
+ platform: ruby
11
+ authors:
12
+ - Jeremy Ashkenas
13
+ - Mooktakim Ahmed
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-02-26 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: sinatra
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 9
31
+ - 4
32
+ version: 0.9.4
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
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 2
44
+ - 3
45
+ - 3
46
+ version: 2.3.3
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: json
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 1
58
+ - 1
59
+ - 7
60
+ version: 1.1.7
61
+ type: :runtime
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: rest-client
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 1
72
+ - 0
73
+ - 3
74
+ version: 1.0.3
75
+ type: :runtime
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: right_aws
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 1
86
+ - 10
87
+ - 0
88
+ version: 1.10.0
89
+ type: :runtime
90
+ version_requirements: *id005
91
+ - !ruby/object:Gem::Dependency
92
+ name: thin
93
+ prerelease: false
94
+ requirement: &id006 !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ segments:
99
+ - 1
100
+ - 2
101
+ - 4
102
+ version: 1.2.4
103
+ type: :runtime
104
+ version_requirements: *id006
105
+ - !ruby/object:Gem::Dependency
106
+ name: faker
107
+ prerelease: false
108
+ requirement: &id007 !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ segments:
113
+ - 0
114
+ - 3
115
+ - 1
116
+ version: 0.3.1
117
+ type: :development
118
+ version_requirements: *id007
119
+ - !ruby/object:Gem::Dependency
120
+ name: thoughtbot-shoulda
121
+ prerelease: false
122
+ requirement: &id008 !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ segments:
127
+ - 2
128
+ - 10
129
+ - 2
130
+ version: 2.10.2
131
+ type: :development
132
+ version_requirements: *id008
133
+ - !ruby/object:Gem::Dependency
134
+ name: notahat-machinist
135
+ prerelease: false
136
+ requirement: &id009 !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ segments:
141
+ - 1
142
+ - 0
143
+ - 3
144
+ version: 1.0.3
145
+ type: :development
146
+ version_requirements: *id009
147
+ - !ruby/object:Gem::Dependency
148
+ name: rack-test
149
+ prerelease: false
150
+ requirement: &id010 !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ segments:
155
+ - 0
156
+ - 4
157
+ - 1
158
+ version: 0.4.1
159
+ type: :development
160
+ version_requirements: *id010
161
+ - !ruby/object:Gem::Dependency
162
+ name: mocha
163
+ prerelease: false
164
+ requirement: &id011 !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ segments:
169
+ - 0
170
+ - 9
171
+ - 7
172
+ version: 0.9.7
173
+ type: :development
174
+ version_requirements: *id011
175
+ 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"
176
+ email: jeremy@documentcloud.org
177
+ executables:
178
+ - crowd
179
+ extensions: []
180
+
181
+ extra_rdoc_files:
182
+ - README
183
+ files:
184
+ - actions/graphics_magick.rb
185
+ - actions/process_pdfs.rb
186
+ - actions/word_count.rb
187
+ - mooktakim-cloud-crowd.gemspec
188
+ - config/config.example.ru
189
+ - config/config.example.yml
190
+ - config/database.example.yml
191
+ - EPIGRAPHS
192
+ - examples/graphics_magick_example.rb
193
+ - examples/process_pdfs_example.rb
194
+ - examples/word_count_example.rb
195
+ - lib/cloud-crowd.rb
196
+ - lib/cloud_crowd/action.rb
197
+ - lib/cloud_crowd/asset_store/filesystem_store.rb
198
+ - lib/cloud_crowd/asset_store/s3_store.rb
199
+ - lib/cloud_crowd/asset_store.rb
200
+ - lib/cloud_crowd/command_line.rb
201
+ - lib/cloud_crowd/exceptions.rb
202
+ - lib/cloud_crowd/helpers/authorization.rb
203
+ - lib/cloud_crowd/helpers/resources.rb
204
+ - lib/cloud_crowd/helpers.rb
205
+ - lib/cloud_crowd/inflector.rb
206
+ - lib/cloud_crowd/models/job.rb
207
+ - lib/cloud_crowd/models/node_record.rb
208
+ - lib/cloud_crowd/models/work_unit.rb
209
+ - lib/cloud_crowd/models.rb
210
+ - lib/cloud_crowd/node.rb
211
+ - lib/cloud_crowd/schema.rb
212
+ - lib/cloud_crowd/server.rb
213
+ - lib/cloud_crowd/worker.rb
214
+ - LICENSE
215
+ - public/css/admin_console.css
216
+ - public/css/reset.css
217
+ - public/images/bullet_green.png
218
+ - public/images/bullet_white.png
219
+ - public/images/cloud_hand.png
220
+ - public/images/header_back.png
221
+ - public/images/logo.png
222
+ - public/images/queue_fill.png
223
+ - public/images/server.png
224
+ - public/images/server_busy.png
225
+ - public/images/server_error.png
226
+ - public/images/sidebar_bottom.png
227
+ - public/images/sidebar_top.png
228
+ - public/images/worker_info.png
229
+ - public/images/worker_info_loading.gif
230
+ - public/js/admin_console.js
231
+ - public/js/excanvas.js
232
+ - public/js/flot.js
233
+ - public/js/jquery.js
234
+ - README
235
+ - test/acceptance/test_node.rb
236
+ - test/acceptance/test_failing_work_units.rb
237
+ - test/acceptance/test_server.rb
238
+ - test/acceptance/test_word_count.rb
239
+ - test/blueprints.rb
240
+ - test/config/config.ru
241
+ - test/config/config.yml
242
+ - test/config/database.yml
243
+ - test/config/actions/failure_testing.rb
244
+ - test/test_helper.rb
245
+ - test/unit/test_action.rb
246
+ - test/unit/test_configuration.rb
247
+ - test/unit/test_node.rb
248
+ - test/unit/test_node_record.rb
249
+ - test/unit/test_job.rb
250
+ - test/unit/test_worker.rb
251
+ - test/unit/test_work_unit.rb
252
+ - views/operations_center.erb
253
+ has_rdoc: true
254
+ homepage: http://wiki.github.com/documentcloud/cloud-crowd
255
+ licenses: []
256
+
257
+ post_install_message:
258
+ rdoc_options:
259
+ - --title
260
+ - CloudCrowd | Parallel Processing for the Rest of Us
261
+ - --exclude
262
+ - test
263
+ - --main
264
+ - README
265
+ - --all
266
+ require_paths:
267
+ - lib
268
+ required_ruby_version: !ruby/object:Gem::Requirement
269
+ requirements:
270
+ - - ">="
271
+ - !ruby/object:Gem::Version
272
+ segments:
273
+ - 0
274
+ version: "0"
275
+ required_rubygems_version: !ruby/object:Gem::Requirement
276
+ requirements:
277
+ - - ">="
278
+ - !ruby/object:Gem::Version
279
+ segments:
280
+ - 0
281
+ version: "0"
282
+ requirements: []
283
+
284
+ rubyforge_project: cloud-crowd
285
+ rubygems_version: 1.3.6
286
+ signing_key:
287
+ specification_version: 3
288
+ summary: Parallel Processing for the Rest of Us
289
+ test_files: []
290
+