sqsrun 0.3.0 → 0.4.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.
@@ -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