mooktakim-cloud-crowd 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
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
+