sqewer 4.0.0 → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/lib/sqewer/connection_messagebox.rb +2 -1
- data/lib/sqewer/isolator.rb +11 -8
- data/lib/sqewer/state_lock.rb +24 -0
- data/lib/sqewer/version.rb +1 -1
- data/lib/sqewer/worker.rb +5 -10
- data/spec/sqewer/cli_spec.rb +2 -2
- data/sqewer.gemspec +6 -5
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b516a6047b6e4470f59d4890618272005ce1a849
|
4
|
+
data.tar.gz: 8cb5e9d063df19d987ea7bc84e3f69a79a48a8e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d74828a5dd45a9e8e7be4a6ea06e175f50335ca783cb04e3df50a2cc1e4900f282026a0d622a614ac9037600aa3c0f0a777085dcd7e682f28e44569425f598b3
|
7
|
+
data.tar.gz: 6e517aad10bf1b4a6be180fb734a697896034b0a15dd844a40df793ad67539afcdc6fcc70c123c16fc7eb12f433c3c6127b506ccb8a88538a0de3fb85d4be162
|
data/Gemfile
CHANGED
@@ -3,7 +3,8 @@ require 'thread'
|
|
3
3
|
# A recorder for send_message and delete_message calls.
|
4
4
|
# Will buffer those calls as if it were a Connection, and then execute
|
5
5
|
# them within a synchronized mutex lock, to prevent concurrent submits
|
6
|
-
#
|
6
|
+
# to the Connection object, and, consequently, concurrent calls to the
|
7
|
+
# SQS client.
|
7
8
|
class Sqewer::ConnectionMessagebox
|
8
9
|
class MethodCall < Struct.new(:method_name, :posargs, :kwargs)
|
9
10
|
def perform(on)
|
data/lib/sqewer/isolator.rb
CHANGED
@@ -33,12 +33,17 @@ class Sqewer::Isolator
|
|
33
33
|
# @param worker[Sqewer::Worker] the worker that is running the jobs
|
34
34
|
# @param message[Sqewer::Connection::Message] the message that is being processed
|
35
35
|
def perform(worker, message)
|
36
|
+
submitter_class = worker.submitter_class
|
37
|
+
execution_context_class = worker.execution_context_class
|
38
|
+
middleware_stack = worker.middleware_stack
|
39
|
+
connection = worker.connection
|
40
|
+
logger = worker.logger
|
41
|
+
serializer = worker.serializer
|
36
42
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
43
|
+
# Create a messagebox that buffers all the calls to Connection, so that
|
44
|
+
# we can send out those commands in one go (without interfering with senders
|
45
|
+
# on other threads, as it seems the Aws::SQS::Client is not entirely
|
46
|
+
# thread-safe - or at least not it's HTTP client part).
|
42
47
|
box = Sqewer::ConnectionMessagebox.new(connection)
|
43
48
|
|
44
49
|
job = middleware_stack.around_deserialization(serializer, message.receipt_handle, message.body) do
|
@@ -60,10 +65,8 @@ class Sqewer::Isolator
|
|
60
65
|
|
61
66
|
delta = Time.now - t
|
62
67
|
logger.info { "[worker] Finished %s in %0.2fs" % [job.inspect, delta] }
|
63
|
-
rescue => e
|
64
|
-
raise e
|
65
68
|
ensure
|
66
69
|
n_flushed = box.flush!
|
67
|
-
logger.
|
70
|
+
logger.debug { "[worker] Flushed %d connection commands" % n_flushed } if n_flushed.nonzero?
|
68
71
|
end
|
69
72
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
# Controls the state of the Worker object, and wraps it's state transitions
|
5
|
+
# with a Mutex.
|
6
|
+
class Sqewer::StateLock < SimpleDelegator
|
7
|
+
def initialize
|
8
|
+
@m = Mutex.new
|
9
|
+
m = VeryTinyStateMachine.new(:stopped)
|
10
|
+
m.permit_state :starting, :running, :stopping, :stopped, :failed
|
11
|
+
m.permit_transition :stopped => :starting, :starting => :running
|
12
|
+
m.permit_transition :running => :stopping, :stopping => :stopped
|
13
|
+
m.permit_transition :starting => :failed # Failed to start
|
14
|
+
__setobj__(m)
|
15
|
+
end
|
16
|
+
|
17
|
+
def in_state?(some_state)
|
18
|
+
@m.synchronize { __getobj__.in_state?(some_state) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def transition!(to_state)
|
22
|
+
@m.synchronize { __getobj__.transition!(to_state) }
|
23
|
+
end
|
24
|
+
end
|
data/lib/sqewer/version.rb
CHANGED
data/lib/sqewer/worker.rb
CHANGED
@@ -74,10 +74,7 @@ class Sqewer::Worker
|
|
74
74
|
|
75
75
|
@execution_counter = Sqewer::AtomicCounter.new
|
76
76
|
|
77
|
-
@state =
|
78
|
-
@state.permit_state :starting, :running, :stopping, :stopped, :failed
|
79
|
-
@state.permit_transition :stopped => :starting, :starting => :running, :running => :stopping, :stopping => :stopped
|
80
|
-
@state.permit_transition :starting => :failed # Failed to start
|
77
|
+
@state = Sqewer::StateLock.new
|
81
78
|
end
|
82
79
|
|
83
80
|
# Start listening on the queue, spin up a number of consumer threads that will execute the jobs.
|
@@ -117,9 +114,8 @@ class Sqewer::Worker
|
|
117
114
|
Thread.pass
|
118
115
|
end
|
119
116
|
else
|
120
|
-
@logger.debug { "[worker]
|
121
|
-
sleep
|
122
|
-
Thread.pass
|
117
|
+
@logger.debug { "[worker] Cache is full (%d items), postponing receive" % @execution_queue.length }
|
118
|
+
sleep SLEEP_SECONDS_ON_EMPTY_QUEUE
|
123
119
|
end
|
124
120
|
end
|
125
121
|
end
|
@@ -147,7 +143,7 @@ class Sqewer::Worker
|
|
147
143
|
break if n_live.zero?
|
148
144
|
|
149
145
|
n_dead = @threads.length - n_live
|
150
|
-
@logger.info {
|
146
|
+
@logger.info { '[worker] Waiting on threads to terminate, %d still alive, %d quit' % [n_live, n_dead] }
|
151
147
|
|
152
148
|
sleep 2
|
153
149
|
end
|
@@ -188,9 +184,8 @@ class Sqewer::Worker
|
|
188
184
|
handle_message(message)
|
189
185
|
rescue ThreadError # Queue is empty
|
190
186
|
sleep SLEEP_SECONDS_ON_EMPTY_QUEUE
|
191
|
-
Thread.pass
|
192
187
|
rescue => e # anything else, at or below StandardError that does not need us to quit
|
193
|
-
@logger.error {
|
188
|
+
@logger.error { '[worker] Failed "%s..." with %s: %s' % [message.inspect[0..32], e.class, e.message] }
|
194
189
|
e.backtrace.each { |s| @logger.error{"\t#{s}"} }
|
195
190
|
end
|
196
191
|
end
|
data/spec/sqewer/cli_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe Sqewer::CLI, :sqs => true, :wait => {timeout: 120} do
|
|
12
12
|
stderr = Tempfile.new('worker-stderr')
|
13
13
|
stderr.sync = true
|
14
14
|
|
15
|
-
pid = fork { $stderr.reopen(stderr); exec("ruby #{__dir__}/cli_app.rb") }
|
15
|
+
pid = fork { $stderr.reopen(stderr); $stderr.sync = true; exec("ruby #{__dir__}/cli_app.rb") }
|
16
16
|
|
17
17
|
Thread.new do
|
18
18
|
20.times do
|
@@ -39,7 +39,7 @@ describe Sqewer::CLI, :sqs => true, :wait => {timeout: 120} do
|
|
39
39
|
stderr = Tempfile.new('worker-stderr')
|
40
40
|
stderr.sync = true
|
41
41
|
|
42
|
-
pid = fork { $stderr.reopen(stderr); exec("ruby #{__dir__}/cli_app.rb") }
|
42
|
+
pid = fork { $stderr.reopen(stderr); $stderr.sync; exec("ruby #{__dir__}/cli_app.rb") }
|
43
43
|
|
44
44
|
Thread.new do
|
45
45
|
20.times do
|
data/sqewer.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: sqewer 4.0.
|
5
|
+
# stub: sqewer 4.0.1 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "sqewer"
|
9
|
-
s.version = "4.0.
|
9
|
+
s.version = "4.0.1"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
@@ -40,6 +40,7 @@ Gem::Specification.new do |s|
|
|
40
40
|
"lib/sqewer/null_logger.rb",
|
41
41
|
"lib/sqewer/serializer.rb",
|
42
42
|
"lib/sqewer/simple_job.rb",
|
43
|
+
"lib/sqewer/state_lock.rb",
|
43
44
|
"lib/sqewer/submitter.rb",
|
44
45
|
"lib/sqewer/version.rb",
|
45
46
|
"lib/sqewer/worker.rb",
|
@@ -67,7 +68,7 @@ Gem::Specification.new do |s|
|
|
67
68
|
|
68
69
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
69
70
|
s.add_runtime_dependency(%q<aws-sdk>, ["~> 2"])
|
70
|
-
s.add_runtime_dependency(%q<very_tiny_state_machine>, ["
|
71
|
+
s.add_runtime_dependency(%q<very_tiny_state_machine>, [">= 0"])
|
71
72
|
s.add_runtime_dependency(%q<hash_tools>, [">= 0"])
|
72
73
|
s.add_runtime_dependency(%q<exceptional_fork>, [">= 0"])
|
73
74
|
s.add_development_dependency(%q<ks>, [">= 0"])
|
@@ -81,7 +82,7 @@ Gem::Specification.new do |s|
|
|
81
82
|
s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
|
82
83
|
else
|
83
84
|
s.add_dependency(%q<aws-sdk>, ["~> 2"])
|
84
|
-
s.add_dependency(%q<very_tiny_state_machine>, ["
|
85
|
+
s.add_dependency(%q<very_tiny_state_machine>, [">= 0"])
|
85
86
|
s.add_dependency(%q<hash_tools>, [">= 0"])
|
86
87
|
s.add_dependency(%q<exceptional_fork>, [">= 0"])
|
87
88
|
s.add_dependency(%q<ks>, [">= 0"])
|
@@ -96,7 +97,7 @@ Gem::Specification.new do |s|
|
|
96
97
|
end
|
97
98
|
else
|
98
99
|
s.add_dependency(%q<aws-sdk>, ["~> 2"])
|
99
|
-
s.add_dependency(%q<very_tiny_state_machine>, ["
|
100
|
+
s.add_dependency(%q<very_tiny_state_machine>, [">= 0"])
|
100
101
|
s.add_dependency(%q<hash_tools>, [">= 0"])
|
101
102
|
s.add_dependency(%q<exceptional_fork>, [">= 0"])
|
102
103
|
s.add_dependency(%q<ks>, [">= 0"])
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sqewer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: very_tiny_state_machine
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: hash_tools
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -221,6 +221,7 @@ files:
|
|
221
221
|
- lib/sqewer/null_logger.rb
|
222
222
|
- lib/sqewer/serializer.rb
|
223
223
|
- lib/sqewer/simple_job.rb
|
224
|
+
- lib/sqewer/state_lock.rb
|
224
225
|
- lib/sqewer/submitter.rb
|
225
226
|
- lib/sqewer/version.rb
|
226
227
|
- lib/sqewer/worker.rb
|