skyrunner 0.0.13 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/bin/skyrunner +10 -6
- data/lib/generators/sky_runner/install/templates/skyrunner.rake +1 -5
- data/lib/generators/sky_runner/install/templates/skyrunner.rb +5 -0
- data/lib/skyrunner/job.rb +2 -0
- data/lib/skyrunner/version.rb +1 -1
- data/lib/skyrunner.rb +69 -25
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6d11252dc57758004a10bba1e6d9321f07a6629
|
4
|
+
data.tar.gz: fe23c5593a322c8a39a90db60b8d0f6632768a19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b2dc81fcdd2416d16973511e929731556661c6b8e4b4b9c0ef578ed3c500b61ce744e42925caa08709b503915b5c37224cb82841e1bb94468ec5e52ee7f960e
|
7
|
+
data.tar.gz: b61a040c8e9c8d3a829a3e1a56b546d1fcc61fa699d2c27dc5b1d2f1eaa6c9415f834ff8b88b627731e956ae2926c6dc6cc57e0f4ee6ef767d0ebb3b5757ad67
|
data/README.md
CHANGED
@@ -31,7 +31,7 @@ To start a consumer
|
|
31
31
|
bundle exec rake skyrunner:consume
|
32
32
|
``
|
33
33
|
|
34
|
-
To gracefully shut down a consumer, send it SIGINT
|
34
|
+
To gracefully shut down a consumer, send it SIGINT. It will finish up processing the messages it has de-queued before terminating.
|
35
35
|
|
36
36
|
See `jobs/example_job.rb` for an example job. To run a job, just call `execute!` on the job, passing any named job arguments you want. The job class should implement the method `run`. This method will get passed the job arguments. For each task you want consumers to run, `run` should yield an array of two elements, the first being the name of the method on the job class to run for the task, and the second a Hash of method arguments.
|
37
37
|
|
data/bin/skyrunner
CHANGED
@@ -12,11 +12,7 @@ logger.level = Log4r::DEBUG
|
|
12
12
|
SkyRunner.logger = logger
|
13
13
|
|
14
14
|
trap("INT") do
|
15
|
-
SkyRunner.stop_consuming!
|
16
|
-
end
|
17
|
-
|
18
|
-
trap("TERM") do
|
19
|
-
SkyRunner.stop_consuming!
|
15
|
+
SkyRunner.stop_consuming!(true)
|
20
16
|
end
|
21
17
|
|
22
18
|
opts = Trollop::options do
|
@@ -29,6 +25,7 @@ opts = Trollop::options do
|
|
29
25
|
Valid commands:
|
30
26
|
|
31
27
|
consume - Starts consuming tasks.
|
28
|
+
test - Runs a test job.
|
32
29
|
init - Creates DynamoDB table and SQS queue for SkyRunner.
|
33
30
|
purge - Purges and re-creates DynamoDB table and SQS queue for SkyRunner. (Destructive!)
|
34
31
|
END
|
@@ -37,14 +34,16 @@ opts = Trollop::options do
|
|
37
34
|
opt :sqs_queue_name, "SQS queue use for tasks.", default: "skyrunner_tasks", type: :string
|
38
35
|
opt :namespace, "Namespace of jobs to consume.", default: "default", type: :string
|
39
36
|
opt :batch_size, "Number of tasks to consume per batch.", default: 10
|
37
|
+
opt :num_threads, "Number of consumer threads.", default: 10
|
40
38
|
end
|
41
39
|
|
42
40
|
SkyRunner.dynamo_db_table_name = opts[:dynamo_db_table_name]
|
43
41
|
SkyRunner.sqs_queue_name = opts[:sqs_queue_name]
|
44
42
|
SkyRunner.job_namespace = opts[:namespace]
|
45
43
|
SkyRunner.consumer_batch_size = opts[:batch_size].to_i
|
44
|
+
SkyRunner.num_threads = opts[:num_threads].to_i
|
46
45
|
|
47
|
-
COMMANDS = ["init", "purge", "consume"]
|
46
|
+
COMMANDS = ["init", "purge", "consume", "test"]
|
48
47
|
|
49
48
|
Trollop::die "Must specify command" unless COMMANDS.include?(ARGV[0])
|
50
49
|
|
@@ -57,4 +56,9 @@ when "purge"
|
|
57
56
|
SkyRunner.init!(purge: true)
|
58
57
|
when "consume"
|
59
58
|
SkyRunner.consume!
|
59
|
+
when "test"
|
60
|
+
$: << "."
|
61
|
+
require "#{File.dirname(__FILE__)}/../jobs/example_job"
|
62
|
+
ExampleJobModule::ExampleJob.new.execute!(number_of_tasks: 500)
|
63
|
+
SkyRunner.consume!
|
60
64
|
end
|
@@ -7,11 +7,7 @@ namespace :skyrunner do
|
|
7
7
|
desc "Starts consuming SkyRunner tasks."
|
8
8
|
task consume: :environment do
|
9
9
|
trap("INT") do
|
10
|
-
SkyRunner.stop_consuming!
|
11
|
-
end
|
12
|
-
|
13
|
-
trap("TERM") do
|
14
|
-
SkyRunner.stop_consuming!
|
10
|
+
SkyRunner.stop_consuming!(true)
|
15
11
|
end
|
16
12
|
|
17
13
|
SkyRunner.consume! do |exception|
|
@@ -16,4 +16,9 @@ SkyRunner.setup do |config|
|
|
16
16
|
# this should provide sufficient time for a consumer to process 10 tasks, for example. (default 90)
|
17
17
|
#
|
18
18
|
# config.visibility_timeout = 90
|
19
|
+
|
20
|
+
# Set the number of concurrent threads for the consumer process.
|
21
|
+
# (If greater than one, you obviously need to make sure your tasks are thread-safe.)
|
22
|
+
#
|
23
|
+
# config.num_threads = 10
|
19
24
|
end
|
data/lib/skyrunner/job.rb
CHANGED
@@ -67,6 +67,7 @@ module SkyRunner::Job
|
|
67
67
|
1.upto(5) do
|
68
68
|
flush.()
|
69
69
|
sleep 5 if pending_args.size > 0
|
70
|
+
break if pending_args.size == 0
|
70
71
|
end
|
71
72
|
end
|
72
73
|
end
|
@@ -74,6 +75,7 @@ module SkyRunner::Job
|
|
74
75
|
1.upto(5) do
|
75
76
|
flush.() if pending_args.size > 0
|
76
77
|
sleep 5 if pending_args.size > 0
|
78
|
+
break if pending_args.size == 0
|
77
79
|
end
|
78
80
|
|
79
81
|
handle_task_completed!
|
data/lib/skyrunner/version.rb
CHANGED
data/lib/skyrunner.rb
CHANGED
@@ -63,14 +63,55 @@ module SkyRunner
|
|
63
63
|
def self.consume!(&block)
|
64
64
|
queue = sqs_queue
|
65
65
|
table = dynamo_db_table
|
66
|
-
|
67
66
|
raise "Queue #{SkyRunner::sqs_queue_name} not found. Try running 'skyrunner init'" unless queue
|
68
67
|
raise "DynamoDB table #{SkyRunner::dynamo_db_table_name} not found. Try running 'skyrunner init'" unless table && table.exists?
|
69
68
|
|
69
|
+
local_queue = Queue.new
|
70
|
+
error_queue = Queue.new
|
71
|
+
|
72
|
+
threads = []
|
73
|
+
|
74
|
+
1.upto(SkyRunner::num_threads) do
|
75
|
+
threads << Thread.new do
|
76
|
+
sqs = AWS::SQS.new
|
77
|
+
|
78
|
+
loop do
|
79
|
+
break if SkyRunner::stop_consuming?
|
80
|
+
sleep 1 unless local_queue.size > 0
|
81
|
+
|
82
|
+
klass, job_id, task_args, message = local_queue.pop
|
83
|
+
|
84
|
+
SkyRunner::log :info, "Run Task: #{task_args} Job: #{job_id} Message: #{message.id}"
|
85
|
+
|
86
|
+
job = klass.new
|
87
|
+
job.skyrunner_job_id = job_id
|
88
|
+
|
89
|
+
begin
|
90
|
+
job.consume!(task_args)
|
91
|
+
message.delete
|
92
|
+
rescue Exception => e
|
93
|
+
error_queue.push(e)
|
94
|
+
SkyRunner::log :error, "Task Failed: #{task_args} Job: #{job_id} #{e.message} #{e.backtrace.join("\n")}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
70
100
|
log :info, "Consumer started."
|
71
101
|
|
72
102
|
loop do
|
73
|
-
|
103
|
+
if error_queue.size > 0
|
104
|
+
SkyRunner::stop_consuming!
|
105
|
+
|
106
|
+
while error_queue.size > 0
|
107
|
+
error = error_queue.pop
|
108
|
+
yield error if block_given?
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
return true if stop_consuming?
|
113
|
+
|
114
|
+
sleep 1 while local_queue.size >= SkyRunner.num_threads
|
74
115
|
|
75
116
|
received_messages = []
|
76
117
|
|
@@ -80,37 +121,19 @@ module SkyRunner
|
|
80
121
|
|
81
122
|
next unless received_messages.size > 0
|
82
123
|
|
83
|
-
failed = false
|
84
|
-
|
85
124
|
table.batch_get(:all, received_messages.map { |m| m[1]["job_id"] }.uniq, consistent_read: true) do |record|
|
86
125
|
received_messages.select { |m| m[1]["job_id"] == record["job_id"] }.each_with_index do |received_message|
|
87
126
|
message = received_message[1]
|
88
127
|
job_id = message["job_id"]
|
89
128
|
|
90
|
-
if record["namespace"] == SkyRunner.job_namespace && record["failed"] == 0 &&
|
129
|
+
if record["namespace"] == SkyRunner.job_namespace && record["failed"] == 0 && error_queue.size == 0
|
91
130
|
start_time = Time.now
|
92
131
|
|
93
132
|
begin
|
94
133
|
klass = Kernel.const_get(record["class"])
|
95
|
-
|
96
134
|
task_args = message["task_args"]
|
97
|
-
|
98
|
-
|
99
|
-
job = klass.new
|
100
|
-
job.skyrunner_job_id = job_id
|
101
|
-
|
102
|
-
begin
|
103
|
-
job.consume!(task_args)
|
104
|
-
received_message[0].delete
|
105
|
-
|
106
|
-
yield false if block_given?
|
107
|
-
rescue Exception => e
|
108
|
-
failed = true
|
109
|
-
log :error, "Task Failed: #{task_args} Job: #{job_id} #{e.message} #{e.backtrace.join("\n")}"
|
110
|
-
yield e if block_given?
|
111
|
-
end
|
135
|
+
local_queue.push([klass, job_id, task_args, received_message[0]])
|
112
136
|
rescue NameError => e
|
113
|
-
failed = true
|
114
137
|
log :error, "Task Failed: No such class #{record["class"]} #{e.message}"
|
115
138
|
yield e if block_given?
|
116
139
|
end
|
@@ -118,6 +141,10 @@ module SkyRunner
|
|
118
141
|
end
|
119
142
|
end
|
120
143
|
end
|
144
|
+
|
145
|
+
threads.each { |t| t.join }
|
146
|
+
|
147
|
+
true
|
121
148
|
end
|
122
149
|
|
123
150
|
def self.dynamo_db_table
|
@@ -165,10 +192,27 @@ module SkyRunner
|
|
165
192
|
mattr_accessor :logger
|
166
193
|
@@logger = Log4r::Logger.new("skyrunner")
|
167
194
|
|
168
|
-
mattr_accessor :
|
195
|
+
mattr_accessor :num_threads
|
196
|
+
@@num_threads = 10
|
197
|
+
|
198
|
+
mattr_accessor :stop_consuming_flag
|
199
|
+
|
200
|
+
@@stop_consuming_mutex = Mutex.new
|
201
|
+
|
202
|
+
def self.stop_consuming?
|
203
|
+
@@stop_consuming_mutex.synchronize do
|
204
|
+
SkyRunner::stop_consuming_flag
|
205
|
+
end
|
206
|
+
end
|
169
207
|
|
170
|
-
def self.stop_consuming!
|
171
|
-
|
208
|
+
def self.stop_consuming!(its_a_trap=false)
|
209
|
+
if its_a_trap
|
210
|
+
SkyRunner::stop_consuming_flag = true
|
211
|
+
else
|
212
|
+
@@stop_consuming_mutex.synchronize do
|
213
|
+
SkyRunner::stop_consuming_flag = true
|
214
|
+
end
|
215
|
+
end
|
172
216
|
end
|
173
217
|
|
174
218
|
private
|