skynet 0.9.1 → 0.9.2

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 (51) hide show
  1. data/History.txt +99 -0
  2. data/Manifest.txt +10 -9
  3. data/README.txt +74 -7
  4. data/app_generators/skynet_install/skynet_install_generator.rb +26 -22
  5. data/app_generators/skynet_install/templates/migration.rb +11 -5
  6. data/app_generators/skynet_install/templates/skynet +25 -12
  7. data/app_generators/skynet_install/templates/skynet_schema.sql +56 -0
  8. data/bin/skynet +26 -2
  9. data/bin/skynet_install +24 -0
  10. data/bin/skynet_tuplespace_server +13 -0
  11. data/config/hoe.rb +1 -0
  12. data/lib/skynet.rb +3 -0
  13. data/lib/skynet/mapreduce_helper.rb +74 -0
  14. data/lib/skynet/message_queue_adapters/mysql.rb +225 -172
  15. data/lib/skynet/message_queue_adapters/tuple_space.rb +31 -16
  16. data/lib/skynet/skynet_active_record_extensions.rb +78 -46
  17. data/lib/skynet/skynet_config.rb +162 -23
  18. data/lib/skynet/skynet_console.rb +23 -10
  19. data/lib/skynet/skynet_console_helper.rb +61 -58
  20. data/lib/skynet/skynet_job.rb +741 -493
  21. data/lib/skynet/skynet_launcher.rb +5 -1
  22. data/lib/skynet/skynet_manager.rb +106 -49
  23. data/lib/skynet/skynet_message.rb +169 -174
  24. data/lib/skynet/skynet_message_queue.rb +29 -16
  25. data/lib/skynet/skynet_partitioners.rb +92 -0
  26. data/lib/skynet/skynet_ruby_extensions.rb +3 -4
  27. data/lib/skynet/skynet_task.rb +61 -19
  28. data/lib/skynet/skynet_tuplespace_server.rb +0 -2
  29. data/lib/skynet/skynet_worker.rb +73 -51
  30. data/lib/skynet/version.rb +1 -1
  31. data/test/test_active_record_extensions.rb +138 -0
  32. data/test/test_helper.rb +6 -0
  33. data/test/{mysql_message_queue_adaptor_test.rb → test_mysql_message_queue_adapter.rb} +94 -30
  34. data/test/test_skynet.rb +11 -11
  35. data/test/test_skynet_install_generator.rb +0 -4
  36. data/test/test_skynet_job.rb +717 -0
  37. data/test/test_skynet_manager.rb +142 -0
  38. data/test/test_skynet_message.rb +229 -0
  39. data/test/test_skynet_task.rb +24 -0
  40. data/test/{tuplespace_message_queue_test.rb → test_tuplespace_message_queue.rb} +25 -30
  41. data/website/index.html +56 -16
  42. data/website/index.txt +55 -25
  43. data/website/template.rhtml +1 -1
  44. metadata +29 -13
  45. data/app_generators/skynet_install/templates/skynet_console +0 -16
  46. data/bin/skynet_console +0 -9
  47. data/sometest.rb +0 -23
  48. data/test/all_models_test.rb +0 -139
  49. data/test/skynet_manager_test.rb +0 -107
  50. data/test/skynet_message_test.rb +0 -42
  51. data/tmtags +0 -1242
@@ -0,0 +1,142 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class SkynetManagerTest < Test::Unit::TestCase
4
+
5
+ PIDS = []
6
+ PIDFILE = []
7
+
8
+ def setup
9
+ Skynet.configure(
10
+ :ENABLE => false,
11
+ # :SKYNET_PIDS_FILE => File.expand_path("#{RAILS_ROOT}/log/skynet_#{RAILS_ENV}.pids"),
12
+ :SKYNET_LOG_FILE => STDOUT,
13
+ :SKYNET_LOG_LEVEL => 4,
14
+ :MESSAGE_QUEUE_ADAPTER => "Skynet::MessageQueueAdapter::Mysql",
15
+ :MYSQL_TEMPERATURE_CHANGE_SLEEP => 1,
16
+ :MYSQL_NEXT_TASK_TIMEOUT => 1
17
+ )
18
+ ActiveRecord::Base.establish_connection(
19
+ :adapter => "mysql",
20
+ :host => "localhost",
21
+ :username => "root",
22
+ :password => "",
23
+ :database => "skynet_test"
24
+ )
25
+
26
+ mq.clear_outstanding_tasks
27
+ mq.clear_worker_status
28
+
29
+ @pids = []
30
+ @pidfile = []
31
+ @worker_queue = []
32
+
33
+ PIDS.delete_if {true}
34
+ PIDFILE.delete_if {true}
35
+
36
+ Process.stubs(:detatch).returns(true)
37
+ Process.stubs(:kill).returns(true)
38
+
39
+ @minstance = Skynet::Manager.any_instance
40
+ @hostname = Socket.gethostname
41
+
42
+ Skynet::Worker.any_instance.stubs(:max_memory_reached?).returns(false)
43
+ end
44
+
45
+ def setup_manager
46
+ @manager = Skynet::Manager.new(:script_path => "path", :workers => 2)
47
+ @manager.extend(Functor)
48
+
49
+ mq = functor
50
+ @manager.stubs(:mq).returns(mq)
51
+
52
+ mq.get_worker_version = 1
53
+
54
+ worker_queue = @worker_queue
55
+ mq.read_all_worker_statuses = lambda do |hostname|
56
+ worker_queue
57
+ end
58
+
59
+ mq.take_worker_status = lambda do |options, timeout|
60
+ worker_queue.delete_if {|w|w.process_id == options[:process_id] }.first
61
+ end
62
+
63
+ pids = @pids
64
+ hostname = @hostname
65
+ @manager.define_method(:fork) do
66
+ newpid = pids.size + 1
67
+ pids << newpid
68
+ worker_info = {
69
+ :hostname => hostname,
70
+ :process_id => newpid,
71
+ :worker_type => :task,
72
+ :worker_id => newpid,
73
+ :version => 1
74
+ }
75
+
76
+ worker_queue << Skynet::WorkerStatusMessage.new(worker_info)
77
+ newpid
78
+ end
79
+ end
80
+
81
+ def test_manager_start
82
+ setup_manager
83
+ @manager.start_workers
84
+ assert_equal 2, @manager.worker_pids.size
85
+ assert_equal @pids.sort, @manager.worker_pids.sort
86
+ assert_equal @pids.sort, @manager.worker_queue.collect {|q|q.process_id}.sort
87
+ end
88
+
89
+ def test_check_workers
90
+ setup_manager
91
+ Skynet::Manager.any_instance.expects(:worker_alive?).times(2).returns(true)
92
+ @manager.start_workers
93
+ @manager.check_workers
94
+ assert_equal 2, @manager.worker_pids.size
95
+ assert_equal @pids.sort, @manager.worker_pids.sort
96
+ assert_equal @pids.sort, @manager.worker_queue.collect {|q|q.process_id}.sort
97
+ end
98
+
99
+ def test_running_pids
100
+ setup_manager
101
+ Skynet::Manager.any_instance.expects(:worker_alive?).with(1).returns(true)
102
+ Skynet::Manager.any_instance.expects(:worker_alive?).with(2).returns(false)
103
+ @manager.start_workers
104
+ @manager.check_workers
105
+ assert_equal 1, @manager.worker_pids.size
106
+ assert_equal [1], @manager.worker_pids.sort
107
+ assert_equal [1], @manager.worker_queue.collect {|q|q.process_id}.sort
108
+ end
109
+
110
+ ## XXX FIXME. What happens if there's a worker missing from the pidfile, but was running?
111
+ def test_more_in_pidfile_than_queue_alive
112
+ setup_manager
113
+ @manager.expects(:worker_alive?).with(1).returns(false)
114
+ Skynet.configure(:SKYNET_LOG_LEVEL => 4) do
115
+ @manager.start_workers
116
+
117
+ @manager.expects(:worker_alive?).with(2).returns(true)
118
+ @worker_queue.delete_if {|w| w.process_id == 1}
119
+ @manager.check_workers
120
+ end
121
+ assert_equal 2, @manager.worker_pids.size
122
+ assert_equal [2,3], @manager.worker_pids.sort
123
+ assert_equal [2,3], @manager.worker_queue.collect {|q|q.process_id}.sort
124
+ end
125
+
126
+ def test_dead_workers
127
+ setup_manager
128
+ Skynet::Manager.any_instance.expects(:worker_alive?).times(1).with(1).returns(false)
129
+ # Skynet::Manager.any_instance.expects(:worker_alive?).with(2).returns(true)
130
+ @manager.start_workers
131
+ @manager.check_workers
132
+ assert_equal [2], @manager.worker_pids.sort
133
+ assert_equal [2], @manager.worker_queue.collect {|q|q.process_id}.sort
134
+ end
135
+
136
+
137
+ private
138
+
139
+ def mq
140
+ Skynet::MessageQueueAdapter::Mysql.new
141
+ end
142
+ end
@@ -0,0 +1,229 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class MysqlMessageQueueTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ Skynet.configure(
7
+ :ENABLE => false,
8
+ :SKYNET_LOG_FILE => STDOUT,
9
+ :SKYNET_LOG_LEVEL => Logger::ERROR
10
+ )
11
+ end
12
+
13
+ def setup_worker_message
14
+ @worker_message = Skynet::WorkerStatusMessage.new(
15
+ :tasktype => :task,
16
+ :drburi => "localhost",
17
+ :job_id => 1,
18
+ :task_id => 2,
19
+ :payload => "payload",
20
+ :payload_type => "task",
21
+ :expiry => 20,
22
+ :expire_time => 1095108406.9251,
23
+ :iteration => 0,
24
+ :name => "name",
25
+ :version => 1,
26
+ :queue_id => 0
27
+ )
28
+ end
29
+
30
+ def setup_task_message
31
+ @task_message = Skynet::Message.new(
32
+ :tasktype => :task,
33
+ :drburi => "localhost",
34
+ :job_id => 1,
35
+ :task_id => 2,
36
+ :payload => "payload",
37
+ :payload_type => "task",
38
+ :expiry => 20,
39
+ :expire_time => 0,
40
+ :iteration => 0,
41
+ :name => "name",
42
+ :version => 1,
43
+ :retry => 2,
44
+ :queue_id => 0
45
+ )
46
+ end
47
+
48
+ def test_worker_status_message
49
+ setup_worker_message
50
+ {
51
+ :queue_id => 0,
52
+ :tasksubtype => :worker,
53
+ :tasktype => :status,
54
+ :name => "name",
55
+ :hostname => nil,
56
+ :worker_id => nil,
57
+ :map_or_reduce => nil,
58
+ :process_id => nil,
59
+ :started_at => nil,
60
+ :job_id => 1,
61
+ :iteration => 0,
62
+ :processed => nil,
63
+ :task_id => 2,
64
+ :version => 1
65
+ }.each do |key, val|
66
+ assert_equal val, @worker_message.send(key), key
67
+ end
68
+ assert_equal @worker_message.to_a, Skynet::WorkerStatusMessage.new([:status, :worker, nil, nil, nil, 1, 2, 0, "name", nil, nil, 1, nil, 0]).to_a
69
+ end
70
+
71
+ def test_task_message
72
+ setup_task_message
73
+ {:payload=>"payload",
74
+ :queue_id=>0,
75
+ :tasktype=>:task,
76
+ :name=>"name",
77
+ :payload_type=>:task,
78
+ :expiry=>20,
79
+ :drburi=>"localhost",
80
+ :expire_time=>0,
81
+ :job_id=>1,
82
+ :iteration=>0,
83
+ :retry=>2,
84
+ :task_id=>2,
85
+ :version=>1}.each do |key, val|
86
+ assert_equal val, @task_message.send(key)
87
+ end
88
+ assert_equal @task_message.to_a, Skynet::Message.new([:task, "localhost", 2, 1, "payload", :task, "name", 20, 0, 0, 1, 2, 0]).to_a
89
+ end
90
+
91
+
92
+ def test_worker_status_template
93
+ template = Skynet::WorkerStatusMessage.worker_status_template(:hostname => "localhost", :process_id => $$)
94
+ [:status,:worker, nil, "localhost", :skip, nil, nil, nil, nil, nil, nil, nil, nil, nil].each_with_index do |field, ii|
95
+ next if field == :skip
96
+ assert_equal field, template[ii]
97
+ end
98
+ end
99
+
100
+ def test_fallback_message
101
+ setup_task_message
102
+ fb = @task_message.fallback_task_message
103
+ test_fb = {:payload=>"payload",
104
+ :queue_id=>0,
105
+ :tasktype=>:task,
106
+ :name=>"name",
107
+ :payload_type=>:task,
108
+ :expiry=>20,
109
+ :drburi=>"localhost",
110
+ :expire_time=>1200599892,
111
+ :job_id=>1,
112
+ :iteration=>1,
113
+ :retry=>2,
114
+ :task_id=>2,
115
+ :version=>1}
116
+
117
+ test_fb.each do |key, val|
118
+ next if key == :expire_time
119
+ assert_equal val, fb.send(key)
120
+ end
121
+
122
+ end
123
+
124
+ def test_retry
125
+ setup_task_message
126
+ test_fb = {:payload=>"payload",
127
+ :queue_id=>0,
128
+ :tasktype=>:task,
129
+ :name=>"name",
130
+ :payload_type=>:task,
131
+ :expiry=>20,
132
+ :drburi=>"localhost",
133
+ :job_id=>1,
134
+ :retry=>2,
135
+ :task_id=>2,
136
+ :version=>1}
137
+
138
+ fb1 = @task_message.fallback_task_message
139
+ test_fb.merge(:iteration => 1).each do |k,v|
140
+ assert_equal v, fb1.send(k)
141
+ end
142
+
143
+ fb2 = fb1.fallback_task_message
144
+ test_fb.merge(:iteration => 2).each do |k,v|
145
+ assert_equal v, fb2.send(k)
146
+ end
147
+
148
+ fb3 = fb2.fallback_task_message
149
+ test_fb.merge(:iteration => -1).each do |k,v|
150
+ assert_equal v, fb3.send(k)
151
+ end
152
+ end
153
+
154
+ def test_next_task_template
155
+ template = Skynet::Message.next_task_template(0,:any, 99)
156
+ [:task, nil, nil, nil, nil, :any, nil, nil, :skip, 0..6, 0, nil, 99].each_with_index do |field, ii|
157
+ next if field == :skip
158
+ assert_equal field, template[ii]
159
+ end
160
+ end
161
+
162
+ def test_result_template
163
+ template = Skynet::Message.result_template(88,:task)
164
+ [:task, nil, nil, 88, nil, nil, nil, nil, nil, nil, nil, nil, nil].each_with_index do |field, ii|
165
+ assert_equal field, template[ii]
166
+ end
167
+ end
168
+
169
+ def test_result_message
170
+ setup_task_message
171
+ result = @task_message.result_message("result")
172
+ {
173
+ :payload=>"result",
174
+ :queue_id=>0,
175
+ :tasktype=>:result,
176
+ :name=>"name",
177
+ :payload_type=>:result,
178
+ :expiry=>20,
179
+ :drburi=>"localhost",
180
+ :expire_time=>0,
181
+ :job_id=>1,
182
+ :iteration=>0,
183
+ :retry=>2,
184
+ :task_id=>2,
185
+ :version=>1
186
+ }.each do |key, val|
187
+ assert_equal val, result.send(key)
188
+ end
189
+
190
+ end
191
+
192
+ def test_fallback_template
193
+ setup_task_message
194
+ template = @task_message.fallback_template
195
+ [:task, "localhost", 2, nil, nil, nil, nil, nil, nil, 1..6, 1, nil, 0].each_with_index do |field, ii|
196
+ assert_equal field, template[ii]
197
+ end
198
+ end
199
+
200
+ def test_no_retry
201
+ setup_task_message
202
+ @task_message.retry = 0
203
+ fb1 = @task_message.fallback_task_message
204
+ {
205
+ :payload=>"payload",
206
+ :queue_id=>0,
207
+ :tasktype=>:task,
208
+ :name=>"name",
209
+ :payload_type=>:task,
210
+ :expiry=>20,
211
+ :drburi=>"localhost",
212
+ :job_id=>1,
213
+ :iteration=>-1,
214
+ :retry=>0,
215
+ :task_id=>2,
216
+ :version=>1
217
+ }.each do |k,v|
218
+ assert_equal v, fb1.send(k)
219
+ end
220
+ end
221
+
222
+ def test_payload
223
+ setup_task_message
224
+ @task_message.payload = "hi"
225
+ assert_equal YAML::dump("hi"), @task_message.raw_payload
226
+ end
227
+
228
+
229
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class SkynetTaskTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ Skynet.configure(
7
+ :ENABLE => false,
8
+ :SKYNET_LOG_FILE => STDOUT,
9
+ :SKYNET_LOG_LEVEL => Logger::ERROR
10
+ )
11
+ end
12
+
13
+ def test_master_task
14
+ job = Skynet::Job.new(:map_reduce_class => self.class, :async => true)
15
+ master_task = Skynet::Task.master_task(job)
16
+ master_job = Skynet::Job.new(master_task.process)
17
+ assert_equal self.class.to_s, master_job.map
18
+ assert ! master_job.async
19
+ assert_equal true, master_job.local_master
20
+ end
21
+
22
+ def self.map(datas)
23
+ end
24
+ end
@@ -1,41 +1,36 @@
1
- ENV["RAILS_ENV"] = "test"
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
2
 
3
- require 'test/unit'
4
- require 'pp'
5
- require '../lib/skynet.rb'
6
-
7
-
8
- # Tests for the partitioners.
9
- #
10
3
  class TuplespaceMessageQueueTest < Test::Unit::TestCase
11
4
 
12
5
  def setup
13
6
  Skynet.configure(
14
- :ENABLE => false,
15
- # :SKYNET_PIDS_FILE => File.expand_path("#{RAILS_ROOT}/log/skynet_#{RAILS_ENV}.pids"),
16
- :SKYNET_LOG_FILE => STDOUT,
17
- :SKYNET_LOG_LEVEL => Logger::ERROR,
18
- :SKYNET_LOCAL_MANAGER_URL => "druby://localhost:40000",
19
- :MESSAGE_QUEUE_ADAPTER => "Skynet::MessageQueueAdapter::TupleSpace",
20
- :TUPLESPACE_DRBURIS => ["druby://localhost:77647"],
21
- :USE_RINGSERVER => false
7
+ :ENABLE => false,
8
+ # :SKYNET_PIDS_FILE => File.expand_path("#{RAILS_ROOT}/log/skynet_#{RAILS_ENV}.pids"),
9
+ :SKYNET_LOG_FILE => STDOUT,
10
+ :SKYNET_LOG_LEVEL => Logger::ERROR,
11
+ :SKYNET_LOCAL_MANAGER_URL => "druby://localhost:40000",
12
+ :MESSAGE_QUEUE_ADAPTER => "Skynet::MessageQueueAdapter::TupleSpace",
13
+ :TS_DRBURIS => ["druby://localhost:77647"],
14
+ :TS_USE_RINGSERVER => false
22
15
  )
23
16
  @ts ||= Rinda::TupleSpace.new
24
- @@tss ||= DRb.start_service(Skynet::CONFIG[:TUPLESPACE_DRBURIS].first, @ts)
17
+ @@tss ||= DRb.start_service(Skynet::CONFIG[:TS_DRBURIS].first, @ts)
25
18
  mq.clear_outstanding_tasks
26
19
 
27
20
  @worker_message = Skynet::Message.new(
28
- :tasktype=> :task,
29
- :drburi=> "localhost",
30
- :job_id => 1,
31
- :task_id => 2,
32
- :payload => "task",
21
+ :tasktype => :task,
22
+ :drburi => "localhost",
23
+ :job_id => 1,
24
+ :task_id => 2,
25
+ :payload => "task",
33
26
  :payload_type => "master",
34
- :expiry => 20,
35
- :expire_time => 0,
36
- :iteration => 0,
37
- :name => "test",
38
- :version => 1
27
+ :expiry => 20,
28
+ :expire_time => 0,
29
+ :iteration => 0,
30
+ :name => "test",
31
+ :version => 1,
32
+ :retry => 3,
33
+ :queue_id => 0
39
34
  )
40
35
 
41
36
  end
@@ -44,7 +39,7 @@ class TuplespaceMessageQueueTest < Test::Unit::TestCase
44
39
  @ts.write([:test])
45
40
  assert_equal [:test], @ts.take([:test])
46
41
 
47
- rts = DRbObject.new(nil, Skynet::CONFIG[:TUPLESPACE_DRBURIS].first)
42
+ rts = DRbObject.new(nil, Skynet::CONFIG[:TS_DRBURIS].first)
48
43
  rts.write([:test])
49
44
  assert_equal [:test], rts.take([:test])
50
45
  end
@@ -84,8 +79,8 @@ class TuplespaceMessageQueueTest < Test::Unit::TestCase
84
79
  message.expiry=0.4
85
80
  assert mq.write_message(message)
86
81
  assert_equal message.to_a, mq.take_next_task(1).to_a
87
- sleep 0.6
88
- ntt = Skynet::Message.next_task_template(1)
82
+ sleep 1
83
+ ntt = Skynet::Message.next_task_template(1,nil,0)
89
84
  assert_equal 2, mq.take_next_task(1,0.00001).task_id
90
85
  end
91
86