opener-daemons 0.4.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 92495f6b7af2acc1f0f83462c71f21a52bb25f4f
4
- data.tar.gz: e6fea06acac2ee6bf859a76768a68549f927aff0
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OWIyYmNmYWY3MzVjMmYzNzAwYzIzMTk4ZDlhMzAwYThhMjE4ZTdlNw==
5
+ data.tar.gz: !binary |-
6
+ MzMzNDQwOTg0OTgwYWVkZjMxNGI2ODU4MWE1YmYxZDUxMjQyY2Q5Ng==
5
7
  SHA512:
6
- metadata.gz: ad2cd39279379f1323008b65284893bd6ce81ff16dc5b931496747c3b35c931c1235315134cd3778a0e005b20de0f9e0258d56ec06c391a99e56f0cb33d93e5f
7
- data.tar.gz: c4cad8ceb7fb4195ba8e7786288d4ccbfb30145a7e30425fb34e91a3fd2ea889cdef563a9bf5afa2a6f46ea549d41dfe452b08f9ff4b13eb656de19a25e68058
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
- @threads[:readers] = []
22
- @threads[:workers] = []
23
- @threads[:writers] = []
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
- @thread_counts = {}
26
- @thread_counts[:readers] = options.fetch(:readers, 1)
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
- @batch_size = options.fetch(:batch_size, 10)
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
- #logger.debug "Maximum input buffer size reached"
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
- return if messages.nil?
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
- # Load Readers
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 "Producer #{t+1} ready for action..."
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
- logger.error(e)
100
- output = input
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
- :handle=>message[:receipt_handle]})
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
- reporter = Thread.new do
145
+ def start_reporters
146
+ threads[:reporters] << Thread.new do
125
147
  loop do
126
- logger.debug "input buffer: #{input_buffer.size} \t output buffer: #{output_buffer.size}"
148
+ log = {:buffers=>{:input=>input_buffer.size}}
149
+ log[:buffers][:output] = output_buffer.size if output_buffer
127
150
 
128
- thread_types = [:readers, :workers, :writers]
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(2)
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("-b", "--batch-size BATCH_SIZE", Integer, "Request x messages at once where x is between 1 and 10") do |v|
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/{basename of current script}.pid") do |v|
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:"
@@ -1,5 +1,5 @@
1
1
  module Opener
2
2
  module Daemons
3
- VERSION = "0.4.2"
3
+ VERSION = "0.6.0"
4
4
  end
5
5
  end
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.2
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-07 00:00:00.000000000 Z
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
- - !ruby/object:Gem::Dependency
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
- - !ruby/object:Gem::Dependency
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: '1.5'
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
- - !ruby/object:Gem::Dependency
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: '0'
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
- - !ruby/object:Gem::Dependency
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
- description: Daemonize OpeNER components and make them read from an SQS queue. JRuby compatible.
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.2.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: []