skynet 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/History.txt +49 -0
  2. data/Manifest.txt +84 -6
  3. data/README.txt +75 -64
  4. data/app_generators/skynet_install/skynet_install_generator.rb +14 -8
  5. data/app_generators/skynet_install/templates/migration.rb +1 -24
  6. data/app_generators/skynet_install/templates/skynet_config.rb +50 -0
  7. data/app_generators/skynet_install/templates/skynet_initializer.rb +1 -0
  8. data/app_generators/skynet_install/templates/{skynet_schema.sql → skynet_mysql_schema.sql} +1 -24
  9. data/bin/skynet +37 -10
  10. data/bin/skynet_install +5 -5
  11. data/bin/skynet_tuplespace_server +27 -19
  12. data/examples/dgrep/README +70 -0
  13. data/examples/dgrep/config/skynet_config.rb +26 -0
  14. data/examples/dgrep/data/shakespeare/README +2 -0
  15. data/examples/dgrep/data/shakespeare/poetry/loverscomplaint +381 -0
  16. data/examples/dgrep/data/shakespeare/poetry/rapeoflucrece +2199 -0
  17. data/examples/dgrep/data/shakespeare/poetry/sonnets +2633 -0
  18. data/examples/dgrep/data/shakespeare/poetry/various +640 -0
  19. data/examples/dgrep/data/shakespeare/poetry/venusandadonis +1423 -0
  20. data/examples/dgrep/data/testfile1.txt +1 -0
  21. data/examples/dgrep/data/testfile2.txt +1 -0
  22. data/examples/dgrep/data/testfile3.txt +1 -0
  23. data/examples/dgrep/data/testfile4.txt +1 -0
  24. data/examples/dgrep/lib/dgrep.rb +59 -0
  25. data/examples/dgrep/lib/mapreduce_test.rb +32 -0
  26. data/examples/dgrep/lib/most_common_words.rb +45 -0
  27. data/examples/dgrep/script/dgrep +75 -0
  28. data/examples/rails_mysql_example/README +66 -0
  29. data/examples/rails_mysql_example/Rakefile +10 -0
  30. data/examples/rails_mysql_example/app/controllers/application.rb +10 -0
  31. data/examples/rails_mysql_example/app/helpers/application_helper.rb +3 -0
  32. data/examples/rails_mysql_example/app/models/user.rb +21 -0
  33. data/examples/rails_mysql_example/app/models/user_favorite.rb +5 -0
  34. data/examples/rails_mysql_example/app/models/user_mailer.rb +12 -0
  35. data/examples/rails_mysql_example/app/views/user_mailer/welcome.erb +5 -0
  36. data/examples/rails_mysql_example/config/boot.rb +109 -0
  37. data/examples/rails_mysql_example/config/database.yml +42 -0
  38. data/examples/rails_mysql_example/config/environment.rb +59 -0
  39. data/examples/rails_mysql_example/config/environments/development.rb +18 -0
  40. data/examples/rails_mysql_example/config/environments/production.rb +19 -0
  41. data/examples/rails_mysql_example/config/environments/test.rb +22 -0
  42. data/examples/rails_mysql_example/config/initializers/inflections.rb +10 -0
  43. data/examples/rails_mysql_example/config/initializers/mime_types.rb +5 -0
  44. data/examples/rails_mysql_example/config/initializers/skynet.rb +1 -0
  45. data/examples/rails_mysql_example/config/routes.rb +35 -0
  46. data/examples/rails_mysql_example/config/skynet_config.rb +36 -0
  47. data/examples/rails_mysql_example/db/migrate/001_create_skynet_tables.rb +43 -0
  48. data/examples/rails_mysql_example/db/migrate/002_create_users.rb +16 -0
  49. data/examples/rails_mysql_example/db/migrate/003_create_user_favorites.rb +14 -0
  50. data/examples/rails_mysql_example/db/schema.rb +85 -0
  51. data/examples/rails_mysql_example/db/skynet_mysql_schema.sql +33 -0
  52. data/examples/rails_mysql_example/doc/README_FOR_APP +2 -0
  53. data/examples/rails_mysql_example/lib/tasks/rails_mysql_example.rake +20 -0
  54. data/examples/rails_mysql_example/public/.htaccess +40 -0
  55. data/examples/rails_mysql_example/public/404.html +30 -0
  56. data/examples/rails_mysql_example/public/422.html +30 -0
  57. data/examples/rails_mysql_example/public/500.html +30 -0
  58. data/examples/rails_mysql_example/public/dispatch.cgi +10 -0
  59. data/examples/rails_mysql_example/public/dispatch.fcgi +24 -0
  60. data/examples/rails_mysql_example/public/dispatch.rb +10 -0
  61. data/{log/debug.log → examples/rails_mysql_example/public/favicon.ico} +0 -0
  62. data/examples/rails_mysql_example/public/images/rails.png +0 -0
  63. data/examples/rails_mysql_example/public/index.html +277 -0
  64. data/examples/rails_mysql_example/public/javascripts/application.js +2 -0
  65. data/examples/rails_mysql_example/public/javascripts/controls.js +963 -0
  66. data/examples/rails_mysql_example/public/javascripts/dragdrop.js +972 -0
  67. data/examples/rails_mysql_example/public/javascripts/effects.js +1120 -0
  68. data/examples/rails_mysql_example/public/javascripts/prototype.js +4225 -0
  69. data/examples/rails_mysql_example/public/robots.txt +5 -0
  70. data/examples/rails_mysql_example/script/about +3 -0
  71. data/examples/rails_mysql_example/script/console +3 -0
  72. data/examples/rails_mysql_example/script/destroy +3 -0
  73. data/examples/rails_mysql_example/script/generate +3 -0
  74. data/examples/rails_mysql_example/script/performance/benchmarker +3 -0
  75. data/examples/rails_mysql_example/script/performance/profiler +3 -0
  76. data/examples/rails_mysql_example/script/performance/request +3 -0
  77. data/examples/rails_mysql_example/script/plugin +3 -0
  78. data/examples/rails_mysql_example/script/process/inspector +3 -0
  79. data/examples/rails_mysql_example/script/process/reaper +3 -0
  80. data/examples/rails_mysql_example/script/process/spawner +3 -0
  81. data/examples/rails_mysql_example/script/runner +3 -0
  82. data/examples/rails_mysql_example/script/server +3 -0
  83. data/examples/rails_mysql_example/test/fixtures/user_favorites.yml +9 -0
  84. data/examples/rails_mysql_example/test/fixtures/users.yml +11 -0
  85. data/examples/rails_mysql_example/test/test_helper.rb +38 -0
  86. data/examples/rails_mysql_example/test/unit/user_favorite_test.rb +8 -0
  87. data/examples/rails_mysql_example/test/unit/user_test.rb +8 -0
  88. data/extras/README +7 -0
  89. data/extras/init.d/skynet +87 -0
  90. data/extras/nagios/check_skynet.sh +121 -0
  91. data/extras/rails/controllers/skynet_controller.rb +43 -0
  92. data/extras/rails/views/skynet/index.rhtml +137 -0
  93. data/lib/skynet.rb +59 -1
  94. data/lib/skynet/mapreduce_helper.rb +2 -2
  95. data/lib/skynet/mapreduce_test.rb +32 -1
  96. data/lib/skynet/message_queue_adapters/mysql.rb +422 -539
  97. data/lib/skynet/message_queue_adapters/tuple_space.rb +45 -71
  98. data/lib/skynet/skynet_active_record_extensions.rb +22 -11
  99. data/lib/skynet/skynet_config.rb +54 -20
  100. data/lib/skynet/skynet_console.rb +4 -1
  101. data/lib/skynet/skynet_console_helper.rb +5 -1
  102. data/lib/skynet/skynet_debugger.rb +58 -4
  103. data/lib/skynet/skynet_job.rb +61 -24
  104. data/lib/skynet/skynet_launcher.rb +29 -3
  105. data/lib/skynet/skynet_logger.rb +11 -1
  106. data/lib/skynet/skynet_manager.rb +403 -240
  107. data/lib/skynet/skynet_message.rb +1 -3
  108. data/lib/skynet/skynet_message_queue.rb +42 -19
  109. data/lib/skynet/skynet_partitioners.rb +19 -15
  110. data/lib/skynet/skynet_ruby_extensions.rb +18 -0
  111. data/lib/skynet/skynet_tuplespace_server.rb +17 -14
  112. data/lib/skynet/skynet_worker.rb +132 -98
  113. data/lib/skynet/version.rb +1 -1
  114. data/script/destroy +0 -0
  115. data/script/generate +0 -0
  116. data/script/txt2html +0 -0
  117. data/test/test_helper.rb +2 -0
  118. data/test/test_skynet.rb +13 -5
  119. data/test/test_skynet_manager.rb +24 -9
  120. data/test/test_skynet_task.rb +1 -1
  121. data/website/index.html +77 -29
  122. data/website/index.txt +53 -24
  123. data/website/stylesheets/screen.css +12 -12
  124. metadata +156 -66
  125. data/app_generators/skynet_install/templates/skynet +0 -46
  126. data/log/skynet.log +0 -29
  127. data/log/skynet_tuplespace_server.log +0 -7
  128. data/log/skynet_worker.pid +0 -1
@@ -34,4 +34,62 @@ end
34
34
  require 'mapreduce_test'
35
35
  require 'skynet_launcher'
36
36
  require 'skynet_console'
37
- require 'mapreduce_helper'
37
+ require 'mapreduce_helper'
38
+
39
+
40
+ begin
41
+ require 'fastthread'
42
+ rescue LoadError
43
+ # puts 'fastthread not installed, using thread instead'
44
+ require 'thread'
45
+ end
46
+
47
+ class Skynet
48
+
49
+ # kinda like system() but gives me back a pid
50
+ def self.fork_and_exec(command)
51
+ sleep 0.01 # remove contention on manager drb object
52
+ log = Skynet::Logger.get
53
+ debug "executing /bin/sh -c \"#{command}\""
54
+ pid = safefork do
55
+ close_files
56
+ exec("/bin/sh -c \"#{command}\"")
57
+ exit
58
+ end
59
+ Process.detach(pid)
60
+ pid
61
+ end
62
+
63
+ def self.safefork (&block)
64
+ @fork_tries ||= 0
65
+ fork(&block)
66
+ rescue Errno::EWOULDBLOCK
67
+ raise if @fork_tries >= 20
68
+ @fork_tries += 1
69
+ sleep 5
70
+ retry
71
+ end
72
+
73
+
74
+ # close open file descriptors starting with STDERR+1
75
+ def self.close_files(from=3, to=50)
76
+ close_console
77
+ (from .. to).each do |fd|
78
+ IO.for_fd(fd).close rescue nil
79
+ end
80
+ end
81
+
82
+ def self.close_console
83
+ STDIN.reopen "/dev/null"
84
+ STDOUT.reopen "/dev/null", "a"
85
+ STDERR.reopen STDOUT
86
+ end
87
+
88
+ def self.process_alive?(worker_pid)
89
+ Process.kill(0,worker_pid)
90
+ return true
91
+ rescue Errno::ESRCH => e
92
+ return false
93
+ end
94
+
95
+ end
@@ -22,7 +22,7 @@ module MapreduceHelper
22
22
  # SomeUrlSlurper.gather_results(url) # returns an array of urls of sites that link to the given url
23
23
  # end
24
24
  #
25
- # def self.reduce(linked_from_url)
25
+ # def self.reduce_each(linked_from_url)
26
26
  # SomeUrlSluper.find_text("mysite", linked_from_url) # finds all the times "mysite" appears in the given url, which we know links to the url given in the map_data
27
27
  # end
28
28
  # end
@@ -56,7 +56,7 @@ module MapreduceHelper
56
56
  # Takes an array of post reduce_partitioned data, iterates over that array calling self.reduce_each(item) for each
57
57
  # item in that array. Catches exceptions in each iteration and continues processing.
58
58
  def reduce(reduce_partitioned_data_array)
59
- raise Skynet::Job::BadMapOrReduceError.new("#{self.class} has no self.reduce_each method.") unless self.respond_to?(:reduce_each)
59
+ return reduce_partitioned_data_array unless self.respond_to?(:reduce_each)
60
60
  if reduce_partitioned_data_array.is_a?(Array)
61
61
  results = []
62
62
  reduce_partitioned_data_array.each do |data|
@@ -1,7 +1,7 @@
1
1
  class Skynet
2
2
  class MapreduceTest
3
3
  include SkynetDebugger
4
-
4
+
5
5
  def self.map(datas)
6
6
  results = {}
7
7
  datas.each do |data|
@@ -22,4 +22,35 @@ class Skynet
22
22
  results
23
23
  end
24
24
  end
25
+
26
+ class ProfileCountTest
27
+ def self.run
28
+ job = Skynet::Job.new(
29
+ :mappers => 2,
30
+ :reducers => 1,
31
+ :map_reduce_class => self,
32
+ :map_data => [OpenStruct.new({:created_by => 2}),OpenStruct.new({:created_by => 2}),OpenStruct.new({:created_by => 3})]
33
+ )
34
+ results = job.run
35
+ end
36
+
37
+ def self.map(profiles)
38
+ result = Array.new
39
+ profiles.each do |profile|
40
+ result << [profile.created_by, 1] if profile.created_by
41
+ end
42
+ result
43
+ end
44
+
45
+ def self.reduce(pairs)
46
+ totals = Hash.new
47
+ pairs.each do |pair|
48
+ created_by, count = pair[0], pair[1]
49
+ totals[created_by] ||= 0
50
+ totals[created_by] += count
51
+ end
52
+ totals
53
+ end
54
+ end
55
+
25
56
  end
@@ -17,360 +17,305 @@ class Skynet
17
17
 
18
18
  class InvalidMessage < Skynet::Error
19
19
  end
20
-
21
- class MessageQueueAdapter
22
20
 
23
- class Mysql < Skynet::MessageQueueAdapter
24
-
25
- include SkynetDebugger
26
- include Skynet::GuidGenerator
21
+ class MessageQueueAdapter::Mysql < Skynet::MessageQueueAdapter
22
+
23
+ include SkynetDebugger
24
+ include Skynet::GuidGenerator
27
25
 
28
- SEARCH_FIELDS = [:tasktype, :task_id, :job_id, :payload_type, :expire_time, :iteration, :version] unless defined?(SEARCH_FIELDS)
29
-
30
- Skynet::CONFIG[:MYSQL_MESSAGE_QUEUE_TEMP_CHECK_DELAY] ||= 30
31
-
32
- @@db_set = false
33
-
34
- def self.adapter
35
- :mysql
36
- end
26
+ SEARCH_FIELDS = [:tasktype, :task_id, :job_id, :payload_type, :expire_time, :iteration, :version] unless defined?(SEARCH_FIELDS)
27
+
28
+ Skynet::CONFIG[:MYSQL_MESSAGE_QUEUE_TEMP_CHECK_DELAY] ||= 30
29
+
30
+ @@db_set = false
31
+
32
+ def self.adapter
33
+ :mysql
34
+ end
37
35
 
38
- def initialize
39
- if Skynet::CONFIG[:MYSQL_MESSAGE_QUEUE_TABLE]
40
- SkynetMessageQueue.table_name = Skynet::CONFIG[:MYSQL_MESSAGE_QUEUE_TABLE]
41
- end
42
- if not @@db_set
43
- if Skynet::CONFIG[:MYSQL_QUEUE_DATABASE]
44
- begin
45
- SkynetMessageQueue.establish_connection Skynet::CONFIG[:MYSQL_QUEUE_DATABASE]
46
- SkynetWorkerQueue.establish_connection Skynet::CONFIG[:MYSQL_QUEUE_DATABASE]
47
- rescue ActiveRecord::AdapterNotSpecified => e
48
- error "#{Skynet::CONFIG[:MYSQL_QUEUE_DATABASE]} not defined as a database adaptor #{e.message}"
49
- end
50
- elsif not ActiveRecord::Base.connected?
51
- db_options = {
52
- :adapter => Skynet::CONFIG[:MYSQL_ADAPTER],
53
- :host => Skynet::CONFIG[:MYSQL_HOST],
54
- :username => Skynet::CONFIG[:MYSQL_USERNAME],
55
- :password => Skynet::CONFIG[:MYSQL_PASSWORD],
56
- :database => Skynet::CONFIG[:MYSQL_DATABASE]
57
- }
58
- ActiveRecord::Base.establish_connection(db_options)
36
+ def self.start_or_connect(options={})
37
+ new
38
+ end
39
+
40
+ def initialize(options={})
41
+ if Skynet::CONFIG[:MYSQL_MESSAGE_QUEUE_TABLE]
42
+ SkynetMessageQueue.table_name = Skynet::CONFIG[:MYSQL_MESSAGE_QUEUE_TABLE]
43
+ end
44
+ if not @@db_set
45
+ if Skynet::CONFIG[:MYSQL_QUEUE_DATABASE]
46
+ begin
47
+ SkynetMessageQueue.establish_connection Skynet::CONFIG[:MYSQL_QUEUE_DATABASE]
48
+ SkynetWorkerQueue.establish_connection Skynet::CONFIG[:MYSQL_QUEUE_DATABASE]
49
+ rescue ActiveRecord::AdapterNotSpecified => e
50
+ error "#{Skynet::CONFIG[:MYSQL_QUEUE_DATABASE]} not defined as a database adaptor #{e.message}"
59
51
  end
52
+ elsif (not ActiveRecord::Base.connected?) and Skynet::CONFIG[:MYSQL_DATABASE]
53
+ db_options = {
54
+ :adapter => Skynet::CONFIG[:MYSQL_ADAPTER],
55
+ :host => Skynet::CONFIG[:MYSQL_HOST],
56
+ :username => Skynet::CONFIG[:MYSQL_USERNAME],
57
+ :password => Skynet::CONFIG[:MYSQL_PASSWORD],
58
+ :database => Skynet::CONFIG[:MYSQL_DATABASE]
59
+ }
60
+ ActiveRecord::Base.establish_connection(db_options)
60
61
  end
61
- @@db_set = true
62
-
63
- end
64
-
65
- def message_queue_table
66
- Skynet::CONFIG[:MYSQL_MESSAGE_QUEUE_TABLE] || SkynetMessageQueue.table_name
67
- end
68
-
69
- def self.debug_class_desc
70
- "MYSQLMQ"
71
62
  end
63
+ @@db_set = true
72
64
 
73
- def message_to_conditions(message)
74
- template_to_conditions(message.to_a)
75
- end
65
+ end
66
+
67
+ def message_queue_table
68
+ Skynet::CONFIG[:MYSQL_MESSAGE_QUEUE_TABLE] || SkynetMessageQueue.table_name
69
+ end
70
+
71
+ def self.debug_class_desc
72
+ "MYSQLMQ"
73
+ end
74
+
75
+ def message_to_conditions(message)
76
+ template_to_conditions(message.to_a)
77
+ end
76
78
 
77
- def template_to_conditions(template,fields=Skynet::Message.fields)
78
- conditions = []
79
- values = []
80
-
81
- fields.each_with_index do |field,ii|
82
- value = template[ii]
83
- next unless value
84
- if value.is_a?(Range)
85
- conditions << "#{field} BETWEEN #{value.first} AND #{value.last}"
86
- elsif value.is_a?(Symbol) or value.is_a?(String)
87
- conditions << "#{field} = '#{value}'"
88
- else
89
- conditions << "#{field} = #{value}"
90
- end
91
- end
92
- return '' if conditions.empty?
93
- return conditions.join(" AND ")
79
+ def template_to_conditions(template,fields=Skynet::Message.fields)
80
+ conditions = []
81
+ values = []
82
+
83
+ fields.each_with_index do |field,ii|
84
+ value = template[ii]
85
+ next unless value
86
+ if value.is_a?(Range)
87
+ conditions << "#{field} BETWEEN #{value.first} AND #{value.last}"
88
+ elsif value.is_a?(Symbol) or value.is_a?(String)
89
+ conditions << "#{field} = '#{value}'"
90
+ else
91
+ conditions << "#{field} = #{value}"
92
+ end
94
93
  end
95
-
96
- def message_to_hash(message,timeout=nil,fields=Skynet::Message.fields)
97
- timeout ||= message.expiry
98
- hash = {}
99
- fields.each do |field|
100
- next if field == :drburi
101
- # next unless message.send(field)
102
- if message.send(field).is_a?(Symbol)
103
- hash[field] = message.send(field).to_s
104
- elsif field == :payload
105
- hash[:raw_payload] = message.raw_payload
106
- else
107
- hash[field] = message.send(field)
108
- end
109
- end
110
- if timeout
111
- hash[:timeout] = timeout
112
- hash[:expire_time] = (Time.now.to_f + timeout) unless hash[:expire_time]
94
+ return '' if conditions.empty?
95
+ return conditions.join(" AND ")
96
+ end
97
+
98
+ def message_to_hash(message,timeout=nil,fields=Skynet::Message.fields)
99
+ timeout ||= message.expiry
100
+ hash = {}
101
+ fields.each do |field|
102
+ next if field == :drburi
103
+ # next unless message.send(field)
104
+ if message.send(field).is_a?(Symbol)
105
+ hash[field] = message.send(field).to_s
106
+ elsif field == :payload
107
+ hash[:raw_payload] = message.raw_payload
108
+ else
109
+ hash[field] = message.send(field)
113
110
  end
114
- hash
115
111
  end
116
-
117
- def write_fallback_message(message_row, message)
118
- tran_id = get_unique_id(1)
119
- ftm = message.fallback_task_message
120
- update_sql = %{
121
- update #{message_queue_table}
122
- SET iteration = #{ftm.iteration },
123
- expire_time = #{ftm.expire_time},
124
- updated_on = '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}',
125
- tran_id = #{tran_id}
126
- WHERE id = #{message_row.id} AND iteration = #{message.iteration}
127
- AND tran_id #{(message_row.tran_id ? " =#{message_row.tran_id}" : ' IS NULL')}
128
- }
129
- rows = update(update_sql) || 0
130
- message_row.tran_id = tran_id if rows == 1
131
- rows
112
+ if timeout
113
+ hash[:timeout] = timeout
114
+ hash[:expire_time] = (Time.now.to_f + timeout) unless hash[:expire_time]
132
115
  end
133
-
134
- def take_next_task(curver,timeout=0.5,payload_type=nil,queue_id=0)
135
- timeout = Skynet::CONFIG[:MYSQL_NEXT_TASK_TIMEOUT] if timeout < 1
136
- debug "TASK NEXT TASK!!!!!!! timeout: #{timeout} queue_id:#{queue_id}"
116
+ hash
117
+ end
118
+
119
+ def write_fallback_message(message_row, message)
120
+ tran_id = get_unique_id(1)
121
+ ftm = message.fallback_task_message
122
+ update_sql = %{
123
+ update #{message_queue_table}
124
+ SET iteration = #{ftm.iteration },
125
+ expire_time = #{ftm.expire_time},
126
+ updated_on = '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}',
127
+ tran_id = #{tran_id}
128
+ WHERE id = #{message_row.id} AND iteration = #{message.iteration}
129
+ AND tran_id #{(message_row.tran_id ? " =#{message_row.tran_id}" : ' IS NULL')}
130
+ }
131
+ rows = update(update_sql) || 0
132
+ message_row.tran_id = tran_id if rows == 1
133
+ rows
134
+ end
135
+
136
+ def take_next_task(curver,timeout=0.5,payload_type=nil,queue_id=0)
137
+ timeout = Skynet::CONFIG[:MYSQL_NEXT_TASK_TIMEOUT] if timeout < 1
138
+ debug "TASK NEXT TASK!!!!!!! timeout: #{timeout} queue_id:#{queue_id}"
137
139
 
138
- start = Time.now
139
- template = Skynet::Message.next_task_template(curver, payload_type)
140
+ start = Time.now
141
+ template = Skynet::Message.next_task_template(curver, payload_type)
142
+ message = nil
143
+
144
+ loop do
145
+ rows = 0
140
146
  message = nil
141
-
142
- loop do
143
- rows = 0
144
- message = nil
145
- template = Skynet::Message.next_task_template(curver, payload_type)
146
- begin
147
- message_row = find_next_message(template, payload_type)
148
- if message_row
149
- message = Skynet::Message.new(message_row.attributes)
150
- rows = write_fallback_message(message_row, message)
151
-
152
- if rows < 1
153
- old_temp = temperature(payload_type)
154
- set_temperature(payload_type, template_to_conditions(template), queue_id)
155
- debug "MISSCOLLISION PTYPE #{payload_type} OLDTEMP: #{old_temp} NEWTEMP: #{temperature(payload_type)}"
156
- else
157
- break
158
- end
159
- else # no messages on queue with this temp
160
- old_temp = temperature(payload_type)
161
- if old_temp > 1
162
- set_temperature(payload_type, template_to_conditions(template), queue_id)
163
- end
164
- debug "MISS PTYPE #{payload_type} OLDTEMP: #{old_temp} NEWTEMP: #{temperature(payload_type)}"
165
- end
166
- rescue Skynet::Message::BadMessage => e
167
- message_row.destroy
168
- next
169
- rescue ActiveRecord::StatementInvalid => e
170
- if e.message =~ /Deadlock/
147
+ template = Skynet::Message.next_task_template(curver, payload_type)
148
+ begin
149
+ message_row = find_next_message(template, payload_type)
150
+ if message_row
151
+ message = Skynet::Message.new(message_row.attributes)
152
+ rows = write_fallback_message(message_row, message)
153
+
154
+ if rows < 1
171
155
  old_temp = temperature(payload_type)
172
156
  set_temperature(payload_type, template_to_conditions(template), queue_id)
173
- debug "COLLISION PTYPE #{payload_type} OLDTEMP: #{old_temp} NEWTEMP: #{temperature(payload_type)}"
157
+ debug "MISSCOLLISION PTYPE #{payload_type} OLDTEMP: #{old_temp} NEWTEMP: #{temperature(payload_type)}"
174
158
  else
175
- raise e
159
+ break
160
+ end
161
+ else # no messages on queue with this temp
162
+ old_temp = temperature(payload_type)
163
+ if old_temp > 1
164
+ set_temperature(payload_type, template_to_conditions(template), queue_id)
176
165
  end
166
+ debug "MISS PTYPE #{payload_type} OLDTEMP: #{old_temp} NEWTEMP: #{temperature(payload_type)}"
177
167
  end
178
- if Time.now.to_f > start.to_f + timeout
179
- debug "MISSTIMEOUT PTYPE #{payload_type} #{temperature(payload_type)}"
180
- raise Skynet::RequestExpiredError.new
181
- else
182
- sleepy = rand(timeout * 0.5 )
183
- debug "EMPTY QUEUE #{temperature(payload_type)} SLEEPING: #{timeout} / #{sleepy}"
184
- sleep sleepy
168
+ rescue Skynet::Message::BadMessage => e
169
+ message_row.destroy
170
+ next
171
+ rescue ActiveRecord::StatementInvalid => e
172
+ if e.message =~ /Deadlock/
173
+ old_temp = temperature(payload_type)
174
+ set_temperature(payload_type, template_to_conditions(template), queue_id)
175
+ debug "COLLISION PTYPE #{payload_type} OLDTEMP: #{old_temp} NEWTEMP: #{temperature(payload_type)}"
176
+ else
177
+ raise e
185
178
  end
186
179
  end
187
-
188
- return message
189
- end
190
-
191
- def write_message(message,timeout=nil)
192
- timeout ||= message.expiry
193
- SkynetMessageQueue.create(message_to_hash(message, timeout))
194
- end
195
-
196
- def write_result(message,result=[],timeout=nil)
197
- timeout ||= message.expiry
198
- result_message = message.result_message(result)
199
- result_message.expire_time = nil
200
- update_message_with_result(result_message,timeout)
201
- end
202
-
203
- def update_message_with_result(message,timeout=nil)
204
- timeout ||= message.expiry
205
- timeout_sql = (timeout ? ", timeout = #{timeout}, expire_time = #{Time.now.to_f + timeout}" : '')
206
- rows = 0
207
- raw_payload_sql = " raw_payload = "
208
- raw_payload_sql << (message.raw_payload ? "'#{::Mysql.escape_string(message.raw_payload)}'" : 'NULL')
209
- update_sql = %{
210
- update #{message_queue_table}
211
- set tasktype = "#{message.tasktype}",
212
- #{raw_payload_sql},
213
- payload_type = "#{message.payload_type}",
214
- updated_on = "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}",
215
- tran_id = NULL
216
- #{timeout_sql}
217
- where task_id = #{message.task_id}
218
- }
219
- rows = update(update_sql)
220
-
221
- raise Skynet::RequestExpiredError.new() if rows == 0
222
- end
223
-
224
- def take_result(job_id,timeout=1)
225
- start = Time.now
226
- result = nil
227
- sleep_time = 10
228
- if timeout < 1
229
- sleep_time = 1
230
- elsif timeout > 10
231
- sleep_time = 10
232
- else
233
- sleep_time = timeout * 0.25
180
+ if Time.now.to_f > start.to_f + timeout
181
+ debug "MISSTIMEOUT PTYPE #{payload_type} #{temperature(payload_type)}"
182
+ raise Skynet::RequestExpiredError.new
183
+ else
184
+ sleepy = rand(timeout * 0.5 )
185
+ debug "EMPTY QUEUE #{temperature(payload_type)} SLEEPING: #{timeout} / #{sleepy}"
186
+ sleep sleepy
234
187
  end
235
- message_row = nil
236
-
237
- loop do
238
- # message_row = take(Skynet::Message.result_template(job_id), start, timeout,sleep_time)
239
- conditions = template_to_conditions(Skynet::Message.result_template(job_id))
240
- # sleep_time ||= timeout
241
-
242
- message_row = SkynetMessageQueue.find(:first,:conditions => conditions)
243
-
244
- break if message_row
188
+ end
245
189
 
246
- if Time.now.to_f > start.to_f + timeout
247
- raise Skynet::RequestExpiredError.new
248
- else
249
- sleepy = rand(sleep_time)
250
- # error "RESULT EMPTY SLEEPING: #{sleepy}"
251
- sleep sleepy
252
- next
253
- end
254
- next
255
- end
190
+ return message
191
+ end
192
+
193
+ def write_message(message,timeout=nil)
194
+ timeout ||= message.expiry
195
+ SkynetMessageQueue.create(message_to_hash(message, timeout))
196
+ end
197
+
198
+ def write_result(message,result=[],timeout=nil)
199
+ timeout ||= message.expiry
200
+ result_message = message.result_message(result)
201
+ result_message.expire_time = nil
202
+ update_message_with_result(result_message,timeout)
203
+ end
204
+
205
+ def update_message_with_result(message,timeout=nil)
206
+ timeout ||= message.expiry
207
+ timeout_sql = (timeout ? ", timeout = #{timeout}, expire_time = #{Time.now.to_f + timeout}" : '')
208
+ rows = 0
209
+ raw_payload_sql = " raw_payload = "
210
+ raw_payload_sql << (message.raw_payload ? "'#{::Mysql.escape_string(message.raw_payload)}'" : 'NULL')
211
+ update_sql = %{
212
+ update #{message_queue_table}
213
+ set tasktype = "#{message.tasktype}",
214
+ #{raw_payload_sql},
215
+ payload_type = "#{message.payload_type}",
216
+ updated_on = "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}",
217
+ tran_id = NULL
218
+ #{timeout_sql}
219
+ where task_id = #{message.task_id}
220
+ }
221
+ rows = update(update_sql)
222
+
223
+ raise Skynet::RequestExpiredError.new() if rows == 0
224
+ end
256
225
 
257
- result = Skynet::Message.new(message_row.clone.attributes)
258
- message_row.destroy
259
- return result if result
260
- end
261
-
262
- def list_tasks(iteration=nil)
263
- conditions = template_to_conditions(Skynet::Message.outstanding_tasks_template(iteration))
264
- SkynetMessageQueue.find(:all,:conditions => conditions)
226
+ def take_result(job_id,timeout=1)
227
+ start = Time.now
228
+ result = nil
229
+ sleep_time = 10
230
+ if timeout < 1
231
+ sleep_time = 1
232
+ elsif timeout > 10
233
+ sleep_time = 10
234
+ else
235
+ sleep_time = timeout * 0.25
265
236
  end
237
+ message_row = nil
266
238
 
267
- def list_results
268
- conditions = template_to_conditions(Skynet::Message.outstanding_results_template)
269
- SkynetMessageQueue.find(:all,:conditions => conditions)
270
- end
239
+ loop do
240
+ # message_row = take(Skynet::Message.result_template(job_id), start, timeout,sleep_time)
241
+ conditions = template_to_conditions(Skynet::Message.result_template(job_id))
242
+ # sleep_time ||= timeout
271
243
 
272
- def write_error(message,error='',timeout=nil)
273
- message.expire_time = nil
274
- update_message_with_result(message.error_message(error),timeout)
275
- end
276
-
277
- def write_worker_status(task, timeout=nil)
278
- message = Skynet::WorkerStatusMessage.new(task)
279
- update_hash = message_to_hash(message, timeout, Skynet::WorkerStatusMessage.fields)
280
- update_hash.each do |k,v|
281
- if not v
282
- update_hash[k] = "NULL"
283
- elsif v.kind_of?(String) or v.kind_of?(Symbol)
284
- update_hash[k] = "'#{v}'"
285
- end
286
- end
244
+ message_row = SkynetMessageQueue.find(:first,:conditions => conditions)
245
+
246
+ break if message_row
287
247
 
288
- update_sql = "UPDATE skynet_worker_queues SET #{update_hash.collect{|k,v| "#{k}=#{v}"}.join(',')} WHERE worker_id=#{message.worker_id}"
289
- rows = update(update_sql)
290
- if rows == 0
291
- begin
292
- insert_sql = "INSERT INTO skynet_worker_queues (#{update_hash.keys.join(',')}) VALUES (#{update_hash.values.join(',')})"
293
- rows = update(insert_sql)
294
- rescue ActiveRecord::StatementInvalid => e
295
- if e.message =~ /Duplicate/
296
- error "DUPLICATE WORKER #{e.message} #{e.backtrace.join("\n")}"
297
- else
298
- raise e
299
- end
300
- end
301
- end
302
- return rows
303
- end
304
-
305
- def take_worker_status(task, timeout=nil)
306
- conditions = template_to_conditions(Skynet::WorkerStatusMessage.worker_status_template(task), Skynet::WorkerStatusMessage.fields)
307
- worker_status = nil
308
- SkynetWorkerQueue.transaction do
309
- worker_row = SkynetWorkerQueue.find(:first, :conditions => conditions)
310
- return unless worker_row
311
- worker_status = Skynet::WorkerStatusMessage.new(worker_row.clone.attributes)
312
- worker_row.destroy
313
- end
314
- worker_status
315
- end
316
-
317
- def read_all_worker_statuses(hostname=nil,process_id=nil)
318
- ws = Skynet::WorkerStatusMessage.all_workers_template(hostname)
319
- ws[4] = process_id if process_id
320
- conditions = template_to_conditions(ws,Skynet::WorkerStatusMessage.fields)
321
- rows = SkynetWorkerQueue.find(:all, :conditions => conditions)
322
- workers = rows.collect{ |w| Skynet::WorkerStatusMessage.new(w.attributes) }#.sort{ |a,b| a.process_id <=> b.process_id }
323
- end
248
+ if Time.now.to_f > start.to_f + timeout
249
+ raise Skynet::RequestExpiredError.new
250
+ else
251
+ sleepy = rand(sleep_time)
252
+ # error "RESULT EMPTY SLEEPING: #{sleepy}"
253
+ sleep sleepy
254
+ next
255
+ end
256
+ next
257
+ end
324
258
 
259
+ result = Skynet::Message.new(message_row.clone.attributes)
260
+ message_row.destroy
261
+ return result if result
262
+ end
263
+
264
+ def list_tasks(iteration=nil)
265
+ conditions = template_to_conditions(Skynet::Message.outstanding_tasks_template(iteration))
266
+ SkynetMessageQueue.find(:all,:conditions => conditions)
267
+ end
268
+
269
+ def list_results
270
+ conditions = template_to_conditions(Skynet::Message.outstanding_results_template)
271
+ SkynetMessageQueue.find(:all,:conditions => conditions)
272
+ end
325
273
 
326
- def clear_worker_status(hostname=nil)
327
- sql = "delete from skynet_worker_queues "
328
- if hostname
329
- sql << "where hostname = '#{hostname}'"
330
- end
331
- SkynetWorkerQueue.connection.execute(sql)
332
- end
274
+ def write_error(message,error='',timeout=nil)
275
+ message.expire_time = nil
276
+ update_message_with_result(message.error_message(error),timeout)
277
+ end
333
278
 
334
- def version_active?(curver=nil, queue_id=0)
335
- return true unless curver
336
- message_row = find_next_message(Skynet::Message.next_task_template(curver, nil, queue_id), :any, 1)
337
- if message_row or curver.to_i == get_worker_version.to_i
338
- true
339
- else
340
- false
341
- end
279
+ def version_active?(curver=nil, queue_id=0)
280
+ return true unless curver
281
+ message_row = find_next_message(Skynet::Message.next_task_template(curver, nil, queue_id), :any, 1)
282
+ if message_row or curver.to_i == get_worker_version.to_i
283
+ true
284
+ else
285
+ false
342
286
  end
287
+ end
343
288
 
344
- def set_worker_version(ver=nil)
345
- ver ||= 1
346
- SkynetMessageQueue.connection.insert("replace #{message_queue_table} (tran_id, task_id, tasktype, version) values (0, 0, 'version',#{ver})")
347
- ver
348
- end
289
+ def set_worker_version(ver=nil)
290
+ ver ||= 1
291
+ SkynetMessageQueue.connection.insert("replace #{message_queue_table} (tran_id, task_id, tasktype, version) values (0, 0, 'version',#{ver})")
292
+ ver
293
+ end
349
294
 
350
- def get_worker_version
351
- ver = SkynetMessageQueue.connection.select_value("select version from #{message_queue_table} where tran_id = 0 and tasktype = 'version'")
352
- if not ver
353
- begin
354
- SkynetMessageQueue.connection.insert("insert into #{message_queue_table} (tran_id, task_id, tasktype, version) values (0, 0, 'version', 1)")
355
- rescue ActiveRecord::StatementInvalid => e
356
- if e.message =~ /Duplicate/
357
- return get_worker_version
358
- else
359
- raise e
360
- end
295
+ def get_worker_version
296
+ ver = SkynetMessageQueue.connection.select_value("select version from #{message_queue_table} where tran_id = 0 and tasktype = 'version'")
297
+ if not ver
298
+ begin
299
+ SkynetMessageQueue.connection.insert("insert into #{message_queue_table} (tran_id, task_id, tasktype, version) values (0, 0, 'version', 1)")
300
+ rescue ActiveRecord::StatementInvalid => e
301
+ if e.message =~ /Duplicate/
302
+ return get_worker_version
303
+ else
304
+ raise e
361
305
  end
362
- ver = 1
363
306
  end
364
- ver.to_i
307
+ ver = 1
365
308
  end
366
-
367
- def clear_outstanding_tasks
368
- SkynetMessageQueue.connection.execute("delete from #{message_queue_table} where tasktype = 'task'")
369
- end
309
+ ver.to_i
310
+ end
311
+
312
+ def clear_outstanding_tasks
313
+ SkynetMessageQueue.connection.execute("delete from #{message_queue_table} where tasktype = 'task'")
314
+ end
370
315
 
371
- def delete_expired_messages
372
- SkynetMessageQueue.connection.execute("delete from #{message_queue_table} where (expire_time BETWEEN 1 AND '#{Time.now.to_f}') and iteration = -1")
373
- end
316
+ def delete_expired_messages
317
+ SkynetMessageQueue.connection.execute("delete from #{message_queue_table} where (tasktype='result' and expire_time < #{Time.now.to_i}) OR (expire_time BETWEEN 1 AND '#{Time.now.to_i - 7200}' and iteration = -1) OR (expire_time BETWEEN 1 AND '#{Time.now.to_i - 36000}')")
318
+ end
374
319
 
375
320
  # select hostname, iteration, count(id) as number_of_workers, count(iteration) as iteration, sum(processed) as processed, max(started_at) as most_recent_task_time from skynet_worker_queues where tasksubtype = 'worker' group by hostname, iteration;
376
321
  #
@@ -379,248 +324,186 @@ class Skynet
379
324
  #
380
325
  # from skynet_worker_queues where tasksubtype = 'worker' group by hostname;
381
326
 
382
- def stats
383
- stats = {
384
- :servers => {},
385
- :results => 0,
386
- :taken_tasks => 0,
387
- :untaken_tasks => 0,
388
- :taken_master_tasks => 0,
389
- :taken_task_tasks => 0,
390
- :untaken_master_tasks => 0,
391
- :untaken_task_tasks => 0,
392
- :failed_tasks => 0,
393
- :processed => 0,
394
- :number_of_workers => 0,
395
- :active_workers => 0,
396
- :idle_workers => 0,
397
- :hosts => 0,
398
- :masters => 0,
399
- :taskworkers => 0,
400
- :time => Time.now.to_f
401
- }
402
-
403
- stat_rows = SkynetWorkerQueue.connection.select_all(%{
404
- SELECT tasktype, payload_type, iteration, count(id) as number_of_tasks
405
- FROM #{message_queue_table}
406
- GROUP BY tasktype, payload_type, iteration
407
- })
408
- # pp stat_rows
409
- stat_rows.each do |row|
410
- if row["tasktype"] == "result" or row["payload_type"] == "result"
411
- stats[:results] += row["number_of_tasks"].to_i
412
- elsif row["tasktype"] == "task"
413
- type_of_tasks = nil
414
- if row["payload_type"] == "master"
415
- type_of_tasks = :master_tasks
416
- elsif row["payload_type"] == "task"
417
- type_of_tasks = :task_tasks
418
- end
419
- if row["iteration"].to_i > 0
420
- stats["taken_#{type_of_tasks}".to_sym] += row["number_of_tasks"].to_i
421
- stats[:taken_tasks] += row["number_of_tasks"].to_i
422
- elsif row["iteration"].to_i == 0
423
- stats["untaken_#{type_of_tasks}".to_sym] += row["number_of_tasks"].to_i
424
- stats[:untaken_tasks] += row["number_of_tasks"].to_i
425
- else
426
- stats[:failed_tasks] += row["number_of_tasks"].to_i
427
- end
428
- end
429
- end
430
-
431
- servers = {}
432
-
433
- stat_sql = <<-SQL
434
- select hostname, map_or_reduce, count(id) number_of_workers, sum(processed) as processed,
435
- max(started_at) as most_recent_task_time, iteration
436
- FROM skynet_worker_queues
437
- WHERE skynet_worker_queues.tasksubtype = 'worker'
438
- SQL
439
-
440
- stat_rows = SkynetWorkerQueue.connection.select_all("#{stat_sql} GROUP BY hostname, map_or_reduce").each do |row|
441
- servers[row["hostname"]] ||= {
442
- :processed => 0,
443
- :hostname => row["hostname"],
444
- :number_of_workers => 0,
445
- :active_workers => 0,
446
- :idle_workers => 0,
447
- }
448
-
449
- servers[row["hostname"]][:processed] += row["processed"].to_i
450
- servers[row["hostname"]][:number_of_workers] += row["number_of_workers"].to_i
451
- servers[row["hostname"]][:active_workers] += 0
452
- servers[row["hostname"]][:idle_workers] += row["number_of_workers"].to_i
453
- stats[:processed] += row["processed"].to_i
454
- stats[:number_of_workers] += row["number_of_workers"].to_i
455
- stats[:idle_workers] += row["number_of_workers"].to_i
456
- end
457
-
458
- SkynetWorkerQueue.connection.select_all(%{
459
- #{stat_sql} AND skynet_worker_queues.iteration IS NOT NULL
460
- GROUP BY hostname, map_or_reduce
461
- }).each do |row|
462
- map_or_reduce = nil
463
- if row["map_or_reduce"] == "master"
464
- map_or_reduce = :masters
327
+ def stats
328
+ stats = {
329
+ :servers => {},
330
+ :results => 0,
331
+ :taken_tasks => 0,
332
+ :untaken_tasks => 0,
333
+ :taken_master_tasks => 0,
334
+ :taken_task_tasks => 0,
335
+ :untaken_master_tasks => 0,
336
+ :untaken_task_tasks => 0,
337
+ :failed_tasks => 0,
338
+ :untaken_future_tasks => 0,
339
+ :time => Time.now.to_f,
340
+ }
341
+
342
+ stats[:untaken_future_tasks] = SkynetWorkerQueue.connection.select_value(%{
343
+ SELECT count(id)
344
+ FROM #{message_queue_table}
345
+ WHERE expire_time > #{Time.now.to_i} and tasktype = 'task' and payload_type = 'master'
346
+ })
347
+
348
+ stat_rows = SkynetWorkerQueue.connection.select_all(%{
349
+ SELECT tasktype, payload_type, iteration, count(id) as number_of_tasks, expire_time
350
+ FROM #{message_queue_table}
351
+ WHERE expire_time <= #{Time.now.to_i}
352
+ GROUP BY tasktype, payload_type, iteration
353
+ })
354
+ stat_rows.each do |row|
355
+ if row["tasktype"] == "result" or row["payload_type"] == "result"
356
+ stats[:results] += row["number_of_tasks"].to_i
357
+ elsif row["tasktype"] == "task"
358
+ type_of_tasks = nil
359
+ if row["payload_type"] == "master"
360
+ type_of_tasks = :master_tasks
361
+ elsif row["payload_type"] == "task"
362
+ type_of_tasks = :task_tasks
363
+ end
364
+ if row["iteration"].to_i == 0
365
+ stats["untaken_#{type_of_tasks}".to_sym] += row["number_of_tasks"].to_i
366
+ stats[:untaken_tasks] += row["number_of_tasks"].to_i
367
+ elsif row["expire_time"].to_i < Time.now.to_i
368
+ stats[:failed_tasks] += row["number_of_tasks"].to_i
465
369
  else
466
- map_or_reduce = :taskworkers
370
+ stats["taken_#{type_of_tasks}".to_sym] += row["number_of_tasks"].to_i
371
+ stats[:taken_tasks] += row["number_of_tasks"].to_i
467
372
  end
468
- servers[row["hostname"]][:active_workers] += row["number_of_workers"].to_i
469
- servers[row["hostname"]][:idle_workers] -= row["number_of_workers"].to_i
470
- servers[row["hostname"]][map_or_reduce] ||= 0
471
- servers[row["hostname"]][map_or_reduce] += row["number_of_workers"].to_i
472
- stats[map_or_reduce] += row["number_of_workers"].to_i
473
- stats[:active_workers] += row["number_of_workers"].to_i
474
- stats[:idle_workers] -= row["number_of_workers"].to_i
475
- end
476
-
477
- stats[:servers] = servers
478
- stats[:hosts] = servers.keys.size
479
- stats[:time] = Time.now.to_f - stats[:time]
480
- stats
481
- end
482
-
483
- def processed(sleepy=5,tim=10)
484
- last_time = Time.now
485
- last_count = Skynet::MessageQueue.new.stats[:processed]
486
- tim.times do
487
- new_count = Skynet::MessageQueue.new.stats[:processed]
488
- new_time = Time.now
489
- puts "Processed #{new_count - last_count} in #{new_time - last_time}"
490
- last_time = new_time
491
- last_count = new_count
492
- sleep sleepy
493
373
  end
494
374
  end
495
-
496
- private
497
375
 
498
- def update(sql)
499
- rows = 0
500
- 3.times do
501
- begin
502
- SkynetMessageQueue.transaction do
503
- rows = SkynetMessageQueue.connection.update(sql)
504
- end
505
- return rows
506
- rescue ActiveRecord::StatementInvalid => e
507
- if e.message =~ /Deadlock/ or e.message =~ /Transaction/
508
- error "#{self.class} update had collision #{e.message}"
509
- sleep 0.2
510
- next
511
- else
512
- raise e
513
- end
376
+ stats[:time] = Time.now.to_f - stats[:time]
377
+ stats
378
+ end
379
+
380
+ private
381
+
382
+ def update(sql)
383
+ rows = 0
384
+ 3.times do
385
+ begin
386
+ SkynetMessageQueue.transaction do
387
+ rows = SkynetMessageQueue.connection.update(sql)
388
+ end
389
+ return rows
390
+ rescue ActiveRecord::StatementInvalid => e
391
+ if e.message =~ /Deadlock/ or e.message =~ /Transaction/
392
+ error "#{self.class} update had collision #{e.message}"
393
+ sleep 0.2
394
+ next
395
+ else
396
+ raise e
514
397
  end
515
398
  end
516
- return rows
517
399
  end
400
+ return rows
401
+ end
402
+
403
+ Skynet::CONFIG[:MYSQL_TEMPERATURE_CHANGE_SLEEP] ||= 40
518
404
 
519
- Skynet::CONFIG[:MYSQL_TEMPERATURE_CHANGE_SLEEP] ||= 40
520
-
521
- def find_next_message(template, payload_type, temperature=nil)
522
- conditions = template_to_conditions(template)
523
- temperature ||= temperature(payload_type)
524
- temperature_sql = (temperature > 1 ? " AND id % #{temperature.ceil} = #{rand(temperature).to_i} " : '')
525
-
526
- ### Mqke sure we get the old ones. If we order by on ever select its VERY expensive.
527
- order_by = (payload_type != :master and rand(100) < 5) ? "ORDER BY payload_type desc, created_on desc" : ''
528
-
529
- sql = <<-SQL
530
- SELECT *
531
- FROM #{message_queue_table}
532
- WHERE #{conditions} #{temperature_sql}
533
- #{order_by}
534
- LIMIT 1
535
- SQL
536
-
537
- SkynetMessageQueue.find_by_sql(sql).first
538
- end
405
+ def find_next_message(template, payload_type, temperature=nil)
406
+ conditions = template_to_conditions(template)
407
+ temperature ||= temperature(payload_type)
408
+ temperature_sql = (temperature > 1 ? " AND id % #{temperature.ceil} = #{rand(temperature).to_i} " : '')
539
409
 
540
- # Skynet::CONFIG[:temperature_growth_rate] ||= 2
541
- # Skynet::CONFIG[:temperature_backoff_rate] ||= 0.75
410
+ ### Mqke sure we get the old ones. If we order by on ever select its VERY expensive.
411
+ order_by = (payload_type != :master and rand(100) < 5) ? "ORDER BY payload_type desc, created_on desc" : ''
542
412
 
543
- # TUNEABLE_SETTINGS = [:temp_pow, :temp_interval, :sleep_time]
544
- #
545
- # def write_score(new_values,new_result,score)
546
- # values ||= {}
547
- # set = new_values.keys.sort.collect{|k|[k,new_values[k]]}.join(",")
548
- # if not values[set]
549
- # values[set] ||= {}
550
- # values[set][:results] ||= []
551
- # values[set][:scores] ||= []
552
- # values[set][:settings] ||= {}
553
- # values[set][:total_score] = 0
554
- # TUNEABLE_SETTINGS.each do |setting|
555
- # values[set][:settings][setting] = []
556
- # end
557
- # end
558
- # TUNEABLE_SETTINGS.each do |setting, value|
559
- # values[set][:settings][setting] << value
560
- # end
561
- # values[set][:results] << new_result
562
- # values[set][:scores] << score + values[set][:total_score]
563
- # values[set][:total_score] += score
564
- # end
565
-
566
- @@temperature ||= {}
567
- @@temperature[:task] ||= 1
568
- @@temperature[:master] ||= 1
569
- @@temperature[:any] ||= 1
413
+ sql = <<-SQL
414
+ SELECT *
415
+ FROM #{message_queue_table}
416
+ WHERE #{conditions} #{temperature_sql}
417
+ #{order_by}
418
+ LIMIT 1
419
+ SQL
420
+
421
+ SkynetMessageQueue.find_by_sql(sql).first
422
+ end
570
423
 
571
- def temperature(payload_type)
572
- payload_type ||= :any
573
- payload_type = payload_type.to_sym
574
- @@temperature[payload_type.to_sym]
575
- end
424
+ # Skynet::CONFIG[:temperature_growth_rate] ||= 2
425
+ # Skynet::CONFIG[:temperature_backoff_rate] ||= 0.75
426
+
427
+ # TUNEABLE_SETTINGS = [:temp_pow, :temp_interval, :sleep_time]
428
+ #
429
+ # def write_score(new_values,new_result,score)
430
+ # values ||= {}
431
+ # set = new_values.keys.sort.collect{|k|[k,new_values[k]]}.join(",")
432
+ # if not values[set]
433
+ # values[set] ||= {}
434
+ # values[set][:results] ||= []
435
+ # values[set][:scores] ||= []
436
+ # values[set][:settings] ||= {}
437
+ # values[set][:total_score] = 0
438
+ # TUNEABLE_SETTINGS.each do |setting|
439
+ # values[set][:settings][setting] = []
440
+ # end
441
+ # end
442
+ # TUNEABLE_SETTINGS.each do |setting, value|
443
+ # values[set][:settings][setting] << value
444
+ # end
445
+ # values[set][:results] << new_result
446
+ # values[set][:scores] << score + values[set][:total_score]
447
+ # values[set][:total_score] += score
448
+ # end
576
449
 
577
- Skynet::CONFIG[:MYSQL_QUEUE_TEMP_POW] ||= 0.6
578
-
579
- def set_temperature(payload_type, conditions, queue_id=0)
580
- payload_type ||= :any
581
- payload_type = payload_type.to_sym
582
-
583
- temp_q_conditions = "queue_id = #{queue_id} AND type = '#{payload_type}' AND updated_on < '#{(Time.now - 5).strftime('%Y-%m-%d %H:%M:%S')}'"
450
+ @@temperature ||= {}
451
+ @@temperature[:task] ||= 1
452
+ @@temperature[:master] ||= 1
453
+ @@temperature[:any] ||= 1
454
+
455
+ def temperature(payload_type)
456
+ payload_type ||= :any
457
+ payload_type = payload_type.to_sym
458
+ @@temperature[payload_type.to_sym]
459
+ end
460
+
461
+ Skynet::CONFIG[:MYSQL_QUEUE_TEMP_POW] ||= 0.6
462
+
463
+ def set_temperature(payload_type, conditions, queue_id=0)
464
+ payload_type ||= :any
465
+ payload_type = payload_type.to_sym
466
+
467
+ temp_q_conditions = "queue_id = #{queue_id} AND type = '#{payload_type}' AND updated_on < '#{(Time.now - 5).strftime('%Y-%m-%d %H:%M:%S')}'"
584
468
  # "POW(#{(rand(40) + 40) * 0.01})"
585
469
  # its almost like the temperature table needs to store the POW and adjust that to be adaptive. Like some % of the time it
586
470
  # uses the one in the table, and some % it tries a new one and scores it.
587
- begin
588
- temperature = SkynetMessageQueue.connection.select_value(%{select (
589
- CASE WHEN (@t:=FLOOR(
590
- POW(@c:=(SELECT count(*) FROM #{message_queue_table} WHERE #{conditions}
591
- ),#{Skynet::CONFIG[:MYSQL_QUEUE_TEMP_POW]}))) < 1 THEN 1 ELSE @t END) from skynet_queue_temperature WHERE #{temp_q_conditions}
592
- })
593
- if temperature
594
- rows = update("UPDATE skynet_queue_temperature SET temperature = #{temperature} WHERE #{temp_q_conditions}")
595
- @@temperature[payload_type.to_sym] = temperature.to_f
596
- else
597
- sleepy = rand Skynet::CONFIG[:MYSQL_TEMPERATURE_CHANGE_SLEEP]
598
- sleep sleepy
599
- @@temperature[payload_type.to_sym] = get_temperature(payload_type, queue_id)
600
- end
601
- rescue ActiveRecord::StatementInvalid => e
602
- if e.message =~ /away/
603
- ActiveRecord::Base.connection.reconnect!
604
- SkynetMessageQueue.connection.reconnect!
605
- end
471
+ begin
472
+ temperature = SkynetMessageQueue.connection.select_value(%{select (
473
+ CASE WHEN (@t:=FLOOR(
474
+ POW(@c:=(SELECT count(*) FROM #{message_queue_table} WHERE #{conditions}
475
+ ),#{Skynet::CONFIG[:MYSQL_QUEUE_TEMP_POW]}))) < 1 THEN 1 ELSE @t END) from skynet_queue_temperature WHERE #{temp_q_conditions}
476
+ })
477
+ if temperature
478
+ rows = update("UPDATE skynet_queue_temperature SET temperature = #{temperature} WHERE #{temp_q_conditions}")
479
+ @@temperature[payload_type.to_sym] = temperature.to_f
480
+ else
481
+ sleepy = rand Skynet::CONFIG[:MYSQL_TEMPERATURE_CHANGE_SLEEP]
482
+ sleep sleepy
483
+ @@temperature[payload_type.to_sym] = get_temperature(payload_type, queue_id)
606
484
  end
607
- # update("UPDATE skynet_queue_temperature SET type = '#{payload_type}', temperature = CASE WHEN @t:=FLOOR(SQRT(select count(*) from #{message_queue_table} WHERE #{conditions})) < 1 THEN 1 ELSE @t END")
608
- # tasks = SkynetMessageQueue.connection.select_value("select count(*) from #{message_queue_table} WHERE #{conditions}").to_i
609
- # sleep 4 if payload_type == :tasks and tasks < 100
610
- # @@temperature[payload_type.to_sym] = tasks ** 0.5
611
- # @@temperature[payload_type.to_sym] *= multiplier
612
- @@temperature[payload_type.to_sym] = 1 if @@temperature[payload_type.to_sym] < 1
613
- end
614
-
615
- def get_temperature(payload_type, queue_id=0)
616
- payload_type ||= :any
617
- payload_type = payload_type.to_sym
618
- value = SkynetMessageQueue.connection.select_value("select temperature from skynet_queue_temperature WHERE type = '#{payload_type}'").to_f
619
- if not value
620
- SkynetMessageQueue.connection.execute("insert into skynet_queue_temperature (queue_id,type,temperature) values (#{queue_id},'#{payload_type}',#{@@temperature[payload_type.to_sym]})")
485
+ rescue ActiveRecord::StatementInvalid => e
486
+ if e.message =~ /away/
487
+ ActiveRecord::Base.connection.reconnect!
488
+ SkynetMessageQueue.connection.reconnect!
621
489
  end
622
- value
623
490
  end
491
+ # update("UPDATE skynet_queue_temperature SET type = '#{payload_type}', temperature = CASE WHEN @t:=FLOOR(SQRT(select count(*) from #{message_queue_table} WHERE #{conditions})) < 1 THEN 1 ELSE @t END")
492
+ # tasks = SkynetMessageQueue.connection.select_value("select count(*) from #{message_queue_table} WHERE #{conditions}").to_i
493
+ # sleep 4 if payload_type == :tasks and tasks < 100
494
+ # @@temperature[payload_type.to_sym] = tasks ** 0.5
495
+ # @@temperature[payload_type.to_sym] *= multiplier
496
+ @@temperature[payload_type.to_sym] = 1 if @@temperature[payload_type.to_sym] < 1
497
+ end
498
+
499
+ def get_temperature(payload_type, queue_id=0)
500
+ payload_type ||= :any
501
+ payload_type = payload_type.to_sym
502
+ value = SkynetMessageQueue.connection.select_value("select temperature from skynet_queue_temperature WHERE type = '#{payload_type}'").to_f
503
+ if not value
504
+ SkynetMessageQueue.connection.execute("insert into skynet_queue_temperature (queue_id,type,temperature) values (#{queue_id},'#{payload_type}',#{@@temperature[payload_type.to_sym]})")
505
+ end
506
+ value
624
507
  end
625
508
  end
626
509
  end