timocratic-skynet 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. data/History.txt +152 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +144 -0
  4. data/README.txt +178 -0
  5. data/Rakefile +5 -0
  6. data/app_generators/skynet_install/USAGE +5 -0
  7. data/app_generators/skynet_install/skynet_install_generator.rb +94 -0
  8. data/app_generators/skynet_install/templates/migration.rb +43 -0
  9. data/app_generators/skynet_install/templates/skynet_config.rb +50 -0
  10. data/app_generators/skynet_install/templates/skynet_initializer.rb +1 -0
  11. data/app_generators/skynet_install/templates/skynet_mysql_schema.sql +33 -0
  12. data/bin/skynet +71 -0
  13. data/bin/skynet_install +36 -0
  14. data/bin/skynet_tuplespace_server +74 -0
  15. data/config/hoe.rb +75 -0
  16. data/config/requirements.rb +17 -0
  17. data/examples/dgrep/README +70 -0
  18. data/examples/dgrep/config/skynet_config.rb +26 -0
  19. data/examples/dgrep/data/shakespeare/README +2 -0
  20. data/examples/dgrep/data/shakespeare/poetry/loverscomplaint +381 -0
  21. data/examples/dgrep/data/shakespeare/poetry/rapeoflucrece +2199 -0
  22. data/examples/dgrep/data/shakespeare/poetry/sonnets +2633 -0
  23. data/examples/dgrep/data/shakespeare/poetry/various +640 -0
  24. data/examples/dgrep/data/shakespeare/poetry/venusandadonis +1423 -0
  25. data/examples/dgrep/data/testfile1.txt +1 -0
  26. data/examples/dgrep/data/testfile2.txt +1 -0
  27. data/examples/dgrep/data/testfile3.txt +1 -0
  28. data/examples/dgrep/data/testfile4.txt +1 -0
  29. data/examples/dgrep/lib/dgrep.rb +59 -0
  30. data/examples/dgrep/lib/mapreduce_test.rb +32 -0
  31. data/examples/dgrep/lib/most_common_words.rb +45 -0
  32. data/examples/dgrep/script/dgrep +75 -0
  33. data/examples/rails_mysql_example/README +66 -0
  34. data/examples/rails_mysql_example/Rakefile +10 -0
  35. data/examples/rails_mysql_example/app/controllers/application.rb +10 -0
  36. data/examples/rails_mysql_example/app/helpers/application_helper.rb +3 -0
  37. data/examples/rails_mysql_example/app/models/user.rb +21 -0
  38. data/examples/rails_mysql_example/app/models/user_favorite.rb +5 -0
  39. data/examples/rails_mysql_example/app/models/user_mailer.rb +12 -0
  40. data/examples/rails_mysql_example/app/views/user_mailer/welcome.erb +5 -0
  41. data/examples/rails_mysql_example/config/boot.rb +109 -0
  42. data/examples/rails_mysql_example/config/database.yml +42 -0
  43. data/examples/rails_mysql_example/config/environment.rb +59 -0
  44. data/examples/rails_mysql_example/config/environments/development.rb +18 -0
  45. data/examples/rails_mysql_example/config/environments/production.rb +19 -0
  46. data/examples/rails_mysql_example/config/environments/test.rb +22 -0
  47. data/examples/rails_mysql_example/config/initializers/inflections.rb +10 -0
  48. data/examples/rails_mysql_example/config/initializers/mime_types.rb +5 -0
  49. data/examples/rails_mysql_example/config/initializers/skynet.rb +1 -0
  50. data/examples/rails_mysql_example/config/routes.rb +35 -0
  51. data/examples/rails_mysql_example/config/skynet_config.rb +36 -0
  52. data/examples/rails_mysql_example/db/migrate/001_create_skynet_tables.rb +43 -0
  53. data/examples/rails_mysql_example/db/migrate/002_create_users.rb +16 -0
  54. data/examples/rails_mysql_example/db/migrate/003_create_user_favorites.rb +14 -0
  55. data/examples/rails_mysql_example/db/schema.rb +85 -0
  56. data/examples/rails_mysql_example/db/skynet_mysql_schema.sql +33 -0
  57. data/examples/rails_mysql_example/doc/README_FOR_APP +2 -0
  58. data/examples/rails_mysql_example/lib/tasks/rails_mysql_example.rake +20 -0
  59. data/examples/rails_mysql_example/public/.htaccess +40 -0
  60. data/examples/rails_mysql_example/public/404.html +30 -0
  61. data/examples/rails_mysql_example/public/422.html +30 -0
  62. data/examples/rails_mysql_example/public/500.html +30 -0
  63. data/examples/rails_mysql_example/public/dispatch.cgi +10 -0
  64. data/examples/rails_mysql_example/public/dispatch.fcgi +24 -0
  65. data/examples/rails_mysql_example/public/dispatch.rb +10 -0
  66. data/examples/rails_mysql_example/public/favicon.ico +0 -0
  67. data/examples/rails_mysql_example/public/images/rails.png +0 -0
  68. data/examples/rails_mysql_example/public/index.html +277 -0
  69. data/examples/rails_mysql_example/public/javascripts/application.js +2 -0
  70. data/examples/rails_mysql_example/public/javascripts/controls.js +963 -0
  71. data/examples/rails_mysql_example/public/javascripts/dragdrop.js +972 -0
  72. data/examples/rails_mysql_example/public/javascripts/effects.js +1120 -0
  73. data/examples/rails_mysql_example/public/javascripts/prototype.js +4225 -0
  74. data/examples/rails_mysql_example/public/robots.txt +5 -0
  75. data/examples/rails_mysql_example/script/about +3 -0
  76. data/examples/rails_mysql_example/script/console +3 -0
  77. data/examples/rails_mysql_example/script/destroy +3 -0
  78. data/examples/rails_mysql_example/script/generate +3 -0
  79. data/examples/rails_mysql_example/script/performance/benchmarker +3 -0
  80. data/examples/rails_mysql_example/script/performance/profiler +3 -0
  81. data/examples/rails_mysql_example/script/performance/request +3 -0
  82. data/examples/rails_mysql_example/script/plugin +3 -0
  83. data/examples/rails_mysql_example/script/process/inspector +3 -0
  84. data/examples/rails_mysql_example/script/process/reaper +3 -0
  85. data/examples/rails_mysql_example/script/process/spawner +3 -0
  86. data/examples/rails_mysql_example/script/runner +3 -0
  87. data/examples/rails_mysql_example/script/server +3 -0
  88. data/examples/rails_mysql_example/test/fixtures/user_favorites.yml +9 -0
  89. data/examples/rails_mysql_example/test/fixtures/users.yml +11 -0
  90. data/examples/rails_mysql_example/test/test_helper.rb +38 -0
  91. data/examples/rails_mysql_example/test/unit/user_favorite_test.rb +8 -0
  92. data/examples/rails_mysql_example/test/unit/user_test.rb +8 -0
  93. data/extras/README +7 -0
  94. data/extras/init.d/skynet +87 -0
  95. data/extras/nagios/check_skynet.sh +121 -0
  96. data/extras/rails/controllers/skynet_controller.rb +43 -0
  97. data/extras/rails/views/skynet/index.rhtml +137 -0
  98. data/lib/skynet.rb +95 -0
  99. data/lib/skynet/mapreduce_helper.rb +74 -0
  100. data/lib/skynet/mapreduce_test.rb +56 -0
  101. data/lib/skynet/message_queue_adapters/message_queue_adapter.rb +70 -0
  102. data/lib/skynet/message_queue_adapters/mysql.rb +509 -0
  103. data/lib/skynet/message_queue_adapters/tuple_space.rb +316 -0
  104. data/lib/skynet/skynet_active_record_extensions.rb +280 -0
  105. data/lib/skynet/skynet_config.rb +232 -0
  106. data/lib/skynet/skynet_console.rb +50 -0
  107. data/lib/skynet/skynet_console_helper.rb +66 -0
  108. data/lib/skynet/skynet_debugger.rb +138 -0
  109. data/lib/skynet/skynet_guid_generator.rb +68 -0
  110. data/lib/skynet/skynet_job.rb +892 -0
  111. data/lib/skynet/skynet_launcher.rb +40 -0
  112. data/lib/skynet/skynet_logger.rb +62 -0
  113. data/lib/skynet/skynet_manager.rb +706 -0
  114. data/lib/skynet/skynet_message.rb +359 -0
  115. data/lib/skynet/skynet_message_queue.rb +136 -0
  116. data/lib/skynet/skynet_partitioners.rb +96 -0
  117. data/lib/skynet/skynet_ruby_extensions.rb +53 -0
  118. data/lib/skynet/skynet_task.rb +118 -0
  119. data/lib/skynet/skynet_tuplespace_server.rb +83 -0
  120. data/lib/skynet/skynet_worker.rb +451 -0
  121. data/lib/skynet/version.rb +9 -0
  122. data/script/destroy +14 -0
  123. data/script/generate +14 -0
  124. data/script/txt2html +74 -0
  125. data/setup.rb +1585 -0
  126. data/tasks/deployment.rake +34 -0
  127. data/tasks/environment.rake +7 -0
  128. data/tasks/website.rake +17 -0
  129. data/test/test_active_record_extensions.rb +138 -0
  130. data/test/test_generator_helper.rb +20 -0
  131. data/test/test_helper.rb +10 -0
  132. data/test/test_mysql_message_queue_adapter.rb +263 -0
  133. data/test/test_skynet.rb +19 -0
  134. data/test/test_skynet_install_generator.rb +49 -0
  135. data/test/test_skynet_job.rb +717 -0
  136. data/test/test_skynet_manager.rb +157 -0
  137. data/test/test_skynet_message.rb +229 -0
  138. data/test/test_skynet_task.rb +24 -0
  139. data/test/test_tuplespace_message_queue.rb +174 -0
  140. data/website/index.html +181 -0
  141. data/website/index.txt +98 -0
  142. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  143. data/website/stylesheets/screen.css +138 -0
  144. data/website/template.rhtml +48 -0
  145. metadata +247 -0
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ require 'tempfile'
4
+ class TestSkynet < Test::Unit::TestCase
5
+
6
+ # this test doesn't work on a mac
7
+ def test_fork_and_exec
8
+ Tempfile.new('control').open
9
+ file = Tempfile.new('fork_exec')
10
+ Skynet.fork_and_exec("/usr/sbin/lsof -p $$ >#{file.path}")
11
+ sleep 1
12
+ open("#{file.path}", 'r') do |f|
13
+ lines = f.readlines
14
+ assert_equal 3, lines.grep(/null/).size, "fork_and_exec should redirect 0,1,2 to dev null"
15
+ assert_equal 0, lines.grep(/control/).size, "fork_and_exec should close parent's file descriptors"
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,49 @@
1
+ require File.join(File.dirname(__FILE__), "test_generator_helper.rb")
2
+
3
+ class TestSkynetInstallGenerator < Test::Unit::TestCase
4
+ include RubiGen::GeneratorTestHelper
5
+
6
+ def setup
7
+ bare_setup
8
+ end
9
+
10
+ def teardown
11
+ bare_teardown
12
+ end
13
+
14
+ # Some generator-related assertions:
15
+ # assert_generated_file(name, &block) # block passed the file contents
16
+ # assert_directory_exists(name)
17
+ # assert_generated_class(name, &block)
18
+ # assert_generated_module(name, &block)
19
+ # assert_generated_test_for(name, &block)
20
+ # The assert_generated_(class|module|test_for) &block is passed the body of the class/module within the file
21
+ # assert_has_method(body, *methods) # check that the body has a list of methods (methods with parentheses not supported yet)
22
+ #
23
+ # Other helper methods are:
24
+ # app_root_files - put this in teardown to show files generated by the test method (e.g. p app_root_files)
25
+ # bare_setup - place this in setup method to create the APP_ROOT folder for each test
26
+ # bare_teardown - place this in teardown method to destroy the TMP_ROOT or APP_ROOT folder after each test
27
+
28
+ def test_generator_without_options
29
+ run_generator('skynet_install', [APP_ROOT], sources)
30
+ assert_directory_exists "script"
31
+ assert_generated_file "script/skynet"
32
+ end
33
+
34
+ def test_generator_in_rails
35
+ run_generator('skynet_install', [APP_ROOT], sources, {"--rails"=>''})
36
+ assert_directory_exists "script"
37
+ assert_generated_file "script/skynet"
38
+ end
39
+
40
+ private
41
+ def sources
42
+ [RubiGen::PathSource.new(:test, File.join(File.dirname(__FILE__),"..", generator_path))
43
+ ]
44
+ end
45
+
46
+ def generator_path
47
+ "app_generators"
48
+ end
49
+ end
@@ -0,0 +1,717 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class SkynetJobTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ Skynet.configure(
7
+ :ENABLE => false,
8
+ :SKYNET_LOG_FILE => STDOUT,
9
+ :MESSAGE_QUEUE_ADAPTER => "Skynet::MessageQueueAdapter::TupleSpace",
10
+ :SKYNET_LOG_LEVEL => Logger::ERROR,
11
+ :TS_DRBURIS => ["druby://localhost:47999"],
12
+ :TS_USE_RINGSERVER => false
13
+ )
14
+
15
+ Skynet::MessageQueue.any_instance.stubs(:get_worker_version).returns(1)
16
+ Skynet::MessageQueue.any_instance.stubs(:set_worker_version).returns(1)
17
+
18
+ @ts = Rinda::TupleSpace.new
19
+ Skynet::MessageQueueAdapter::TupleSpace.stubs(:get_tuple_space).returns(@ts)
20
+
21
+ @messages = []
22
+ end
23
+
24
+ def test_new_job
25
+ job = Skynet::Job.new(:map_reduce_class => JobMRTester)
26
+ {
27
+ :map_name => "JobMRTester MAP",
28
+ :map_timeout => 60,
29
+ :mappers => 2,
30
+ :name => "JobMRTester MASTER",
31
+ :reducers => 1,
32
+ :reduce_partition => nil,
33
+ :reduce => "JobMRTester",
34
+ :queue_id => 0,
35
+ :start_after => 0,
36
+ :reduce_timeout => 60,
37
+ :reduce_name => "JobMRTester REDUCE",
38
+ :master_timeout => 60,
39
+ :map => "JobMRTester",
40
+ :version => 1,
41
+ :result_timeout => 1200,
42
+ :master_result_timeout => 1200
43
+ }.each do |key, val|
44
+ assert_equal val, job.send(key), key
45
+ end
46
+ end
47
+
48
+ def test_new_async_job
49
+ job = Skynet::AsyncJob.new(:map_reduce_class => JobMRTester)
50
+ {
51
+ :map_timeout => 60,
52
+ :reduce_partition => nil,
53
+ :master_timeout => 60,
54
+ :reduce_timeout => 60,
55
+ :name => "JobMRTester MASTER",
56
+ :version => 1,
57
+ :result_timeout => 1200,
58
+ :map_name => "JobMRTester MAP",
59
+ :reducers => 1,
60
+ :queue_id => 0,
61
+ :reduce_name => "JobMRTester REDUCE",
62
+ :map => "JobMRTester",
63
+ :async => true,
64
+ :master_result_timeout => 1200,
65
+ :mappers => 2,
66
+ :reduce => "JobMRTester",
67
+ :start_after => 0
68
+ }.each do |key, val|
69
+ assert_equal val, job.send(key), key
70
+ end
71
+ end
72
+
73
+ def test_run_async
74
+ job = Skynet::AsyncJob.new(
75
+ :map_reduce_class => JobMRTester,
76
+ :version => 1,
77
+ :map_data => [[1]],
78
+ :mappers => 1
79
+ )
80
+ job.stubs(:use_local_queue?).returns(true)
81
+ assert_equal job.job_id, job.run
82
+ assert_equal 1, job.local_mq.messages.size
83
+ master_job = Skynet::Job.new(job.local_mq.messages.first.payload.process)
84
+ assert ! master_job.async
85
+ assert_equal true, master_job.local_master
86
+ end
87
+
88
+ def test_run_master
89
+ job = Skynet::Job.new(
90
+ :map_reduce_class => JobMRTester,
91
+ :version => 1,
92
+ :map_data => [[1]],
93
+ :mappers => 1,
94
+ :local_master => false
95
+ )
96
+ mq = functor
97
+ received_messages = []
98
+ mq.write_message = lambda do |message,timeout|
99
+ received_messages << message
100
+ end
101
+ mq.get_worker_version = 1
102
+ job.stubs(:mq).returns(mq)
103
+ result_message = functor(:payload => "result", :payload_type => :result, :task_id => 1)
104
+ mq.expects(:take_result).with(job.job_id,120).times(1).returns(result_message)
105
+ assert_equal ["result"], job.run
106
+ assert_equal 1, received_messages.size
107
+ end
108
+
109
+ def test_run
110
+ job = Skynet::Job.new(
111
+ :map_reduce_class => JobMRTester,
112
+ :version => 1,
113
+ :map_data => [1,2,3],
114
+ :mappers => 2,
115
+ :reducers => 2
116
+ )
117
+ job.stubs(:use_local_queue?).returns(true)
118
+ results = job.run
119
+ assert_equal 2, results.size
120
+ assert_equal [1,2,3], results.flatten.sort
121
+ end
122
+
123
+ def test_master_enqueue
124
+ job = Skynet::AsyncJob.new(
125
+ :map_reduce_class => JobMRTester,
126
+ :version => 1,
127
+ :map_data => [[1]],
128
+ :mappers => 1
129
+ )
130
+
131
+ mq = functor
132
+ job.stubs(:mq).returns(mq)
133
+ received_messages = []
134
+ mq.write_message = lambda do |message,timeout|
135
+ received_messages << message
136
+ end
137
+ mq.get_worker_version = 1
138
+
139
+ job.master_enqueue
140
+ assert_equal :master, received_messages.first.payload_type
141
+ assert_equal :master, received_messages.first.payload.map_or_reduce
142
+ master_job = Skynet::Job.new(received_messages.first.payload.process)
143
+ assert_equal JobMRTester.to_s, master_job.map
144
+ assert ! master_job.async
145
+ assert_equal true, master_job.local_master
146
+ end
147
+
148
+ def test_master_results
149
+ job = Skynet::Job.new(
150
+ :map_reduce_class => JobMRTester,
151
+ :version => 1,
152
+ :map_data => [[1]],
153
+ :mappers => 1
154
+ )
155
+
156
+ mq = functor(:payload => "result")
157
+ result_message = functor(:payload => "result", :payload_type => :result, :task_id => 1)
158
+ mq.expects(:take_result).with(job.job_id,120).times(1).returns(result_message)
159
+ job.stubs(:mq).returns(mq)
160
+ results = job.master_results
161
+ assert_equal "result", results.first
162
+ end
163
+
164
+ def test_map_enqueue
165
+ job = Skynet::AsyncJob.new(
166
+ :map_reduce_class => JobMRTester,
167
+ :version => 1,
168
+ :map_data => [1,2,3],
169
+ :mappers => 2
170
+ )
171
+
172
+ mq = functor
173
+ job.stubs(:mq).returns(mq)
174
+ received_messages = []
175
+ mq.write_message = lambda do |message,timeout|
176
+ received_messages << message
177
+ end
178
+ mq.get_worker_version = 1
179
+
180
+ job.map_enqueue
181
+ assert_equal 2, received_messages.size
182
+ assert_equal :task, received_messages.first.payload_type
183
+ assert_equal :map, received_messages.first.payload.map_or_reduce
184
+ end
185
+
186
+ def test_map_results
187
+ job = Skynet::AsyncJob.new(
188
+ :map_reduce_class => JobMRTester,
189
+ :version => 1,
190
+ :map_data => [[1]],
191
+ :mappers => 1
192
+ )
193
+
194
+ mq = functor(:payload => "result")
195
+ i = 0
196
+ result_message = functor(:payload => "result", :payload_type => :result, :task_id => lambda {i += 1})
197
+ mq.expects(:take_result).with(job.job_id,120).times(2).returns(result_message)
198
+ job.stubs(:mq).returns(mq)
199
+ results = job.map_results(2)
200
+ assert_equal "result", results.first
201
+ end
202
+
203
+ def test_local_map_results
204
+ job = Skynet::AsyncJob.new(
205
+ :map_reduce_class => JobMRTester,
206
+ :version => 1,
207
+ :map_data => [1,2],
208
+ :mappers => 2,
209
+ :single => true
210
+ )
211
+
212
+ job.map_enqueue
213
+ assert_equal 2, job.local_mq.messages.size
214
+ results = job.map_results(2)
215
+ assert_equal [[1],[2]], results.sort
216
+ end
217
+
218
+ def test_partition_data
219
+ job = Skynet::AsyncJob.new(
220
+ :map_reduce_class => JobMRTester,
221
+ :version => 1,
222
+ :map_data => [[1]],
223
+ :reducers => 2
224
+ )
225
+
226
+ partitioned_data = job.partition_data([[1],[2],[3]])
227
+ assert_equal [[1, 3], [2]], partitioned_data
228
+ end
229
+
230
+ def test_partition_data_class
231
+ job = Skynet::AsyncJob.new(
232
+ :map_reduce_class => "JobPartitionTest",
233
+ :version => 1,
234
+ :map_data => [[1]],
235
+ :reducers => 2
236
+ )
237
+
238
+ partitioned_data = job.partition_data([[1],[2],[3]])
239
+ assert_equal [[1], [2], [3]], partitioned_data
240
+ end
241
+
242
+ def test_reduce_enqueue
243
+ job = Skynet::AsyncJob.new(
244
+ :map_reduce_class => JobMRTester,
245
+ :version => 1,
246
+ :map_data => [1,2,3],
247
+ :mappers => 2
248
+ )
249
+
250
+ mq = functor
251
+ job.stubs(:mq).returns(mq)
252
+ received_messages = []
253
+ mq.write_message = lambda do |message,timeout|
254
+ received_messages << message
255
+ end
256
+ mq.get_worker_version = 1
257
+
258
+ job.reduce_enqueue([[1, 3], [2]])
259
+ assert_equal 2, received_messages.size
260
+ assert_equal :task, received_messages.first.payload_type
261
+ assert_equal :reduce, received_messages.first.payload.map_or_reduce
262
+ end
263
+
264
+ def test_reduce_results
265
+ job = Skynet::AsyncJob.new(
266
+ :map_reduce_class => JobMRTester,
267
+ :version => 1,
268
+ :map_data => [[1]],
269
+ :mappers => 1
270
+ )
271
+
272
+ mq = functor(:payload => "result")
273
+ i = 0
274
+ result_message = functor(:payload => "result", :payload_type => :result, :task_id => lambda {i += 1})
275
+ mq.expects(:take_result).with(job.job_id,120).times(2).returns(result_message)
276
+ job.stubs(:mq).returns(mq)
277
+ results = job.reduce_results(2)
278
+ assert_equal "result", results.first
279
+ end
280
+
281
+ def test_master_task
282
+ job = Skynet::AsyncJob.new(:map_reduce_class => JobMRTester,:version=>1, :queue_id => 4)
283
+ mt = job.master_task
284
+ assert mt.is_a?(Skynet::Task)
285
+ assert_equal mt.result_timeout, 60
286
+ master_job = Skynet::Job.new(mt.process)
287
+ assert_equal job.map, JobMRTester.to_s
288
+ assert_equal job.reduce, JobMRTester.to_s
289
+ assert_equal nil, job.reduce_partition
290
+ assert_equal master_job.map, JobMRTester.to_s
291
+ assert_equal master_job.reduce, JobMRTester.to_s
292
+ assert_equal nil, master_job.reduce_partition
293
+ assert_equal 4, master_job.queue_id
294
+ Skynet::Job::FIELDS.each do |field|
295
+ case field
296
+ when :async, :local_master
297
+ nil
298
+ when :job_id, :single
299
+ next
300
+ else
301
+ assert_equal job.send(field), master_job.send(field), "Testing #{field}, jobfield: #{job.send(field)} mjobfield: #{master_job.send(field)}"
302
+ end
303
+ end
304
+ end
305
+
306
+ def test_gather_results_with_errors
307
+ job = Skynet::AsyncJob.new(
308
+ :map_reduce_class => JobMRTester,
309
+ :version => 1,
310
+ :map_data => [1],
311
+ :mappers => 1
312
+ )
313
+ map_tasks = job.map_tasks
314
+ mq = mq
315
+ mq.stubs(:get_worker_version).returns(1)
316
+ job.stubs(:mq).returns(mq)
317
+ messages = job.tasks_to_messages(map_tasks)
318
+ message = messages.first.result_message(["works"])
319
+ message2 = Skynet::Message.new(message.to_h.merge(:payload_type => :error, :payload => "error", :task_id => 33))
320
+
321
+ test_message1 = {
322
+ :version =>1,
323
+ :queue_id =>0,
324
+ :iteration =>0,
325
+ :name =>"JobMRTester MAP",
326
+ :tasktype =>:result,
327
+ :expire_time =>0,
328
+ :payload_type =>:result,
329
+ :payload =>["works"],
330
+ :drburi =>nil,
331
+ :expiry =>60,
332
+ :retry =>3
333
+ }
334
+ assert message.task_id.is_a?(Bignum)
335
+ assert message.job_id.is_a?(Bignum)
336
+ test_message1.each do |k,v|
337
+ assert_equal v, message.send(k), k
338
+ end
339
+
340
+ mq.expects(:take_result).with(job.job_id, 120).returns(message,message2).times(2)
341
+ results = nil
342
+ Skynet.silent do
343
+ results = job.gather_results(2, map_tasks.first.result_timeout, map_tasks.first.name)
344
+ end
345
+ assert_equal [["works"]], results
346
+ end
347
+
348
+ def test_map_tasks
349
+ job = Skynet::AsyncJob.new(
350
+ :map_reduce_class => JobMRTester,
351
+ :version => 1,
352
+ :map_data => [1,2,3],
353
+ :map_retry => 7,
354
+ :mappers => 2
355
+ )
356
+ map_tasks = job.map_tasks
357
+ assert_equal 2, map_tasks.size
358
+ assert_equal 7, map_tasks.first.retry
359
+ assert map_tasks[0].task_id != map_tasks[1].task_id
360
+ end
361
+
362
+ def test_reduce_tasks
363
+ job = Skynet::AsyncJob.new(
364
+ :map_reduce_class => JobMRTester,
365
+ :version => 1,
366
+ :map_data => [1,2,3],
367
+ :reduce_retry => 9,
368
+ :reducers => 2
369
+ )
370
+ reduce_tasks = job.reduce_tasks([1,2,3])
371
+ assert_equal 3, reduce_tasks.size
372
+ assert_equal 9, reduce_tasks.first.retry
373
+ assert reduce_tasks[0].task_id != reduce_tasks[1].task_id
374
+ end
375
+
376
+ def test_enqueue_messages
377
+ passed_messages = []
378
+ mq = functor
379
+ mq.write_message = lambda do |m,timeout|
380
+ passed_messages << m
381
+ end
382
+ job = Skynet::Job.new(:map_data => [1,2,3], :map_reduce_class => JobMRTester)
383
+ job.stubs(:mq).returns(mq)
384
+ message1 = Skynet::Message.new(
385
+ :tasktype => :task,
386
+ :task_id => 9,
387
+ :job_id => 8,
388
+ :payload_type => :task,
389
+ :payload => "blah",
390
+ :retry => 3,
391
+ :iteration => 0,
392
+ :version => 1,
393
+ :queue_id => 4,
394
+ :name => "test"
395
+ )
396
+ message2 = Skynet::Message.new(message1.to_h.merge(:name => "test2", :payload => "test2"))
397
+ job.enqueue_messages([message1,message2])
398
+ assert_equal [message1, message2], passed_messages
399
+ end
400
+
401
+
402
+ def test_local_queue_write_message
403
+ local_queue = Skynet::Job::LocalMessageQueue.new
404
+ assert_equal 1, local_queue.get_worker_version
405
+ local_queue.write_message(Skynet::Message.new({}),2)
406
+ assert local_queue.messages.first.is_a?(Skynet::Message)
407
+ end
408
+
409
+ def test_local_queue_take_result
410
+ job = Skynet::AsyncJob.new(
411
+ :map_reduce_class => JobMRTester,
412
+ :queue_id => 6,
413
+ :version => 1,
414
+ :map_data => [1,2,3],
415
+ :mappers => 2,
416
+ :master_retry => 17,
417
+ :master_result_timeout => 1
418
+ )
419
+ tasks = job.map_tasks
420
+ assert_equal 2, tasks.size
421
+ messages = job.tasks_to_messages(tasks)
422
+
423
+ local_queue = Skynet::Job::LocalMessageQueue.new
424
+ messages.each do |message|
425
+ local_queue.write_message(message)
426
+ end
427
+ assert_equal messages, local_queue.messages
428
+ assert_equal [1,3], local_queue.take_result(job.job_id,2).payload
429
+ assert_equal [2], local_queue.take_result(job.job_id,2).payload
430
+ assert_equal 0, local_queue.messages.size
431
+ assert_equal 0, local_queue.results.size
432
+ end
433
+
434
+ def test_run_tasks_locally_errors
435
+ job = Skynet::AsyncJob.new(
436
+ :map_reduce_class => JobMRTester,
437
+ :queue_id => 6,
438
+ :version => 1,
439
+ :map_data => [1,2,3],
440
+ :mappers => 2,
441
+ :master_retry => 17,
442
+ :master_result_timeout => 1
443
+ )
444
+ tasks = job.map_tasks
445
+ assert_equal 2, tasks.size
446
+
447
+ messages = job.tasks_to_messages(tasks)
448
+
449
+ task1 = messages.first.payload
450
+ task1.extend(Functor)
451
+ tries = 0
452
+ task1.define_method(:tries) {@tries}
453
+ task1.define_method(:run) do
454
+ @tries ||= 0
455
+ @tries += 1
456
+ if @tries == 1
457
+ raise Exception
458
+ else
459
+ return task1.data
460
+ end
461
+ end
462
+ messages.first.expects(:payload).returns(task1).times(2)
463
+
464
+ task2 = messages[1].payload
465
+ task2.extend(Functor)
466
+ tries = 0
467
+ task2.define_method(:tries) {@tries}
468
+ task2.define_method(:run) do
469
+ @tries ||= 0
470
+ @tries += 1
471
+ return task2.data
472
+ end
473
+ messages[1].expects(:payload).returns(task2).times(1)
474
+
475
+ local_queue = Skynet::Job::LocalMessageQueue.new
476
+ messages.each do |message|
477
+ local_queue.write_message(message)
478
+ end
479
+
480
+ assert_equal messages, local_queue.messages
481
+ Skynet.configure(:SKYNET_LOG_LEVEL=>Logger::FATAL) do
482
+ assert_equal [1,3], local_queue.take_result(job.job_id,2).payload
483
+ assert_equal [2], local_queue.take_result(job.job_id,2).payload
484
+ end
485
+ assert_equal 2, task1.tries
486
+ assert_equal 1, task2.tries
487
+ assert_equal 0, local_queue.messages.size
488
+ assert_equal 0, local_queue.results.size
489
+ end
490
+
491
+ def test_map_local
492
+ job = Skynet::AsyncJob.new(
493
+ :map_reduce_class => JobMRTester,
494
+ :version => 1,
495
+ :map_data => [1,2,3,4],
496
+ :mappers => 3
497
+ )
498
+
499
+ assert_equal 3, job.map_tasks.size
500
+ assert !job.map_local?
501
+
502
+ job.keep_map_tasks = true
503
+ assert job.map_local?
504
+
505
+ job.keep_map_tasks = 3
506
+ assert job.map_local?
507
+
508
+ job.keep_map_tasks = 2
509
+ assert !job.map_local?
510
+
511
+ job.single = true
512
+ assert job.map_local?
513
+ end
514
+
515
+ def test_reduce_local
516
+ job = Skynet::AsyncJob.new(
517
+ :reduce_reduce_class => JobMRTester,
518
+ :version => 1,
519
+ :map_data => [1,2,3,4],
520
+ :reducers => 3
521
+ )
522
+
523
+ partitioned_data = [[1,2],[3],[4]]
524
+ assert_equal 3, job.reduce_tasks(partitioned_data).size
525
+ assert !job.reduce_local?(job.reduce_tasks(partitioned_data))
526
+
527
+ job.keep_reduce_tasks = true
528
+ assert job.reduce_local?(job.reduce_tasks(partitioned_data))
529
+
530
+ job.keep_reduce_tasks = 3
531
+ assert job.reduce_local?(job.reduce_tasks(partitioned_data))
532
+
533
+ job.keep_reduce_tasks = 2
534
+ assert !job.reduce_local?(job.reduce_tasks(partitioned_data))
535
+
536
+ job.single = true
537
+ assert job.reduce_local?(job.reduce_tasks(partitioned_data))
538
+ end
539
+
540
+
541
+
542
+ def test_keep_map_tasks
543
+ job = Skynet::Job.new(
544
+ :map_reduce_class => JobMRTester,
545
+ :version => 1,
546
+ :map_data => [1,2],
547
+ :mappers => 2,
548
+ :keep_map_tasks => 2
549
+ )
550
+ assert_equal 2, job.map_enqueue
551
+ assert_equal 2, job.local_mq.messages.size
552
+ assert_equal [[1],[2]], job.map_results(2).sort
553
+ assert_equal 0, job.local_mq.messages.size
554
+ assert_equal 0, job.local_mq.results.size
555
+ end
556
+
557
+
558
+ def test_keep_reduce_tasks
559
+ job = Skynet::Job.new(
560
+ :map_reduce_class => JobMRTester,
561
+ :version => 1,
562
+ :map_data => [1,2],
563
+ :reducers => 1,
564
+ :keep_reduce_tasks => 2
565
+ )
566
+ assert_equal 1, job.reduce_enqueue([[1,2]])
567
+ assert_equal 1, job.local_mq.messages.size
568
+ assert_equal [[1,2]], job.reduce_results(1).sort
569
+ assert_equal 0, job.local_mq.messages.size
570
+ assert_equal 0, job.local_mq.results.size
571
+ end
572
+
573
+ def test_mapreduce_helper_mixin
574
+ job = Skynet::Job.new(
575
+ :map_reduce_class => "JobMapreduceHelperTest",
576
+ :version => 1,
577
+ :map_data => [1,2],
578
+ :reducers => 2,
579
+ :keep_reduce_tasks => true,
580
+ :keep_map_tasks => true
581
+ )
582
+ map_results = nil
583
+ results = nil
584
+ Skynet.solo do
585
+ map_results = job.map_results(job.map_enqueue)
586
+ partitioned_data = job.partition_data(map_results)
587
+ results = job.reduce_results(job.reduce_enqueue(partitioned_data))
588
+ end
589
+ assert_equal [2,3], map_results.flatten.sort
590
+ assert_equal [3,4], results.flatten.sort
591
+ end
592
+
593
+ def test_mapreduce_helper_mixin_again
594
+ [JobMRTest2, JobMRTest3].each do |klass|
595
+ job = Skynet::Job.new(
596
+ :mappers => 2,
597
+ :reducers => 1,
598
+ :map_reduce_class => klass,
599
+ :map_data => [
600
+ OpenStruct.new({:created_by => 2}),
601
+ OpenStruct.new({:created_by => 2}),
602
+ OpenStruct.new({:created_by => 3})]
603
+ )
604
+
605
+ map_results = nil
606
+ results = nil
607
+ Skynet.solo do
608
+ map_results = job.map_results(job.map_enqueue)
609
+ partitioned_data = job.partition_data(map_results)
610
+ results = job.reduce_results(job.reduce_enqueue(partitioned_data))
611
+ end
612
+ assert_equal [1, 1, 1, 2, 2, 3], map_results.flatten.sort
613
+ expected_results = {2=>2, 3=>1}
614
+ assert_equal expected_results, results
615
+ end
616
+ end
617
+
618
+
619
+ private
620
+
621
+ def mq
622
+ Skynet::MessageQueueAdapter::TupleSpace.new
623
+ end
624
+
625
+ end
626
+
627
+
628
+ class JobMRTester
629
+ def self.map(datas)
630
+ ret = []
631
+ datas.each do |data|
632
+ if data == :error
633
+ raise Exception.new("something bad happened")
634
+ else
635
+ ret << data
636
+ end
637
+ end
638
+ return ret
639
+ end
640
+
641
+ def self.reduce(datas)
642
+ datas
643
+ end
644
+ end
645
+
646
+ class JobPartitionTest < JobMRTester
647
+
648
+ def self.reduce_partition(post_map_data, reducers)
649
+ return post_map_data.compact
650
+ end
651
+ end
652
+
653
+ class JobMapreduceHelperTest
654
+ include MapreduceHelper
655
+
656
+ def self.map_each(data)
657
+ return data + 1
658
+ end
659
+
660
+ def self.reduce_each(data)
661
+ return data + 1
662
+ end
663
+ end
664
+
665
+ class JobMRTest2
666
+ include MapreduceHelper
667
+
668
+ # def self.map(profiles)
669
+ # result = Array.new
670
+ # profiles.each do |profile|
671
+ # result << [profile.created_by, 1] if profile.created_by
672
+ # end
673
+ # result
674
+ # end
675
+
676
+ def self.map_each(item)
677
+ return [item.created_by, 1] if item.created_by
678
+ end
679
+
680
+ def self.reduce(pairs)
681
+ totals = Hash.new
682
+ pairs.each do |pair|
683
+ created_by, count = pair[0], pair[1]
684
+ totals[created_by] ||= 0
685
+ totals[created_by] += count
686
+ end
687
+ return totals
688
+ end
689
+ end
690
+
691
+ class JobMRTest3
692
+
693
+ include MapreduceHelper
694
+
695
+ def self.map(profiles)
696
+ result = Array.new
697
+ profiles.each do |profile|
698
+ result << [profile.created_by, 1] if profile.created_by
699
+ end
700
+ result
701
+ end
702
+
703
+ # def self.map_each(item)
704
+ # return [item.created_by, 1] if item.created_by
705
+ # end
706
+
707
+ def self.reduce(pairs)
708
+ totals = Hash.new
709
+ pairs.each do |pair|
710
+ created_by, count = pair[0], pair[1]
711
+ totals[created_by] ||= 0
712
+ totals[created_by] += count
713
+ end
714
+
715
+ return totals
716
+ end
717
+ end