skyrunner 0.0.13 → 0.1.0
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.
- 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
|