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 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: []