sqsrun 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,232 +1,5 @@
1
- require 'monitor'
2
-
3
- module SQSRun
4
-
5
-
6
- class Worker
7
- def initialize(conf)
8
- require 'right_aws'
9
- @key_id = conf[:key_id]
10
- @secret_key = conf[:secret_key]
11
- @queue_name = conf[:queue]
12
- @visibility_timeout = conf[:timeout]
13
- @extend_timeout = conf[:extend_timeout]
14
- @kill_timeout = conf[:kill_timeout]
15
- @interval = conf[:interval]
16
- @finished = false
17
-
18
- @extender = VisibilityExtender.new(@visibility_timeout, @extend_timeout)
19
- @sqs = RightAws::SqsGen2.new(@key_id, @secret_key)
20
- @queue = @sqs.queue(@queue_name)
21
-
22
- @mutex = Mutex.new
23
- @cond = ConditionVariable.new
24
- end
25
-
26
- def run(run_proc)
27
- @run_proc = run_proc
28
- @extender.start
29
- until @finished
30
- msg = @queue.receive(@visibility_timeout)
31
- if msg
32
- process(msg)
33
- else
34
- cond_wait(@interval)
35
- end
36
- end
37
- end
38
-
39
- def shutdown
40
- @finished = true
41
- @extender.shutdown
42
- receive!
43
- end
44
-
45
- def receive!
46
- @mutex.synchronize {
47
- @cond.broadcast
48
- }
49
- end
50
-
51
- def finished?
52
- @finished
53
- end
54
-
55
- private
56
- if ConditionVariable.new.method(:wait).arity == 1
57
- require 'timeout'
58
- def cond_wait(sec)
59
- @mutex.synchronize {
60
- Timeout.timeout(sec) {
61
- @cond.wait(@mutex)
62
- }
63
- }
64
- rescue Timeout::Error
65
- end
66
- else
67
- def cond_wait(sec)
68
- @mutex.synchronize {
69
- @cond.wait(@mutex, sec)
70
- }
71
- end
72
- end
73
-
74
- def process(msg)
75
- puts "started id=#{msg.id}"
76
- thread = Thread.new(msg.to_s, &@run_proc.method(:call))
77
-
78
- @extender.set_message(msg)
79
-
80
- success = false
81
- begin
82
- joined = thread.join(@kill_timeout)
83
- if joined
84
- thread.value
85
- success = true
86
- puts "finished id=#{msg.id}"
87
- else
88
- thread.kill
89
- puts "killed id=#{msg.id}"
90
- end
91
- rescue
92
- puts "failed id=#{msg.id}: #{$!}"
93
- $!.backtrace.each {|bt|
94
- puts " #{bt}"
95
- }
96
- end
97
-
98
- @extender.reset_message
99
-
100
- if success
101
- msg.delete
102
- else
103
- msg.visibility = 0
104
- end
105
- end
106
-
107
- class VisibilityExtender
108
- include MonitorMixin
109
-
110
- def initialize(visibility_timeout, extend_timeout)
111
- super()
112
- @visibility_timeout = visibility_timeout
113
- @extend_timeout = extend_timeout
114
- @extend_time = nil
115
- @message = nil
116
- @finished = false
117
- end
118
-
119
- def start
120
- @thread = Thread.new(&method(:run))
121
- end
122
-
123
- def join
124
- @thread.join
125
- end
126
-
127
- def set_message(msg)
128
- synchronize do
129
- @extend_time = Time.now.to_i + @extend_timeout
130
- @message = msg
131
- end
132
- end
133
-
134
- def reset_message
135
- synchronize do
136
- @message = nil
137
- end
138
- end
139
-
140
- def shutdown
141
- @finished = true
142
- end
143
-
144
- private
145
- def run
146
- until @finished
147
- sleep 1
148
- synchronize do
149
- try_extend(@message) if @message
150
- end
151
- end
152
- end
153
-
154
- def try_extend(msg)
155
- now = Time.now.to_i
156
- if now > @extend_time
157
- ntime = msg.visibility + @visibility_timeout
158
- puts "extending timeout=#{ntime} id=#{msg.id}"
159
- msg.visibility = ntime
160
- @extend_time = now + @extend_timeout
161
- end
162
- end
163
- end
164
- end
165
-
166
-
167
- class ExecRunner
168
- def initialize(cmd)
169
- @cmd = cmd + ' ' + ARGV.map {|a| Shellwords.escape(a) }.join(' ')
170
- @iobuf = ''
171
- end
172
-
173
- def call(message)
174
- IO.popen(@cmd, "r+") {|io|
175
- io.write(message) rescue nil
176
- io.close_write
177
- begin
178
- while true
179
- io.sysread(1024, @iobuf)
180
- print @iobuf
181
- end
182
- rescue EOFError
183
- end
184
- }
185
- if $?.to_i != 0
186
- raise "Command failed"
187
- end
188
- end
189
- end
190
-
191
-
192
- class Controller
193
- def initialize(conf)
194
- require 'right_aws'
195
- @key_id = conf[:key_id]
196
- @secret_key = conf[:secret_key]
197
- @queue_name = conf[:queue]
198
- @visibility_timeout = conf[:visibility_timeout]
199
- end
200
-
201
- def push(body)
202
- @sqs = RightAws::SqsGen2.new(@key_id, @secret_key)
203
- @queue = @sqs.queue(@queue_name, true, @visibility_timeout)
204
- @queue.send_message(body)
205
- end
206
-
207
- def list
208
- @sqs = RightAws::SqsGen2.new(@key_id, @secret_key)
209
- @sqs.queues.map {|q| q.name }
210
- end
211
- end
212
-
213
-
214
- def self.worker=(worker)
215
- @worker = worker
216
- end
217
-
218
- def self.receive!
219
- @worker.receive!
220
- end
221
-
222
- def self.finished?
223
- @worker.finished?
224
- end
225
-
226
-
227
- end
228
-
229
-
1
+ require 'sqsrun/worker'
2
+ require 'sqsrun/controller'
230
3
  require 'optparse'
231
4
 
232
5
  op = OptionParser.new
@@ -0,0 +1,28 @@
1
+
2
+ module SQSRun
3
+
4
+
5
+ class Controller
6
+ def initialize(conf)
7
+ require 'right_aws'
8
+ @key_id = conf[:key_id]
9
+ @secret_key = conf[:secret_key]
10
+ @queue_name = conf[:queue]
11
+ @visibility_timeout = conf[:visibility_timeout]
12
+ end
13
+
14
+ def push(body)
15
+ @sqs = RightAws::SqsGen2.new(@key_id, @secret_key)
16
+ @queue = @sqs.queue(@queue_name, true, @visibility_timeout)
17
+ @queue.send_message(body)
18
+ end
19
+
20
+ def list
21
+ @sqs = RightAws::SqsGen2.new(@key_id, @secret_key)
22
+ @sqs.queues.map {|q| q.name }
23
+ end
24
+ end
25
+
26
+
27
+ end
28
+
@@ -0,0 +1,5 @@
1
+ module SQSRun
2
+
3
+ VERSION = '0.4.0'
4
+
5
+ end
@@ -0,0 +1,206 @@
1
+ require 'monitor'
2
+
3
+ module SQSRun
4
+
5
+
6
+ class Worker
7
+ def initialize(conf)
8
+ require 'right_aws'
9
+ @key_id = conf[:key_id]
10
+ @secret_key = conf[:secret_key]
11
+ @queue_name = conf[:queue]
12
+ @visibility_timeout = conf[:timeout]
13
+ @extend_timeout = conf[:extend_timeout]
14
+ @kill_timeout = conf[:kill_timeout]
15
+ @interval = conf[:interval]
16
+ @finished = false
17
+
18
+ @extender = VisibilityExtender.new(@visibility_timeout, @extend_timeout)
19
+ @sqs = RightAws::SqsGen2.new(@key_id, @secret_key)
20
+ @queue = @sqs.queue(@queue_name)
21
+
22
+ @mutex = Mutex.new
23
+ @cond = ConditionVariable.new
24
+ end
25
+
26
+ def run(run_proc)
27
+ @run_proc = run_proc
28
+ @extender.start
29
+ until @finished
30
+ msg = @queue.receive(@visibility_timeout)
31
+ if msg
32
+ process(msg)
33
+ else
34
+ cond_wait(@interval)
35
+ end
36
+ end
37
+ end
38
+
39
+ def shutdown
40
+ @finished = true
41
+ @extender.shutdown
42
+ receive!
43
+ end
44
+
45
+ def receive!
46
+ @mutex.synchronize {
47
+ @cond.broadcast
48
+ }
49
+ end
50
+
51
+ def finished?
52
+ @finished
53
+ end
54
+
55
+ private
56
+ if ConditionVariable.new.method(:wait).arity == 1
57
+ require 'timeout'
58
+ def cond_wait(sec)
59
+ @mutex.synchronize {
60
+ Timeout.timeout(sec) {
61
+ @cond.wait(@mutex)
62
+ }
63
+ }
64
+ rescue Timeout::Error
65
+ end
66
+ else
67
+ def cond_wait(sec)
68
+ @mutex.synchronize {
69
+ @cond.wait(@mutex, sec)
70
+ }
71
+ end
72
+ end
73
+
74
+ def process(msg)
75
+ puts "started id=#{msg.id}"
76
+ thread = Thread.new(msg.to_s, &@run_proc.method(:call))
77
+
78
+ @extender.set_message(msg)
79
+
80
+ success = false
81
+ begin
82
+ joined = thread.join(@kill_timeout)
83
+ if joined
84
+ thread.value
85
+ success = true
86
+ puts "finished id=#{msg.id}"
87
+ else
88
+ thread.kill
89
+ puts "killed id=#{msg.id}"
90
+ end
91
+ rescue
92
+ puts "failed id=#{msg.id}: #{$!}"
93
+ $!.backtrace.each {|bt|
94
+ puts " #{bt}"
95
+ }
96
+ end
97
+
98
+ @extender.reset_message
99
+
100
+ if success
101
+ msg.delete
102
+ else
103
+ msg.visibility = 0
104
+ end
105
+ end
106
+
107
+ class VisibilityExtender
108
+ include MonitorMixin
109
+
110
+ def initialize(visibility_timeout, extend_timeout)
111
+ super()
112
+ @visibility_timeout = visibility_timeout
113
+ @extend_timeout = extend_timeout
114
+ @extend_time = nil
115
+ @message = nil
116
+ @finished = false
117
+ end
118
+
119
+ def start
120
+ @thread = Thread.new(&method(:run))
121
+ end
122
+
123
+ def join
124
+ @thread.join
125
+ end
126
+
127
+ def set_message(msg)
128
+ synchronize do
129
+ @extend_time = Time.now.to_i + @extend_timeout
130
+ @message = msg
131
+ end
132
+ end
133
+
134
+ def reset_message
135
+ synchronize do
136
+ @message = nil
137
+ end
138
+ end
139
+
140
+ def shutdown
141
+ @finished = true
142
+ end
143
+
144
+ private
145
+ def run
146
+ until @finished
147
+ sleep 1
148
+ synchronize do
149
+ try_extend(@message) if @message
150
+ end
151
+ end
152
+ end
153
+
154
+ def try_extend(msg)
155
+ now = Time.now.to_i
156
+ if now > @extend_time
157
+ ntime = msg.visibility + @visibility_timeout
158
+ puts "extending timeout=#{ntime} id=#{msg.id}"
159
+ msg.visibility = ntime
160
+ @extend_time = now + @extend_timeout
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+
167
+ class ExecRunner
168
+ def initialize(cmd)
169
+ @cmd = cmd + ' ' + ARGV.map {|a| Shellwords.escape(a) }.join(' ')
170
+ @iobuf = ''
171
+ end
172
+
173
+ def call(message)
174
+ IO.popen(@cmd, "r+") {|io|
175
+ io.write(message) rescue nil
176
+ io.close_write
177
+ begin
178
+ while true
179
+ io.sysread(1024, @iobuf)
180
+ print @iobuf
181
+ end
182
+ rescue EOFError
183
+ end
184
+ }
185
+ if $?.to_i != 0
186
+ raise "Command failed"
187
+ end
188
+ end
189
+ end
190
+
191
+
192
+ def self.worker=(worker)
193
+ @worker = worker
194
+ end
195
+
196
+ def self.receive!
197
+ @worker.receive!
198
+ end
199
+
200
+ def self.finished?
201
+ @worker.finished?
202
+ end
203
+
204
+
205
+ end
206
+
data/test/cat.sh ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ cat > $1
data/test/exec_test.rb ADDED
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__)+'/test_helper'
2
+
3
+ class ExecTest < Test::Unit::TestCase
4
+ it 'success' do
5
+ success_sh = File.expand_path File.dirname(__FILE__)+"/success.sh"
6
+ e = SQSRun::ExecRunner.new(success_sh)
7
+
8
+ message = 'me ssa ge'
9
+
10
+ assert_nothing_raised do
11
+ e.call(message)
12
+ end
13
+ end
14
+
15
+ it 'fail' do
16
+ fail_sh = File.expand_path File.dirname(__FILE__)+"/fail.sh"
17
+ e = SQSRun::ExecRunner.new(fail_sh)
18
+
19
+ message = 'me ssa ge'
20
+
21
+ assert_raise(RuntimeError) do
22
+ e.call(message)
23
+ end
24
+ end
25
+
26
+ it 'stdin' do
27
+ cat_sh = File.expand_path File.dirname(__FILE__)+"/cat.sh"
28
+ out_tmp = File.expand_path File.dirname(__FILE__)+"/cat.sh.tmp"
29
+ e = SQSRun::ExecRunner.new("#{cat_sh} #{out_tmp}")
30
+
31
+ message = 'me ssa ge'
32
+
33
+ e.call(message)
34
+
35
+ assert_equal message, File.read(out_tmp)
36
+ end
37
+
38
+ it 'huge' do
39
+ huge_sh = File.expand_path File.dirname(__FILE__)+"/huge.sh"
40
+ e = SQSRun::ExecRunner.new("#{huge_sh}")
41
+
42
+ message = 'me ssa ge'
43
+
44
+ e.call(message)
45
+
46
+ # should finish
47
+ end
48
+ end
49
+
data/test/fail.sh ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ exit 1
data/test/huge.sh ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ dd if=/dev/zero bs=1024 count=1024
data/test/success.sh ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ exit 0
@@ -0,0 +1,15 @@
1
+ require 'test/unit'
2
+ $LOAD_PATH << File.dirname(__FILE__)+"/../lib"
3
+ require 'sqsrun/worker'
4
+ require 'sqsrun/controller'
5
+ require 'fileutils'
6
+
7
+ class Test::Unit::TestCase
8
+ #class << self
9
+ # alias_method :it, :test
10
+ #end
11
+ def self.it(name, &block)
12
+ define_method("test_#{name}", &block)
13
+ end
14
+ end
15
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqsrun
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sadayuki Furuhashi
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-11 00:00:00 +09:00
18
+ date: 2011-07-12 00:00:00 +09:00
19
19
  default_executable: sqsrun
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -45,7 +45,16 @@ extra_rdoc_files:
45
45
  files:
46
46
  - bin/sqsrun
47
47
  - lib/sqsrun/command/sqsrun.rb
48
+ - lib/sqsrun/controller.rb
49
+ - lib/sqsrun/version.rb
50
+ - lib/sqsrun/worker.rb
51
+ - test/exec_test.rb
52
+ - test/test_helper.rb
48
53
  - README.rdoc
54
+ - test/cat.sh
55
+ - test/fail.sh
56
+ - test/huge.sh
57
+ - test/success.sh
49
58
  has_rdoc: true
50
59
  homepage:
51
60
  licenses: []
@@ -80,5 +89,10 @@ rubygems_version: 1.3.7
80
89
  signing_key:
81
90
  specification_version: 3
82
91
  summary: Generic SQS Worker Executor Service
83
- test_files: []
84
-
92
+ test_files:
93
+ - test/exec_test.rb
94
+ - test/test_helper.rb
95
+ - test/cat.sh
96
+ - test/fail.sh
97
+ - test/huge.sh
98
+ - test/success.sh