skynet 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +49 -0
- data/Manifest.txt +84 -6
- data/README.txt +75 -64
- data/app_generators/skynet_install/skynet_install_generator.rb +14 -8
- data/app_generators/skynet_install/templates/migration.rb +1 -24
- data/app_generators/skynet_install/templates/skynet_config.rb +50 -0
- data/app_generators/skynet_install/templates/skynet_initializer.rb +1 -0
- data/app_generators/skynet_install/templates/{skynet_schema.sql → skynet_mysql_schema.sql} +1 -24
- data/bin/skynet +37 -10
- data/bin/skynet_install +5 -5
- data/bin/skynet_tuplespace_server +27 -19
- data/examples/dgrep/README +70 -0
- data/examples/dgrep/config/skynet_config.rb +26 -0
- data/examples/dgrep/data/shakespeare/README +2 -0
- data/examples/dgrep/data/shakespeare/poetry/loverscomplaint +381 -0
- data/examples/dgrep/data/shakespeare/poetry/rapeoflucrece +2199 -0
- data/examples/dgrep/data/shakespeare/poetry/sonnets +2633 -0
- data/examples/dgrep/data/shakespeare/poetry/various +640 -0
- data/examples/dgrep/data/shakespeare/poetry/venusandadonis +1423 -0
- data/examples/dgrep/data/testfile1.txt +1 -0
- data/examples/dgrep/data/testfile2.txt +1 -0
- data/examples/dgrep/data/testfile3.txt +1 -0
- data/examples/dgrep/data/testfile4.txt +1 -0
- data/examples/dgrep/lib/dgrep.rb +59 -0
- data/examples/dgrep/lib/mapreduce_test.rb +32 -0
- data/examples/dgrep/lib/most_common_words.rb +45 -0
- data/examples/dgrep/script/dgrep +75 -0
- data/examples/rails_mysql_example/README +66 -0
- data/examples/rails_mysql_example/Rakefile +10 -0
- data/examples/rails_mysql_example/app/controllers/application.rb +10 -0
- data/examples/rails_mysql_example/app/helpers/application_helper.rb +3 -0
- data/examples/rails_mysql_example/app/models/user.rb +21 -0
- data/examples/rails_mysql_example/app/models/user_favorite.rb +5 -0
- data/examples/rails_mysql_example/app/models/user_mailer.rb +12 -0
- data/examples/rails_mysql_example/app/views/user_mailer/welcome.erb +5 -0
- data/examples/rails_mysql_example/config/boot.rb +109 -0
- data/examples/rails_mysql_example/config/database.yml +42 -0
- data/examples/rails_mysql_example/config/environment.rb +59 -0
- data/examples/rails_mysql_example/config/environments/development.rb +18 -0
- data/examples/rails_mysql_example/config/environments/production.rb +19 -0
- data/examples/rails_mysql_example/config/environments/test.rb +22 -0
- data/examples/rails_mysql_example/config/initializers/inflections.rb +10 -0
- data/examples/rails_mysql_example/config/initializers/mime_types.rb +5 -0
- data/examples/rails_mysql_example/config/initializers/skynet.rb +1 -0
- data/examples/rails_mysql_example/config/routes.rb +35 -0
- data/examples/rails_mysql_example/config/skynet_config.rb +36 -0
- data/examples/rails_mysql_example/db/migrate/001_create_skynet_tables.rb +43 -0
- data/examples/rails_mysql_example/db/migrate/002_create_users.rb +16 -0
- data/examples/rails_mysql_example/db/migrate/003_create_user_favorites.rb +14 -0
- data/examples/rails_mysql_example/db/schema.rb +85 -0
- data/examples/rails_mysql_example/db/skynet_mysql_schema.sql +33 -0
- data/examples/rails_mysql_example/doc/README_FOR_APP +2 -0
- data/examples/rails_mysql_example/lib/tasks/rails_mysql_example.rake +20 -0
- data/examples/rails_mysql_example/public/.htaccess +40 -0
- data/examples/rails_mysql_example/public/404.html +30 -0
- data/examples/rails_mysql_example/public/422.html +30 -0
- data/examples/rails_mysql_example/public/500.html +30 -0
- data/examples/rails_mysql_example/public/dispatch.cgi +10 -0
- data/examples/rails_mysql_example/public/dispatch.fcgi +24 -0
- data/examples/rails_mysql_example/public/dispatch.rb +10 -0
- data/{log/debug.log → examples/rails_mysql_example/public/favicon.ico} +0 -0
- data/examples/rails_mysql_example/public/images/rails.png +0 -0
- data/examples/rails_mysql_example/public/index.html +277 -0
- data/examples/rails_mysql_example/public/javascripts/application.js +2 -0
- data/examples/rails_mysql_example/public/javascripts/controls.js +963 -0
- data/examples/rails_mysql_example/public/javascripts/dragdrop.js +972 -0
- data/examples/rails_mysql_example/public/javascripts/effects.js +1120 -0
- data/examples/rails_mysql_example/public/javascripts/prototype.js +4225 -0
- data/examples/rails_mysql_example/public/robots.txt +5 -0
- data/examples/rails_mysql_example/script/about +3 -0
- data/examples/rails_mysql_example/script/console +3 -0
- data/examples/rails_mysql_example/script/destroy +3 -0
- data/examples/rails_mysql_example/script/generate +3 -0
- data/examples/rails_mysql_example/script/performance/benchmarker +3 -0
- data/examples/rails_mysql_example/script/performance/profiler +3 -0
- data/examples/rails_mysql_example/script/performance/request +3 -0
- data/examples/rails_mysql_example/script/plugin +3 -0
- data/examples/rails_mysql_example/script/process/inspector +3 -0
- data/examples/rails_mysql_example/script/process/reaper +3 -0
- data/examples/rails_mysql_example/script/process/spawner +3 -0
- data/examples/rails_mysql_example/script/runner +3 -0
- data/examples/rails_mysql_example/script/server +3 -0
- data/examples/rails_mysql_example/test/fixtures/user_favorites.yml +9 -0
- data/examples/rails_mysql_example/test/fixtures/users.yml +11 -0
- data/examples/rails_mysql_example/test/test_helper.rb +38 -0
- data/examples/rails_mysql_example/test/unit/user_favorite_test.rb +8 -0
- data/examples/rails_mysql_example/test/unit/user_test.rb +8 -0
- data/extras/README +7 -0
- data/extras/init.d/skynet +87 -0
- data/extras/nagios/check_skynet.sh +121 -0
- data/extras/rails/controllers/skynet_controller.rb +43 -0
- data/extras/rails/views/skynet/index.rhtml +137 -0
- data/lib/skynet.rb +59 -1
- data/lib/skynet/mapreduce_helper.rb +2 -2
- data/lib/skynet/mapreduce_test.rb +32 -1
- data/lib/skynet/message_queue_adapters/mysql.rb +422 -539
- data/lib/skynet/message_queue_adapters/tuple_space.rb +45 -71
- data/lib/skynet/skynet_active_record_extensions.rb +22 -11
- data/lib/skynet/skynet_config.rb +54 -20
- data/lib/skynet/skynet_console.rb +4 -1
- data/lib/skynet/skynet_console_helper.rb +5 -1
- data/lib/skynet/skynet_debugger.rb +58 -4
- data/lib/skynet/skynet_job.rb +61 -24
- data/lib/skynet/skynet_launcher.rb +29 -3
- data/lib/skynet/skynet_logger.rb +11 -1
- data/lib/skynet/skynet_manager.rb +403 -240
- data/lib/skynet/skynet_message.rb +1 -3
- data/lib/skynet/skynet_message_queue.rb +42 -19
- data/lib/skynet/skynet_partitioners.rb +19 -15
- data/lib/skynet/skynet_ruby_extensions.rb +18 -0
- data/lib/skynet/skynet_tuplespace_server.rb +17 -14
- data/lib/skynet/skynet_worker.rb +132 -98
- data/lib/skynet/version.rb +1 -1
- data/script/destroy +0 -0
- data/script/generate +0 -0
- data/script/txt2html +0 -0
- data/test/test_helper.rb +2 -0
- data/test/test_skynet.rb +13 -5
- data/test/test_skynet_manager.rb +24 -9
- data/test/test_skynet_task.rb +1 -1
- data/website/index.html +77 -29
- data/website/index.txt +53 -24
- data/website/stylesheets/screen.css +12 -12
- metadata +156 -66
- data/app_generators/skynet_install/templates/skynet +0 -46
- data/log/skynet.log +0 -29
- data/log/skynet_tuplespace_server.log +0 -7
- data/log/skynet_worker.pid +0 -1
@@ -310,6 +310,7 @@ class Skynet
|
|
310
310
|
end
|
311
311
|
|
312
312
|
class WorkerStatusMessage < Skynet::Message
|
313
|
+
# I'd love to rename tasktype and tasksubtype to something more reasonable
|
313
314
|
self.fields = [
|
314
315
|
:tasktype,
|
315
316
|
:tasksubtype,
|
@@ -330,13 +331,11 @@ class Skynet
|
|
330
331
|
|
331
332
|
def initialize(opts)
|
332
333
|
super
|
333
|
-
self.tasktype = :status
|
334
334
|
self.tasksubtype = :worker
|
335
335
|
end
|
336
336
|
|
337
337
|
def self.worker_status_template(opts)
|
338
338
|
template = {
|
339
|
-
:tasktype => :status,
|
340
339
|
:tasksubtype => :worker,
|
341
340
|
:hostname => opts[:hostname],
|
342
341
|
:process_id => opts[:process_id]
|
@@ -348,7 +347,6 @@ class Skynet
|
|
348
347
|
|
349
348
|
def self.all_workers_template(hostname=nil)
|
350
349
|
template = {
|
351
|
-
:tasktype => :status,
|
352
350
|
:tasksubtype => :worker,
|
353
351
|
:hostname => hostname,
|
354
352
|
}
|
@@ -12,27 +12,48 @@ class Skynet
|
|
12
12
|
class RequestExpiredError < Skynet::Error
|
13
13
|
end
|
14
14
|
|
15
|
-
# This class is the interface to the Skynet Message Queue.
|
15
|
+
# This class is the interface to the Skynet Message Queue.
|
16
16
|
class MessageQueue
|
17
17
|
|
18
18
|
include SkynetDebugger
|
19
19
|
|
20
|
-
require 'forwardable'
|
21
|
-
extend Forwardable
|
22
|
-
|
20
|
+
require 'forwardable'
|
21
|
+
extend Forwardable
|
22
|
+
|
23
23
|
def self.adapter
|
24
|
-
|
24
|
+
adapter_class.constantize.adapter
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
def self.adapter_class
|
28
|
+
Skynet::CONFIG[:MESSAGE_QUEUE_ADAPTER]
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.start_or_connect(adapter_class = self.adapter_class)
|
32
|
+
begin
|
33
|
+
mq = new
|
34
|
+
rescue Skynet::ConnectionError
|
35
|
+
if self.adapter == :tuplespace
|
36
|
+
pid = fork do
|
37
|
+
exec("skynet_tuplespace_server start")
|
38
|
+
end
|
39
|
+
sleep 5
|
40
|
+
end
|
41
|
+
new
|
32
42
|
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(message_queue_proxy_class=Skynet::CONFIG[:MESSAGE_QUEUE_ADAPTER])
|
33
46
|
mq
|
34
47
|
end
|
35
48
|
|
49
|
+
def self.message_queue_proxy_class
|
50
|
+
adapter_class.constantize
|
51
|
+
end
|
52
|
+
|
53
|
+
def message_queue_proxy_class
|
54
|
+
@message_queue_proxy_class ||= self.class.message_queue_proxy_class
|
55
|
+
end
|
56
|
+
|
36
57
|
# Is this version still active in the queue?
|
37
58
|
def version_active?(version,queue_id=0)
|
38
59
|
mq.version_active?(version,queue_id)
|
@@ -42,12 +63,12 @@ class Skynet
|
|
42
63
|
def get_worker_version
|
43
64
|
mq.get_worker_version
|
44
65
|
end
|
45
|
-
|
66
|
+
|
46
67
|
# Sets the current worker version (causing workers to restart)
|
47
68
|
def set_worker_version(version)
|
48
69
|
mq.set_worker_version(version)
|
49
70
|
end
|
50
|
-
|
71
|
+
|
51
72
|
# Increments the current worker version (causing workers to restart)
|
52
73
|
def increment_worker_version
|
53
74
|
newver = self.get_worker_version + 1
|
@@ -56,16 +77,18 @@ class Skynet
|
|
56
77
|
end
|
57
78
|
|
58
79
|
def mq
|
59
|
-
@mq ||=
|
80
|
+
@mq ||= message_queue_proxy_class.new(
|
81
|
+
:use_ringserver => Skynet::CONFIG[:TS_USE_RINGSERVER],
|
82
|
+
:ringserver_hosts => Skynet::CONFIG[:TS_SERVER_HOSTS],
|
83
|
+
:drburi => Skynet::CONFIG[:TS_DRBURI]
|
84
|
+
)
|
60
85
|
end
|
61
|
-
|
86
|
+
|
62
87
|
def_delegators :mq, :take_next_task, :write_message, :take_result, :write_error, :write_result,
|
63
|
-
:list_tasks, :list_results, :stats
|
64
|
-
|
65
|
-
|
66
|
-
|
88
|
+
:list_tasks, :list_results, :clear_outstanding_tasks, :clear_outstanding_results, :stats
|
89
|
+
|
90
|
+
|
67
91
|
|
68
|
-
|
69
92
|
def message_fields
|
70
93
|
Skynet::Message.fields
|
71
94
|
end
|
@@ -51,14 +51,16 @@ class Skynet
|
|
51
51
|
#
|
52
52
|
def self.reduce_partition(post_map_data,new_partitions)
|
53
53
|
return post_map_data unless post_map_data.is_a?(Array) and (not post_map_data.empty?) and post_map_data.first.is_a?(Array)
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
### Why did I do this? It breaks badly.
|
55
|
+
# if not post_map_data.first.first.is_a?(Array)
|
56
|
+
# partitioned_data = post_map_data.flatten
|
57
|
+
# else
|
57
58
|
partitioned_data = post_map_data.inject(Array.new) do |data,part|
|
58
59
|
data += part
|
59
60
|
end
|
60
|
-
end
|
61
|
+
# end
|
61
62
|
partitioned_data = Skynet::Partitioners::SimplePartitionData.reduce_partition(partitioned_data, new_partitions)
|
63
|
+
debug "POST PARTITIONED DATA_SIZE", partitioned_data.size
|
62
64
|
debug "POST PARTITIONED DATA", partitioned_data
|
63
65
|
partitioned_data
|
64
66
|
end
|
@@ -68,20 +70,22 @@ class Skynet
|
|
68
70
|
# Smarter partitioner for array data, generates simple sum of array[0]
|
69
71
|
# and ensures that all arrays sharing that key go into the same partition.
|
70
72
|
#
|
71
|
-
def self.reduce_partition(
|
72
|
-
partitions =
|
73
|
+
def self.reduce_partition(post_map_data, new_partitions)
|
74
|
+
partitions = []
|
73
75
|
(0..new_partitions - 1).each { |i| partitions[i] = Array.new }
|
74
|
-
|
75
|
-
|
76
|
-
partition.each do |array|
|
77
|
-
next unless array.
|
76
|
+
cnt = 0
|
77
|
+
post_map_data.each do |partition|
|
78
|
+
partition.each do |array|
|
79
|
+
next unless array.is_a?(Array) and array.size >= 2
|
78
80
|
if array[0].kind_of?(Fixnum)
|
79
|
-
key = array[0]
|
80
|
-
|
81
|
-
key = 0
|
82
|
-
|
81
|
+
key = array[0] % new_partitions
|
82
|
+
elsif array[0].kind_of?(String)
|
83
|
+
key = array[0].sum % new_partitions
|
84
|
+
else
|
85
|
+
cnt += 1
|
86
|
+
key = cnt % new_partitions
|
83
87
|
end
|
84
|
-
partitions[key
|
88
|
+
partitions[key] << array
|
85
89
|
end
|
86
90
|
end
|
87
91
|
partitions
|
@@ -32,4 +32,22 @@ module Enumerable
|
|
32
32
|
end
|
33
33
|
job.run
|
34
34
|
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class String
|
38
|
+
### THIS IS TAKEN DIRECTLY FROM ActiveSupport::Inflector
|
39
|
+
# Constantize tries to find a declared constant with the name specified
|
40
|
+
# in the string. It raises a NameError when the name is not in CamelCase
|
41
|
+
# or is not initialized.
|
42
|
+
#
|
43
|
+
# Examples
|
44
|
+
# "Module".constantize #=> Module
|
45
|
+
# "Class".constantize #=> Class
|
46
|
+
def constantize
|
47
|
+
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self
|
48
|
+
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
49
|
+
end
|
50
|
+
|
51
|
+
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
52
|
+
end
|
35
53
|
end
|
@@ -49,28 +49,31 @@ class Skynet
|
|
49
49
|
class Job
|
50
50
|
end
|
51
51
|
|
52
|
-
class
|
52
|
+
class TuplespaceServer
|
53
53
|
|
54
|
-
def
|
55
|
-
|
56
|
-
log
|
57
|
-
log.
|
54
|
+
def self.start(options)
|
55
|
+
options[:port] ||= 7647
|
56
|
+
log = Logger.new(options[:logfile])
|
57
|
+
log.level = Object.module_eval("#{"Logger::" + options[:loglevel].upcase}", __FILE__, __LINE__) if options[:loglevel]
|
58
|
+
log.info "STARTING TUPLESPACE SERVER ON PORT: #{options[:port]} Logging to #{options[:logfile]}"
|
58
59
|
|
59
60
|
# Create a TupleSpace to hold named services, and start running
|
61
|
+
ts = Rinda::TupleSpace.new
|
60
62
|
begin
|
61
|
-
|
63
|
+
if options[:use_ringserver] and options[:port]
|
64
|
+
DRb.start_service
|
65
|
+
tuple = [:name,:TupleSpace, ts, 'Tuple Space']
|
66
|
+
renewer = Rinda::SimpleRenewer.new
|
67
|
+
ring_ts = Rinda::TupleSpace.new
|
68
|
+
ring_ts.write(tuple, renewer)
|
69
|
+
|
70
|
+
server = Rinda::RingServer.new(ring_ts, options[:port])
|
71
|
+
end
|
62
72
|
if options[:drburi]
|
63
73
|
DRb.start_service(options[:drburi], ts)
|
64
|
-
else
|
65
|
-
DRb.start_service
|
66
74
|
end
|
67
|
-
tuple = [:name,:TupleSpace, ts, 'Tuple Space']
|
68
|
-
renewer = Rinda::SimpleRenewer.new
|
69
|
-
ring_ts = Rinda::TupleSpace.new
|
70
|
-
ring_ts.write(tuple, renewer)
|
71
|
-
|
72
|
-
server = Rinda::RingServer.new(ring_ts, options[:port])
|
73
75
|
DRb.thread.join
|
76
|
+
rescue SystemExit, Interrupt
|
74
77
|
rescue Exception, RuntimeError => e
|
75
78
|
log.fatal "Couldn't start Skynet Server #{e.inspect}"
|
76
79
|
end
|
data/lib/skynet/skynet_worker.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
class Skynet
|
1
|
+
class Skynet
|
2
2
|
class Worker
|
3
3
|
|
4
|
-
include SkynetDebugger
|
4
|
+
include SkynetDebugger
|
5
5
|
include Skynet::GuidGenerator
|
6
6
|
|
7
7
|
RETRY_TIME = 2
|
@@ -14,7 +14,7 @@ class Skynet
|
|
14
14
|
|
15
15
|
attr_accessor :message,:task, :mq, :processed
|
16
16
|
attr_reader :worker_id, :worker_info, :worker_type, :queue_id
|
17
|
-
|
17
|
+
|
18
18
|
class Error < StandardError; end
|
19
19
|
class RespawnWorker < Skynet::Error; end
|
20
20
|
class ConnectionFailure < Skynet::Error; end
|
@@ -23,57 +23,59 @@ class Skynet
|
|
23
23
|
def self.debug_class_desc
|
24
24
|
"WORKER-#{$$}"
|
25
25
|
end
|
26
|
-
|
27
|
-
def initialize(worker_type, options = {})
|
26
|
+
|
27
|
+
def initialize(worker_type, options = {})
|
28
28
|
@worker_id = get_unique_id(1).to_i
|
29
29
|
@worker_type = worker_type.to_sym
|
30
30
|
@queue_id = options[:queue_id] || 0
|
31
31
|
@processed = 0
|
32
|
+
@in_process = false
|
32
33
|
@mq = Skynet::MessageQueue.new
|
33
34
|
|
34
35
|
debug "THIS WORKER TAKES #{worker_type}"
|
35
36
|
|
36
|
-
@worker_info = {
|
37
|
+
@worker_info = {
|
38
|
+
:tasktype => worker_type,
|
37
39
|
:hostname => hostname,
|
38
40
|
:process_id => process_id,
|
39
|
-
:worker_type => payload_type,
|
41
|
+
:worker_type => payload_type,
|
40
42
|
:worker_id => worker_id,
|
41
43
|
:version => mq.get_worker_version,
|
42
|
-
}
|
44
|
+
}
|
43
45
|
@worker_info.merge!(options)
|
44
46
|
end
|
45
47
|
|
46
48
|
def process_id
|
47
49
|
$$
|
48
50
|
end
|
49
|
-
|
51
|
+
|
50
52
|
def hostname
|
51
53
|
@machine_name ||= Socket.gethostname
|
52
|
-
end
|
53
|
-
|
54
|
+
end
|
55
|
+
|
54
56
|
def version
|
55
57
|
@curver
|
56
58
|
end
|
57
|
-
|
59
|
+
|
58
60
|
def new_version_respawn?
|
59
61
|
if !@verchecktime
|
60
62
|
@verchecktime = Time.now
|
61
|
-
begin
|
63
|
+
begin
|
62
64
|
@curver = mq.get_worker_version
|
63
65
|
debug "FINDING INITIAL VER #{@curver}"
|
64
66
|
rescue Skynet::RequestExpiredError => e
|
65
67
|
warn "NO INITIAL VER IN MQ using 1"
|
66
68
|
@curver = 1
|
67
69
|
end
|
68
|
-
else
|
70
|
+
else
|
69
71
|
if Time.now < (@verchecktime + Skynet::CONFIG[:WORKER_VERSION_CHECK_DELAY])
|
70
72
|
return false
|
71
|
-
else
|
73
|
+
else
|
72
74
|
@verchecktime = Time.now
|
73
75
|
begin
|
74
76
|
newver = mq.get_worker_version
|
75
77
|
# debug "CURVER #{@curver} NEWVER: #{newver}"
|
76
|
-
if newver != @curver and not mq.version_active?(@curver, queue_id)
|
78
|
+
if newver != @curver and not mq.version_active?(@curver, queue_id)
|
77
79
|
info "RESTARTING WORKER ON PID #{$$}"
|
78
80
|
return true
|
79
81
|
end
|
@@ -85,19 +87,10 @@ class Skynet
|
|
85
87
|
end
|
86
88
|
end
|
87
89
|
return false
|
88
|
-
end
|
89
|
-
|
90
|
-
|
91
|
-
def take_worker_status
|
92
|
-
begin
|
93
|
-
mq.take_worker_status(@worker_info,0.00001)
|
94
|
-
rescue Skynet::RequestExpiredError, Skynet::QueueTimeout => e
|
95
|
-
error "Couldnt take worker status for #{hostname} pid: #{process_id}"
|
96
|
-
end
|
97
90
|
end
|
98
|
-
|
91
|
+
|
99
92
|
def notify_worker_started
|
100
|
-
|
93
|
+
write_worker_status(
|
101
94
|
@worker_info.merge({
|
102
95
|
:name => "waiting for #{@worker_type}",
|
103
96
|
:processed => 0,
|
@@ -105,17 +98,19 @@ class Skynet
|
|
105
98
|
})
|
106
99
|
)
|
107
100
|
end
|
108
|
-
|
101
|
+
|
109
102
|
def notify_task_begun(task)
|
110
103
|
task[:processed] = @processed
|
111
104
|
task[:started_at] = Time.now.to_i
|
112
|
-
|
105
|
+
@in_process = true
|
106
|
+
write_worker_status(@worker_info.merge(task))
|
113
107
|
end
|
114
|
-
|
108
|
+
|
115
109
|
def notify_task_complete
|
116
110
|
@processed += 1
|
111
|
+
@in_process = false
|
117
112
|
|
118
|
-
|
113
|
+
write_worker_status(
|
119
114
|
@worker_info.merge({
|
120
115
|
:task_id => 0,
|
121
116
|
:job_id => 0,
|
@@ -125,39 +120,74 @@ class Skynet
|
|
125
120
|
:started_at => Time.now.to_i
|
126
121
|
})
|
127
122
|
)
|
128
|
-
end
|
129
|
-
|
123
|
+
end
|
124
|
+
|
130
125
|
def notify_worker_stop
|
131
126
|
info "Worker #{process_id} stopping..."
|
132
|
-
|
133
|
-
|
127
|
+
write_worker_status(
|
128
|
+
@worker_info.merge({
|
129
|
+
:task_id => 0,
|
130
|
+
:job_id => 0,
|
131
|
+
:name => "waiting for #{@worker_type}",
|
132
|
+
:processed => @processed,
|
133
|
+
:process_id => nil,
|
134
|
+
:map_or_reduce => nil,
|
135
|
+
:started_at => Time.now.to_i
|
136
|
+
})
|
137
|
+
)
|
138
|
+
end
|
139
|
+
|
140
|
+
def manager_send(method,*args)
|
141
|
+
begin
|
142
|
+
manager.send(method,*args)
|
143
|
+
rescue DRb::DRbConnError, Errno::ECONNREFUSED => e
|
144
|
+
error "Worker could not connect to manager to call #{method} on manager #{e.inspect}"
|
145
|
+
rescue Exception => e
|
146
|
+
error "Worker could not connect call #{method} on manager #{e.inspect} args:", args
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def write_worker_status(status)
|
151
|
+
manager_send(:worker_notify,status)
|
152
|
+
end
|
153
|
+
|
154
|
+
def manager
|
155
|
+
Skynet::Manager.get
|
156
|
+
end
|
134
157
|
|
135
158
|
def payload_type
|
136
159
|
return nil if worker_type == :any
|
137
|
-
return worker_type
|
160
|
+
return worker_type
|
138
161
|
end
|
139
|
-
|
162
|
+
|
140
163
|
def interrupt
|
141
164
|
if @die
|
142
165
|
exit
|
143
166
|
else
|
144
167
|
@die = true
|
145
|
-
|
168
|
+
if not @in_process
|
169
|
+
notify_worker_stop
|
170
|
+
exit
|
171
|
+
end
|
172
|
+
end
|
146
173
|
end
|
147
|
-
|
174
|
+
|
148
175
|
def start
|
149
176
|
exceptions = 0
|
150
177
|
conerror = 0
|
151
178
|
@curver = nil
|
152
|
-
|
179
|
+
|
153
180
|
# setup signal handlers for manager
|
154
|
-
Signal.trap("HUP")
|
181
|
+
Signal.trap("HUP") do
|
182
|
+
@respawn = true
|
183
|
+
raise Skynet::Worker::RespawnWorker.new if not @in_process
|
184
|
+
end
|
155
185
|
Signal.trap("TERM") { interrupt }
|
156
|
-
Signal.trap("INT") {
|
157
|
-
|
186
|
+
Signal.trap("INT") { interrupt }
|
187
|
+
|
158
188
|
raise Skynet::Worker::RespawnWorker.new if new_version_respawn?
|
159
|
-
|
160
|
-
|
189
|
+
|
190
|
+
printlog "STARTING WORKER @ VER:#{@curver} type:#{@worker_type} QUEUE_ID:#{queue_id}"
|
161
191
|
|
162
192
|
notify_worker_started
|
163
193
|
|
@@ -165,13 +195,13 @@ class Skynet
|
|
165
195
|
task = nil
|
166
196
|
|
167
197
|
loop do
|
168
|
-
message = nil
|
169
|
-
begin
|
198
|
+
message = nil
|
199
|
+
begin
|
170
200
|
if Skynet::CONFIG[:WORKER_MAX_PROCESSED] and Skynet::CONFIG[:WORKER_MAX_PROCESSED] > 0 and @processed >= Skynet::CONFIG[:WORKER_MAX_PROCESSED]
|
171
201
|
raise Skynet::Worker::RespawnWorker.new("WORKER OVER MAX MEM AT: #{get_memory_size} MAX: #{Skynet::CONFIG[:WORKER_MAX_MEMORY]}")
|
172
202
|
end
|
173
|
-
if @die
|
174
|
-
exit
|
203
|
+
if @die
|
204
|
+
exit
|
175
205
|
elsif @respawn
|
176
206
|
raise Skynet::Worker::RespawnWorker.new()
|
177
207
|
end
|
@@ -179,7 +209,7 @@ class Skynet
|
|
179
209
|
if local_mem = max_memory_reached?
|
180
210
|
raise Skynet::Worker::RespawnWorker.new("WORKER OVER MAX MEM AT: #{local_mem} MAX: #{Skynet::CONFIG[:WORKER_MAX_MEMORY]}")
|
181
211
|
end
|
182
|
-
|
212
|
+
|
183
213
|
if conerror > 0
|
184
214
|
@mq = Skynet::MessageQueue.new
|
185
215
|
warn "WORKER RECONNECTED AFTER #{conerror} tries"
|
@@ -187,14 +217,14 @@ class Skynet
|
|
187
217
|
end
|
188
218
|
|
189
219
|
# debug "1 START LOOPSSS at VER #{@curver}"
|
190
|
-
#
|
220
|
+
#
|
191
221
|
# debug "LOOK FOR WORK USING TEMPLATE", Skynet::Message.task_template(@curver)
|
192
222
|
# message = Skynet::Message.new(mq.take(Skynet::Message.task_template(@curver),0.00001))
|
193
223
|
message = mq.take_next_task(@curver, 0.00001, payload_type, queue_id)
|
194
224
|
|
195
225
|
next unless message.respond_to?(:payload)
|
196
226
|
|
197
|
-
task = message.payload
|
227
|
+
task = message.payload
|
198
228
|
error "BAD MESSAGE", task unless task.respond_to?(:map_or_reduce)
|
199
229
|
|
200
230
|
info "STEP 2 GOT MESSAGE #{message.name} type:#{task.map_or_reduce}, jobid: #{message.job_id}, taskid:#{message.task_id} it: #{message.iteration}"
|
@@ -207,11 +237,11 @@ class Skynet
|
|
207
237
|
# task.debug "taking task #{task.task_id} name:#{task.name}..."
|
208
238
|
|
209
239
|
info "STEP 4 RUNNING TASK #{message.name} jobid: #{message.job_id} taskid: #{task.task_id}"
|
210
|
-
notify_task_begun({
|
211
|
-
:job_id => message.job_id,
|
212
|
-
:task_id => message.task_id,
|
213
|
-
:iteration => message.iteration,
|
214
|
-
:name => message.name,
|
240
|
+
notify_task_begun({
|
241
|
+
:job_id => message.job_id,
|
242
|
+
:task_id => message.task_id,
|
243
|
+
:iteration => message.iteration,
|
244
|
+
:name => message.name,
|
215
245
|
:map_or_reduce => task.map_or_reduce
|
216
246
|
})
|
217
247
|
result = task.run(message.iteration)
|
@@ -222,22 +252,22 @@ class Skynet
|
|
222
252
|
result_message = mq.write_result(message,result,task.result_timeout)
|
223
253
|
info "STEP 6 WROTE RESULT MESSAGE #{message.name} jobid: #{message.job_id} taskid: #{task.task_id}"
|
224
254
|
# debug "STEP 6.1 RESULT_MESSAGE:", result_message
|
225
|
-
notify_task_complete
|
255
|
+
notify_task_complete
|
226
256
|
|
227
257
|
rescue Skynet::Task::TimeoutError => e
|
228
258
|
error "Task timed out while executing #{e.inspect} #{e.backtrace.join("\n")}"
|
259
|
+
@in_process = false
|
229
260
|
next
|
230
261
|
|
231
|
-
rescue Skynet::Worker::RespawnWorker => e
|
262
|
+
rescue Skynet::Worker::RespawnWorker => e
|
232
263
|
info "Respawning and taking worker status #{e.message}"
|
233
264
|
notify_worker_stop
|
234
|
-
raise e
|
265
|
+
raise e
|
235
266
|
|
236
267
|
rescue Skynet::RequestExpiredError => e
|
237
268
|
if new_version_respawn?
|
238
269
|
notify_worker_stop
|
239
|
-
|
240
|
-
manager.restart_worker($$) if manager
|
270
|
+
manager_send(:restart_worker,$$)
|
241
271
|
end
|
242
272
|
sleep 1
|
243
273
|
next
|
@@ -251,15 +281,15 @@ class Skynet
|
|
251
281
|
if conerror > 20
|
252
282
|
fatal "TOO MANY RECONNECTION EXCEPTIONS #{e.message}"
|
253
283
|
notify_worker_stop
|
254
|
-
raise e
|
284
|
+
raise e
|
255
285
|
end
|
256
286
|
next
|
257
287
|
|
258
288
|
rescue NoManagerError => e
|
259
289
|
fatal e.message
|
260
|
-
break
|
290
|
+
break
|
261
291
|
rescue Interrupt, SystemExit => e
|
262
|
-
|
292
|
+
info "Exiting..."
|
263
293
|
notify_worker_stop
|
264
294
|
break
|
265
295
|
rescue Exception => e
|
@@ -274,6 +304,7 @@ class Skynet
|
|
274
304
|
# mq.write_error(message,"ERROR in WORKER [#{$$}] #{e.inspect} #{e.backtrace.join("\n")}")
|
275
305
|
end
|
276
306
|
# mq.write_error("ERROR in WORKER [#{$$}] #{e.inspect} #{e.backtrace.join("\n")}")
|
307
|
+
@in_process = false
|
277
308
|
next
|
278
309
|
end
|
279
310
|
end
|
@@ -282,7 +313,7 @@ class Skynet
|
|
282
313
|
@@ok_to_mem_check = false
|
283
314
|
@@lastmem = nil
|
284
315
|
@@memct = 0
|
285
|
-
|
316
|
+
|
286
317
|
def max_memory_reached?
|
287
318
|
return false unless ok_to_mem_check?
|
288
319
|
if !@memchecktime
|
@@ -296,7 +327,7 @@ class Skynet
|
|
296
327
|
false
|
297
328
|
end
|
298
329
|
end
|
299
|
-
|
330
|
+
|
300
331
|
def find_pid_size(file, format=:notpretty)
|
301
332
|
begin
|
302
333
|
open(file).each { |line|
|
@@ -321,49 +352,38 @@ class Skynet
|
|
321
352
|
return false if @@ok_to_mem_check == :notok
|
322
353
|
if File.exists?('/proc/self/status')
|
323
354
|
@@lastmem ||= get_memory_size.to_i
|
324
|
-
return @@ok_to_mem_check = true
|
355
|
+
return @@ok_to_mem_check = true
|
325
356
|
else
|
326
357
|
@@ok_to_mem_check = :notok
|
327
|
-
return false
|
328
|
-
end
|
329
|
-
end
|
330
|
-
|
331
|
-
|
332
|
-
# kinda like system() but gives me back a pid
|
333
|
-
def self.fork_and_exec(command)
|
334
|
-
sleep 0.01 # remove contention on manager drb object
|
335
|
-
log = Skynet::Logger.get
|
336
|
-
info "executing /bin/sh -c \"#{command}\""
|
337
|
-
pid = fork do
|
338
|
-
exec("/bin/sh -c \"#{command}\"")
|
339
|
-
exit
|
358
|
+
return false
|
340
359
|
end
|
341
|
-
Process.detach(pid)
|
342
|
-
pid
|
343
360
|
end
|
344
361
|
|
345
362
|
def self.start(options={})
|
346
363
|
options[:worker_type] ||= :any
|
347
364
|
options[:required_libs] ||= []
|
348
|
-
|
365
|
+
|
349
366
|
OptionParser.new do |opt|
|
350
367
|
opt.banner = "Usage: worker [options]"
|
351
368
|
opt.on('-r', '--required LIBRARY', 'Include the specified libraries') do |v|
|
352
369
|
options[:required_libs] << v
|
353
370
|
end
|
354
|
-
opt.on('
|
371
|
+
opt.on('--worker_type=WORKERTYPE', "master, task or any") do |v|
|
355
372
|
if ["any","master","task"].include?(v)
|
356
373
|
options[:worker_type] = v
|
357
374
|
else
|
358
375
|
raise Skynet::Error.new("#{v} is not a valid worker_type")
|
359
376
|
end
|
360
377
|
end
|
361
|
-
opt.on('
|
378
|
+
opt.on('--config=CONFIG_FILE', 'Where to find the skynet.rb config file') do |v|
|
379
|
+
options[:config_file] = File.expand_path(v)
|
380
|
+
end
|
381
|
+
opt.on('--queue=QUEUE_NAME', 'Which queue should these workers use (default "default").') do |v|
|
362
382
|
options[:queue] = v
|
363
|
-
end
|
364
|
-
opt.on('
|
383
|
+
end
|
384
|
+
opt.on('--queue_id=queue_id', 'Which queue should these workers use (default 0).') do |v|
|
365
385
|
options[:queue_id] = v.to_i
|
366
|
-
end
|
386
|
+
end
|
367
387
|
opt.parse!(ARGV)
|
368
388
|
end
|
369
389
|
|
@@ -381,21 +401,35 @@ class Skynet
|
|
381
401
|
error "The included lib #{adlib} was not found: #{e.inspect}"
|
382
402
|
exit
|
383
403
|
end
|
384
|
-
end
|
404
|
+
end
|
405
|
+
|
406
|
+
options[:config_file] ||= Skynet::CONFIG[:CONFIG_FILE]
|
407
|
+
if options[:config_file]
|
408
|
+
begin
|
409
|
+
require options[:config_file]
|
410
|
+
rescue MissingSourceFile => e
|
411
|
+
error "The config file at #{options[:config_file]} was not found: #{e.inspect}"
|
412
|
+
exit
|
413
|
+
end
|
414
|
+
else
|
415
|
+
error "Config file missing. Please add a config/skynet_config.rb before starting."
|
416
|
+
exit
|
417
|
+
end
|
385
418
|
|
386
419
|
debug "WORKER STARTING WORKER_TYPE?:#{options[:worker_type]}. QUEUE: #{Skynet::Config.new.queue_name_by_id(options[:queue_id])}"
|
387
420
|
|
388
|
-
begin
|
421
|
+
begin
|
389
422
|
worker = Skynet::Worker.new(options[:worker_type], options)
|
390
423
|
worker.start
|
391
424
|
rescue Skynet::Worker::NoManagerError => e
|
392
425
|
fatal e.message
|
393
|
-
exit
|
426
|
+
exit
|
394
427
|
rescue Skynet::Worker::RespawnWorker => e
|
395
428
|
warn "WORKER #{$$} SCRIPT CAUGHT RESPAWN. RESTARTING #{e.message}"
|
396
|
-
cmd = "ruby #{Skynet::CONFIG[:LAUNCHER_PATH]} --worker_type=#{options[:worker_type]} --queue_id=#{options[:queue_id]}"
|
429
|
+
cmd = "ruby #{Skynet::CONFIG[:LAUNCHER_PATH]} --worker_type=#{options[:worker_type]} --queue_id=#{options[:queue_id]} "
|
430
|
+
cmd << "--config=#{options[:config_file]} "
|
397
431
|
cmd << "-r #{options[:required_libs].join(' -r ')}" if options[:required_libs] and not options[:required_libs].empty?
|
398
|
-
pid = fork_and_exec(cmd)
|
432
|
+
pid = Skynet.fork_and_exec(cmd)
|
399
433
|
exit
|
400
434
|
rescue SystemExit
|
401
435
|
info "WORKER #{$$} EXITING GRACEFULLY"
|
@@ -408,10 +442,10 @@ class Skynet
|
|
408
442
|
end
|
409
443
|
end
|
410
444
|
|
411
|
-
class ExceptionReport
|
412
|
-
def initialize(*args)
|
413
|
-
end
|
414
|
-
|
445
|
+
class ExceptionReport
|
446
|
+
def initialize(*args)
|
447
|
+
end
|
448
|
+
|
415
449
|
def save
|
416
450
|
end
|
417
451
|
end
|