opener-daemons 0.4.2 → 0.6.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 +13 -5
- data/lib/opener/daemons/daemon.rb +76 -46
- data/lib/opener/daemons/opt_parser.rb +14 -2
- data/lib/opener/daemons/version.rb +1 -1
- metadata +39 -38
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OWIyYmNmYWY3MzVjMmYzNzAwYzIzMTk4ZDlhMzAwYThhMjE4ZTdlNw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MzMzNDQwOTg0OTgwYWVkZjMxNGI2ODU4MWE1YmYxZDUxMjQyY2Q5Ng==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YzdkZDFmNTZmZTYzZmQ1ZTMzODNkMmY0YWQ5MTFmYTg1ZDM1MGE1Y2QxMzc2
|
10
|
+
YzdkMDczNjk1NTc3NjVmNzc2OTEzYzBkOWJmMzg4MjA4N2NlNjc5ZDIzNDAx
|
11
|
+
OGFhN2E2ZGM0N2JjZjA0ZmNhOTNjMDU4OWQ3MjMyNWMzMGZjMmY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YjBhYzJjZTAwOTZkNjg3MTQ3MjRmZDU0YjFjYzY2ZjlmYjE5N2MzMWRiYTUz
|
14
|
+
OGRjZjE5MGFlN2QwNzNlMGRlYmRhNzViZWUzMDNlZmZhYjA2NWE1YmY3OTdi
|
15
|
+
NWRmYTFhZWY5ZDhkYjNmYTAwYmI1NzY3MjI5MjQ1Nzk1YWQyYmQ=
|
@@ -2,10 +2,13 @@ require 'thread'
|
|
2
2
|
require 'opener/daemons/sqs'
|
3
3
|
require 'json'
|
4
4
|
|
5
|
+
Encoding.default_internal = Encoding::UTF_8
|
6
|
+
Encoding.default_external = Encoding::UTF_8
|
7
|
+
|
5
8
|
module Opener
|
6
9
|
module Daemons
|
7
10
|
class Daemon
|
8
|
-
attr_reader :batch_size,
|
11
|
+
attr_reader :batch_size, :buffer_size, :sleep_interval,
|
9
12
|
:input_queue, :output_queue,
|
10
13
|
:input_buffer, :output_buffer,
|
11
14
|
:klass,
|
@@ -14,27 +17,34 @@ module Opener
|
|
14
17
|
attr_accessor :threads, :thread_counts
|
15
18
|
|
16
19
|
def initialize(klass, options={})
|
17
|
-
@input_queue = Opener::Daemons::SQS.find(options.fetch(:input_queue))
|
18
|
-
@output_queue = Opener::Daemons::SQS.find(options.fetch(:output_queue))
|
19
20
|
|
20
|
-
@threads = {}
|
21
|
-
@
|
22
|
-
|
23
|
-
|
21
|
+
@threads = {:readers=>[], :workers=>[], :writers=>[], :reporters=>[]}
|
22
|
+
@thread_counts = {:readers => options.fetch(:readers, 1),
|
23
|
+
:workers => options.fetch(:workers, 5),
|
24
|
+
:writers => options.fetch(:writers, 1)}
|
24
25
|
|
25
|
-
@
|
26
|
-
@
|
27
|
-
@thread_counts[:workers] = options.fetch(:workers, 5)
|
28
|
-
@thread_counts[:writers] = options.fetch(:writers, 1)
|
26
|
+
@relentless = options.fetch(:relentless, false)
|
27
|
+
@sleep_interval = options.fetch(:sleep_interval, 5)
|
29
28
|
|
30
|
-
|
29
|
+
# Initialize queues
|
30
|
+
@input_queue = Opener::Daemons::SQS.find(options.fetch(:input_queue))
|
31
|
+
if options[:output_queue]
|
32
|
+
@output_queue = Opener::Daemons::SQS.find(options[:output_queue])
|
33
|
+
end
|
31
34
|
|
35
|
+
# Initialize Buffers
|
32
36
|
@input_buffer = Queue.new
|
33
37
|
@output_buffer = Queue.new
|
34
38
|
|
39
|
+
# Batch and Buffer size for a smooth flow.
|
40
|
+
@batch_size = options.fetch(:batch_size, 10)
|
41
|
+
@buffer_size = options[:buffer_size]
|
42
|
+
|
43
|
+
# Working component
|
35
44
|
@klass = klass
|
36
45
|
|
37
46
|
script_name = File.basename($0, ".rb")
|
47
|
+
|
38
48
|
@logger = Logger.new(options.fetch(:log, STDOUT))
|
39
49
|
@logger.level = if options.fetch(:debug, false)
|
40
50
|
Logger::DEBUG
|
@@ -42,22 +52,19 @@ module Opener
|
|
42
52
|
Logger::INFO
|
43
53
|
end
|
44
54
|
|
55
|
+
logger.debug(options.to_json)
|
45
56
|
end
|
46
57
|
|
47
58
|
def buffer_new_messages
|
48
|
-
if input_buffer.size > buffer_size
|
49
|
-
|
50
|
-
return
|
51
|
-
end
|
52
|
-
|
53
|
-
if output_buffer.size > buffer_size
|
54
|
-
#logger.debug "Maximum output buffer size reached"
|
55
|
-
return
|
56
|
-
end
|
59
|
+
return if input_buffer.size > buffer_size
|
60
|
+
return if output_buffer.size > buffer_size
|
57
61
|
|
58
62
|
messages = input_queue.receive_messages(batch_size)
|
59
63
|
|
60
|
-
|
64
|
+
if messages.nil?
|
65
|
+
sleep(sleep_interval)
|
66
|
+
return
|
67
|
+
end
|
61
68
|
messages.each do |message|
|
62
69
|
input_buffer << message
|
63
70
|
end
|
@@ -65,21 +72,30 @@ module Opener
|
|
65
72
|
|
66
73
|
def start
|
67
74
|
Thread.abort_on_exception = true
|
68
|
-
|
69
|
-
|
70
|
-
|
75
|
+
|
76
|
+
start_readers
|
77
|
+
start_workers
|
78
|
+
start_writers
|
79
|
+
start_reporters
|
80
|
+
|
81
|
+
threads[:readers].each(&:join)
|
82
|
+
threads[:workers].each(&:join)
|
83
|
+
threads[:writers].each(&:join)
|
84
|
+
threads[:reporters].each(&:join)
|
85
|
+
end
|
86
|
+
|
87
|
+
def start_readers
|
71
88
|
thread_counts[:readers].times do |t|
|
72
89
|
threads[:readers] << Thread.new do
|
73
|
-
logger.info "
|
90
|
+
logger.info "Reader #{t+1} ready for action..."
|
74
91
|
loop do
|
75
92
|
buffer_new_messages
|
76
93
|
end
|
77
94
|
end
|
78
95
|
end
|
96
|
+
end
|
79
97
|
|
80
|
-
|
81
|
-
# Load Workers
|
82
|
-
#
|
98
|
+
def start_workers
|
83
99
|
thread_counts[:workers].times do |t|
|
84
100
|
threads[:workers] << Thread.new do
|
85
101
|
logger.info "Worker #{t+1} launching..."
|
@@ -96,53 +112,67 @@ module Opener
|
|
96
112
|
raise "The component returned an empty response."
|
97
113
|
end
|
98
114
|
rescue Exception => e
|
99
|
-
|
100
|
-
|
115
|
+
if relentless?
|
116
|
+
raise
|
117
|
+
else
|
118
|
+
logger.error(e)
|
119
|
+
output = input
|
120
|
+
end
|
101
121
|
end
|
122
|
+
|
102
123
|
output_buffer.push({ :output=>output,
|
103
|
-
|
124
|
+
:handle=>message[:receipt_handle]})
|
104
125
|
end
|
105
126
|
end
|
106
127
|
end
|
128
|
+
end
|
107
129
|
|
108
|
-
|
109
|
-
# Load Writers
|
110
|
-
#
|
130
|
+
def start_writers
|
111
131
|
thread_counts[:writers].times do |t|
|
112
132
|
threads[:writers] << Thread.new do
|
113
133
|
logger.info "Pusher #{t+1} ready for action..."
|
114
134
|
loop do
|
115
135
|
message = output_buffer.pop
|
116
136
|
|
117
|
-
payload = {:input=>message[:output]}.to_json
|
118
|
-
output_queue.send_message(payload)
|
137
|
+
payload = {:input=>message[:output].force_encoding("UTF-8")}.to_json
|
138
|
+
output_queue.send_message(payload) if output_queue
|
119
139
|
input_queue.delete_message(message[:handle])
|
120
140
|
end
|
121
141
|
end
|
122
142
|
end
|
143
|
+
end
|
123
144
|
|
124
|
-
|
145
|
+
def start_reporters
|
146
|
+
threads[:reporters] << Thread.new do
|
125
147
|
loop do
|
126
|
-
|
148
|
+
log = {:buffers=>{:input=>input_buffer.size}}
|
149
|
+
log[:buffers][:output] = output_buffer.size if output_buffer
|
127
150
|
|
128
|
-
|
151
|
+
logger.debug log.to_json
|
152
|
+
sleep(2)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
threads[:reporters] << Thread.new do
|
157
|
+
loop do
|
158
|
+
thread_types = threads.keys - [:reporters]
|
129
159
|
thread_counts = thread_types.map do |type|
|
130
160
|
threads[type].select{|thread| thread.status}.count
|
131
161
|
end
|
132
162
|
zip = thread_types.zip(thread_counts)
|
133
163
|
logger.debug "active thread counts: #{zip}"
|
134
164
|
|
135
|
-
sleep(
|
165
|
+
sleep(10)
|
136
166
|
end
|
137
167
|
end
|
138
|
-
|
139
|
-
threads[:readers].each(&:join)
|
140
|
-
threads[:workers].each(&:join)
|
141
|
-
threads[:writers].each(&:join)
|
142
168
|
end
|
143
169
|
|
144
170
|
def buffer_size
|
145
|
-
4 * batch_size
|
171
|
+
@buffer_size ||= (4 * batch_size)
|
172
|
+
end
|
173
|
+
|
174
|
+
def relentless?
|
175
|
+
@relentless
|
146
176
|
end
|
147
177
|
|
148
178
|
end
|
@@ -59,10 +59,18 @@ module Opener
|
|
59
59
|
options[:output_queue] = v
|
60
60
|
end
|
61
61
|
|
62
|
-
opts.on("
|
62
|
+
opts.on("--batch-size ITEMS", Integer, "Request x messages at once where x is between 1 and 10") do |v|
|
63
63
|
options[:batch_size] = v
|
64
64
|
end
|
65
65
|
|
66
|
+
opts.on("--buffer-size ITEMS", Integer, "Size of input and output buffer. Defaults to 4 * batch-size") do |v|
|
67
|
+
options[:buffer_size] = v
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.on("--sleep-interval TIME_IN_SECONDS", Integer, "The interval to sleep when the queue is empty (seconds)") do |v|
|
71
|
+
options[:sleep_interval] = v
|
72
|
+
end
|
73
|
+
|
66
74
|
opts.on("-w", "--workers NUMBER", Integer, "number of worker thread") do |v|
|
67
75
|
options[:workers] = v
|
68
76
|
end
|
@@ -79,7 +87,7 @@ module Opener
|
|
79
87
|
options[:log] = v
|
80
88
|
end
|
81
89
|
|
82
|
-
opts.on("--pid FILENAME", "Filename and path of pidfile. Defaults to /var/run
|
90
|
+
opts.on("--pidfile FILENAME", "--pid FILENAME", "Filename and path of pidfile. Defaults to /var/run/#{script_name}.pid") do |v|
|
83
91
|
options[:pid] = v
|
84
92
|
end
|
85
93
|
|
@@ -91,6 +99,10 @@ module Opener
|
|
91
99
|
options[:debug] = true
|
92
100
|
end
|
93
101
|
|
102
|
+
opts.on("--relentless", "Be relentless, fail fast, fail hard, do not continue processing when encountering component errors") do |v|
|
103
|
+
options[:relentless] = true
|
104
|
+
end
|
105
|
+
|
94
106
|
opts.separator ""
|
95
107
|
|
96
108
|
opts.separator "Common options:"
|
metadata
CHANGED
@@ -1,86 +1,87 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opener-daemons
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wilco van Duinkerken
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-core
|
15
|
-
version_requirements: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - '>='
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
15
|
requirement: !ruby/object:Gem::Requirement
|
21
16
|
requirements:
|
22
|
-
- - '>='
|
17
|
+
- - ! '>='
|
23
18
|
- !ruby/object:Gem::Version
|
24
19
|
version: '0'
|
25
|
-
prerelease: false
|
26
20
|
type: :runtime
|
27
|
-
|
28
|
-
name: spoon
|
21
|
+
prerelease: false
|
29
22
|
version_requirements: !ruby/object:Gem::Requirement
|
30
23
|
requirements:
|
31
|
-
- - '>='
|
24
|
+
- - ! '>='
|
32
25
|
- !ruby/object:Gem::Version
|
33
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: spoon
|
34
29
|
requirement: !ruby/object:Gem::Requirement
|
35
30
|
requirements:
|
36
|
-
- - '>='
|
31
|
+
- - ! '>='
|
37
32
|
- !ruby/object:Gem::Version
|
38
33
|
version: '0'
|
39
|
-
prerelease: false
|
40
34
|
type: :runtime
|
41
|
-
|
42
|
-
name: bundler
|
35
|
+
prerelease: false
|
43
36
|
version_requirements: !ruby/object:Gem::Requirement
|
44
37
|
requirements:
|
45
|
-
- -
|
38
|
+
- - ! '>='
|
46
39
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
44
|
requirements:
|
50
45
|
- - ~>
|
51
46
|
- !ruby/object:Gem::Version
|
52
47
|
version: '1.5'
|
53
|
-
prerelease: false
|
54
48
|
type: :development
|
55
|
-
|
56
|
-
name: rake
|
49
|
+
prerelease: false
|
57
50
|
version_requirements: !ruby/object:Gem::Requirement
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ~>
|
60
53
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
62
57
|
requirement: !ruby/object:Gem::Requirement
|
63
58
|
requirements:
|
64
|
-
- - '>='
|
59
|
+
- - ! '>='
|
65
60
|
- !ruby/object:Gem::Version
|
66
61
|
version: '0'
|
67
|
-
prerelease: false
|
68
62
|
type: :development
|
69
|
-
|
70
|
-
name: rspec
|
63
|
+
prerelease: false
|
71
64
|
version_requirements: !ruby/object:Gem::Requirement
|
72
65
|
requirements:
|
73
|
-
- - '>='
|
66
|
+
- - ! '>='
|
74
67
|
- !ruby/object:Gem::Version
|
75
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
76
71
|
requirement: !ruby/object:Gem::Requirement
|
77
72
|
requirements:
|
78
|
-
- - '>='
|
73
|
+
- - ! '>='
|
79
74
|
- !ruby/object:Gem::Version
|
80
75
|
version: '0'
|
81
|
-
prerelease: false
|
82
76
|
type: :development
|
83
|
-
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Daemonize OpeNER components and make them read from an SQS queue. JRuby
|
84
|
+
compatible.
|
84
85
|
email:
|
85
86
|
- wilco@sparkboxx.com
|
86
87
|
executables: []
|
@@ -103,24 +104,24 @@ homepage: http://opener-project.github.io
|
|
103
104
|
licenses:
|
104
105
|
- MIT
|
105
106
|
metadata: {}
|
106
|
-
post_install_message:
|
107
|
+
post_install_message:
|
107
108
|
rdoc_options: []
|
108
109
|
require_paths:
|
109
110
|
- lib
|
110
111
|
required_ruby_version: !ruby/object:Gem::Requirement
|
111
112
|
requirements:
|
112
|
-
- - '>='
|
113
|
+
- - ! '>='
|
113
114
|
- !ruby/object:Gem::Version
|
114
115
|
version: '0'
|
115
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
117
|
requirements:
|
117
|
-
- - '>='
|
118
|
+
- - ! '>='
|
118
119
|
- !ruby/object:Gem::Version
|
119
120
|
version: '0'
|
120
121
|
requirements: []
|
121
|
-
rubyforge_project:
|
122
|
-
rubygems_version: 2.
|
123
|
-
signing_key:
|
122
|
+
rubyforge_project:
|
123
|
+
rubygems_version: 2.1.11
|
124
|
+
signing_key:
|
124
125
|
specification_version: 4
|
125
126
|
summary: Daemonize OpeNER components and make them read from an SQS queue. JRuby compatible.
|
126
127
|
test_files: []
|