opener-daemons 1.3.0 → 2.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.
@@ -0,0 +1,85 @@
1
+ module Opener
2
+ module Daemons
3
+ ##
4
+ # Class for writing and retrieving PID files as well as managing the
5
+ # associated process.
6
+ #
7
+ # @!attribute [r] path
8
+ # The path to store the PID in.
9
+ # @return [String]
10
+ #
11
+ class Pidfile
12
+ attr_reader :path
13
+
14
+ ##
15
+ # @param [String] path
16
+ #
17
+ def initialize(path)
18
+ @path = path
19
+ end
20
+
21
+ ##
22
+ # Writes the given process ID to `@path`.
23
+ #
24
+ # @param [Fixnum] id
25
+ #
26
+ def write(id)
27
+ File.open(path, 'w') do |handle|
28
+ handle.write(id.to_s)
29
+ end
30
+
31
+ # Kill the process immediately if we couldn't write the PID
32
+ rescue Errno::ENOENT, Errno::EPERM => error
33
+ Process.kill('KILL', id)
34
+ end
35
+
36
+ ##
37
+ # Reads and returns the process ID.
38
+ #
39
+ # @return [Fixnum]
40
+ #
41
+ def read
42
+ return File.read(path).to_i
43
+ end
44
+
45
+ ##
46
+ # Removes the associated file, if it exists.
47
+ #
48
+ def unlink
49
+ File.unlink(path) if File.file?(path)
50
+ end
51
+
52
+ ##
53
+ # Terminates the process by sending it the TERM signal and waits for it to
54
+ # shut down.
55
+ #
56
+ def terminate
57
+ id = read
58
+
59
+ begin
60
+ Process.kill('TERM', id)
61
+ Process.wait(id)
62
+ rescue Errno::ESRCH, Errno::ECHILD
63
+ # Process terminated, yay. Any other error is re-raised.
64
+ end
65
+ end
66
+
67
+ ##
68
+ # Returns `true` if the associated process is alive.
69
+ #
70
+ # @return [TrueClass|FalseClass]
71
+ #
72
+ def alive?
73
+ id = read
74
+
75
+ begin
76
+ Process.kill(0, id)
77
+
78
+ return true
79
+ rescue Errno::ESRCH, Errno::EPERM
80
+ return false
81
+ end
82
+ end
83
+ end # Pidfile
84
+ end # Daemons
85
+ end # Opener
@@ -0,0 +1,58 @@
1
+ module Opener
2
+ module Daemons
3
+ ##
4
+ # Wrapper around `Syslog` that makes it easier to disable loggers and to log
5
+ # custom key/value pairs in message.
6
+ #
7
+ module Syslog
8
+ ##
9
+ # Configures Syslog.
10
+ #
11
+ # @see [Syslog.open]
12
+ # @param [String] name The name of the program.
13
+ # @param [Fixnum] facility
14
+ #
15
+ def self.open(name, facility = nil)
16
+ ::Syslog.open(name, facility) if Daemons.syslog?
17
+ end
18
+
19
+ # methods defined using define_method() are slower than those defined
20
+ # using eval() on JRuby and Rubinius.
21
+ [:debug, :err, :fatal, :info, :warn, :unknown].each do |method|
22
+ eval <<-EOF, nil, __FILE__, __LINE__ + 1
23
+ def self.#{method}(message, meta = {})
24
+ add(:#{method}, message, meta)
25
+ end
26
+ EOF
27
+ end
28
+
29
+ ##
30
+ # Adds a new log message.
31
+ #
32
+ # @example
33
+ # add(:info, 'Testing Syslog', :user_id => 19)
34
+ #
35
+ # @param [Symbol] type The type of log message to add, corresponds to the
36
+ # logger method that will be called.
37
+ #
38
+ # @param [String] message The message to log.
39
+ # @param [Hash] meta Extra meta data to log.
40
+ #
41
+ def self.add(type, message, meta = {})
42
+ return unless Daemons.syslog?
43
+
44
+ pairs = make_pairs(meta)
45
+
46
+ ::Syslog.send(type, "#{pairs} #{message}".strip)
47
+ end
48
+
49
+ ##
50
+ # @param [Hash] meta
51
+ # @return [String]
52
+ #
53
+ def self.make_pairs(meta)
54
+ return meta.map { |(key, value)| "#{key}=#{value.inspect}" }.join(' ')
55
+ end
56
+ end # Syslog
57
+ end # Daemons
58
+ end # Opener
@@ -0,0 +1,50 @@
1
+ module Opener
2
+ module Daemons
3
+ ##
4
+ # Class for uploading KAF documents to Amazon S3.
5
+ #
6
+ class Uploader
7
+ ##
8
+ # Uploads the given KAF document.
9
+ #
10
+ # @param [String] identifier
11
+ # @param [String] document
12
+ # @param [Hash] metadata description
13
+ #
14
+ # @return [AWS::S3::S3Object]
15
+ #
16
+ def upload(identifier, document, metadata = {})
17
+ object = create(
18
+ "#{identifier}.xml",
19
+ document,
20
+ :metadata => metadata,
21
+ :content_type => 'application/xml'
22
+ )
23
+
24
+ return object
25
+ end
26
+
27
+ ##
28
+ # @param [Array] args
29
+ # @return [AWS::S3::S3Object]
30
+ #
31
+ def create(*args)
32
+ return bucket.objects.create(*args)
33
+ end
34
+
35
+ ##
36
+ # @return [AWS::S3.new]
37
+ #
38
+ def s3
39
+ return @s3 ||= AWS::S3.new
40
+ end
41
+
42
+ ##
43
+ # @return [AWS::S3::Bucket]
44
+ #
45
+ def bucket
46
+ return @bucket ||= s3.buckets[Daemons.output_bucket]
47
+ end
48
+ end # Uploader
49
+ end # Daemons
50
+ end # Opener
@@ -1,5 +1,5 @@
1
1
  module Opener
2
2
  module Daemons
3
- VERSION = "1.3.0"
4
- end
5
- end
3
+ VERSION = '2.0'
4
+ end # Daemons
5
+ end # Opener
@@ -0,0 +1,104 @@
1
+ module Opener
2
+ module Daemons
3
+ ##
4
+ # Downlods a KAF document, passes it to a component and submits the output
5
+ # to a callback URL or a default queue. Each Worker instance runs in an
6
+ # isolated thread
7
+ #
8
+ # @!attribute [r] config
9
+ # @return [Opener::Daemons::Configuration]
10
+ #
11
+ # @!attribute [r] uploader
12
+ # @return [Opener::Daemons::Uploader]
13
+ #
14
+ # @!attribute [r] downloader
15
+ # @return [Opener::Daemons::Downloader]
16
+ #
17
+ # @!attribute [r] callback_handler
18
+ # @return [Opener::CallbackHandler]
19
+ #
20
+ class Worker < Oni::Worker
21
+ attr_reader :config, :uploader, :downloader, :callback_handler
22
+
23
+ include NewRelic::Agent::Instrumentation::ControllerInstrumentation
24
+ include NewRelic::Agent::MethodTracer
25
+
26
+ ##
27
+ # @param [Opener::Daemons::Configuration] config
28
+ #
29
+ def initialize(config)
30
+ @config = config
31
+ @downloader = Downloader.new
32
+ @uploader = Uploader.new
33
+ @callback_handler = CallbackHandler.new
34
+ end
35
+
36
+ ##
37
+ # Processes a document.
38
+ #
39
+ # @raise [Oni::WrappedError]
40
+ #
41
+ def process
42
+ add_newrelic_attributes
43
+
44
+ input = downloader.download(config.input_url)
45
+ instance = config.component.new
46
+ output = instance.run(input)
47
+ object = uploader.upload(config.identifier, output, config.metadata)
48
+
49
+ Syslog.info(
50
+ "Wrote output to s3://#{Daemons.output_bucket}/#{object.key}",
51
+ config.metadata
52
+ )
53
+
54
+ submit_callbacks(object)
55
+
56
+ rescue Exception => error
57
+ raise Oni::WrappedError.from(
58
+ error,
59
+ :input_url => config.input_url,
60
+ :callbacks => config.callbacks,
61
+ :metadata => config.metadata
62
+ )
63
+ end
64
+
65
+ ##
66
+ # Sends the object's URL to the next callback URL.
67
+ #
68
+ # @param [AWS::S3::S3Object] object
69
+ #
70
+ def submit_callbacks(object)
71
+ urls = config.callbacks.dup
72
+ next_url = urls.shift
73
+ input_url = object.url_for(:read, :expires => 3600)
74
+
75
+ callback_handler.post(
76
+ next_url,
77
+ :input_url => input_url,
78
+ :identifier => config.identifier,
79
+ :callbacks => urls,
80
+ :metadata => config.metadata
81
+ )
82
+
83
+ Syslog.info("Submitted response to #{next_url}", config.metadata)
84
+ end
85
+
86
+ private
87
+
88
+ def add_newrelic_attributes
89
+ if Daemons.newrelic?
90
+ NewRelic::Agent.add_custom_attributes(
91
+ :input_url => config.input_url,
92
+ :callbacks => config.callbacks.join(', '),
93
+ :metadata => config.metadata
94
+ )
95
+ end
96
+ end
97
+
98
+ if Daemons.newrelic?
99
+ add_transaction_tracer(:process, :category => :task)
100
+ add_method_tracer(:download_input)
101
+ end
102
+ end # Worker
103
+ end # Daemons
104
+ end # Opener
@@ -1,16 +1,31 @@
1
- require "opener/daemons/version"
2
- require "opener/daemons/sqs"
3
- require "opener/daemons/s3"
4
- require "opener/daemons/daemon"
5
- require "opener/daemons/opt_parser"
6
- require "opener/daemons/controller"
1
+ # https://github.com/nahi/httpclient/issues/230
2
+ gem 'httpclient', '= 2.5.2'
3
+
4
+ require 'timeout'
5
+ require 'syslog'
6
+ require 'logger'
7
+ require 'securerandom'
8
+
9
+ require 'aws-sdk'
10
+ require 'httpclient'
11
+ require 'slop'
12
+ require 'oni'
13
+ require 'oni/daemons/sqs'
7
14
  require 'opener/callback_handler'
15
+ require 'new_relic/control'
16
+ require 'rollbar'
17
+ require 'json-schema'
8
18
 
9
- require "dotenv"
10
- env_file = File.expand_path("~/.opener-daemons-env")
11
- Dotenv.load(env_file)
19
+ require_relative 'daemons/version'
20
+ require_relative 'daemons/daemons'
21
+ require_relative 'daemons/option_parser'
22
+ require_relative 'daemons/controller'
23
+ require_relative 'daemons/pidfile'
24
+ require_relative 'daemons/configuration'
25
+ require_relative 'daemons/downloader'
26
+ require_relative 'daemons/uploader'
27
+ require_relative 'daemons/syslog'
12
28
 
13
- module Opener
14
- module Daemons
15
- end
16
- end
29
+ require_relative 'daemons/mapper'
30
+ require_relative 'daemons/worker'
31
+ require_relative 'daemons/daemon'
@@ -1,29 +1,36 @@
1
1
  require File.expand_path('../lib/opener/daemons/version', __FILE__)
2
2
 
3
3
  Gem::Specification.new do |spec|
4
- spec.name = "opener-daemons"
4
+ spec.name = 'opener-daemons'
5
5
  spec.version = Opener::Daemons::VERSION
6
- spec.authors = ["Wilco van Duinkerken"]
7
- spec.email = ["wilco@sparkboxx.com"]
8
- spec.summary = %q{Daemonize OpeNER components and make them read from an SQS queue. JRuby compatible.}
6
+ spec.authors = ['Wilco van Duinkerken', 'Olery']
7
+ spec.email = ['wilco@sparkboxx.com', 'development@olery.com']
8
+ spec.summary = 'Toolkit for turning OpeNER components into daemons'
9
9
  spec.description = spec.summary
10
- spec.homepage = "http://opener-project.github.io"
11
- spec.license = "Apache 2.0"
10
+ spec.homepage = 'http://opener-project.github.io'
11
+ spec.license = 'Apache 2.0'
12
+
13
+ spec.required_ruby_version = '>= 1.9.2'
12
14
 
13
15
  spec.files = Dir.glob([
14
16
  'lib/**/*',
15
17
  'LICENSE.txt',
16
18
  '*.gemspec',
17
19
  'README.md'
18
- ]).select { |file| File.basename(file) }
20
+ ]).select { |file| File.file?(file) }
21
+
22
+ spec.add_dependency 'aws-sdk', '~> 1.0'
23
+ spec.add_dependency 'slop', '~> 3.0'
24
+ spec.add_dependency 'opener-callback-handler'
25
+ spec.add_dependency 'newrelic_rpm'
26
+ spec.add_dependency 'json-schema'
27
+ spec.add_dependency 'rollbar', '~> 1.0'
28
+ spec.add_dependency 'oni', '~> 3.0'
19
29
 
20
- spec.add_dependency 'aws-sdk'
21
- spec.add_dependency 'spoon'
22
- spec.add_dependency 'dotenv'
23
- spec.add_dependency "opener-callback-handler"
24
- spec.add_dependency "httpclient"
30
+ # https://github.com/nahi/httpclient/issues/230
31
+ spec.add_dependency 'httpclient', '= 2.5.2'
25
32
 
26
- spec.add_development_dependency "bundler", "~> 1.5"
27
- spec.add_development_dependency "rake"
28
- spec.add_development_dependency "rspec"
33
+ spec.add_development_dependency 'bundler'
34
+ spec.add_development_dependency 'rake'
35
+ spec.add_development_dependency 'rspec'
29
36
  end
metadata CHANGED
@@ -1,166 +1,217 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opener-daemons
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: '2.0'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wilco van Duinkerken
8
- autorequire:
8
+ - Olery
9
+ autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-09-22 00:00:00.000000000 Z
12
+ date: 2014-11-17 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: aws-sdk
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.0'
21
+ type: :runtime
22
+ prerelease: false
15
23
  version_requirements: !ruby/object:Gem::Requirement
16
24
  requirements:
17
- - - '>='
25
+ - - "~>"
18
26
  - !ruby/object:Gem::Version
19
- version: '0'
27
+ version: '1.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: slop
20
30
  requirement: !ruby/object:Gem::Requirement
21
31
  requirements:
22
- - - '>='
32
+ - - "~>"
23
33
  - !ruby/object:Gem::Version
24
- version: '0'
25
- prerelease: false
34
+ version: '3.0'
26
35
  type: :runtime
27
- - !ruby/object:Gem::Dependency
28
- name: spoon
36
+ prerelease: false
29
37
  version_requirements: !ruby/object:Gem::Requirement
30
38
  requirements:
31
- - - '>='
39
+ - - "~>"
32
40
  - !ruby/object:Gem::Version
33
- version: '0'
41
+ version: '3.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: opener-callback-handler
34
44
  requirement: !ruby/object:Gem::Requirement
35
45
  requirements:
36
- - - '>='
46
+ - - ">="
37
47
  - !ruby/object:Gem::Version
38
48
  version: '0'
39
- prerelease: false
40
49
  type: :runtime
41
- - !ruby/object:Gem::Dependency
42
- name: dotenv
50
+ prerelease: false
43
51
  version_requirements: !ruby/object:Gem::Requirement
44
52
  requirements:
45
- - - '>='
53
+ - - ">="
46
54
  - !ruby/object:Gem::Version
47
55
  version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: newrelic_rpm
48
58
  requirement: !ruby/object:Gem::Requirement
49
59
  requirements:
50
- - - '>='
60
+ - - ">="
51
61
  - !ruby/object:Gem::Version
52
62
  version: '0'
53
- prerelease: false
54
63
  type: :runtime
55
- - !ruby/object:Gem::Dependency
56
- name: opener-callback-handler
64
+ prerelease: false
57
65
  version_requirements: !ruby/object:Gem::Requirement
58
66
  requirements:
59
- - - '>='
67
+ - - ">="
60
68
  - !ruby/object:Gem::Version
61
69
  version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: json-schema
62
72
  requirement: !ruby/object:Gem::Requirement
63
73
  requirements:
64
- - - '>='
74
+ - - ">="
65
75
  - !ruby/object:Gem::Version
66
76
  version: '0'
67
- prerelease: false
68
77
  type: :runtime
69
- - !ruby/object:Gem::Dependency
70
- name: httpclient
78
+ prerelease: false
71
79
  version_requirements: !ruby/object:Gem::Requirement
72
80
  requirements:
73
- - - '>='
81
+ - - ">="
74
82
  - !ruby/object:Gem::Version
75
83
  version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rollbar
76
86
  requirement: !ruby/object:Gem::Requirement
77
87
  requirements:
78
- - - '>='
88
+ - - "~>"
79
89
  - !ruby/object:Gem::Version
80
- version: '0'
81
- prerelease: false
90
+ version: '1.0'
82
91
  type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '1.0'
83
98
  - !ruby/object:Gem::Dependency
84
- name: bundler
99
+ name: oni
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '3.0'
105
+ type: :runtime
106
+ prerelease: false
85
107
  version_requirements: !ruby/object:Gem::Requirement
86
108
  requirements:
87
- - - ~>
109
+ - - "~>"
88
110
  - !ruby/object:Gem::Version
89
- version: '1.5'
111
+ version: '3.0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: httpclient
90
114
  requirement: !ruby/object:Gem::Requirement
91
115
  requirements:
92
- - - ~>
116
+ - - '='
93
117
  - !ruby/object:Gem::Version
94
- version: '1.5'
118
+ version: 2.5.2
119
+ type: :runtime
95
120
  prerelease: false
96
- type: :development
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '='
124
+ - !ruby/object:Gem::Version
125
+ version: 2.5.2
97
126
  - !ruby/object:Gem::Dependency
98
- name: rake
127
+ name: bundler
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
99
135
  version_requirements: !ruby/object:Gem::Requirement
100
136
  requirements:
101
- - - '>='
137
+ - - ">="
102
138
  - !ruby/object:Gem::Version
103
139
  version: '0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: rake
104
142
  requirement: !ruby/object:Gem::Requirement
105
143
  requirements:
106
- - - '>='
144
+ - - ">="
107
145
  - !ruby/object:Gem::Version
108
146
  version: '0'
109
- prerelease: false
110
147
  type: :development
111
- - !ruby/object:Gem::Dependency
112
- name: rspec
148
+ prerelease: false
113
149
  version_requirements: !ruby/object:Gem::Requirement
114
150
  requirements:
115
- - - '>='
151
+ - - ">="
116
152
  - !ruby/object:Gem::Version
117
153
  version: '0'
154
+ - !ruby/object:Gem::Dependency
155
+ name: rspec
118
156
  requirement: !ruby/object:Gem::Requirement
119
157
  requirements:
120
- - - '>='
158
+ - - ">="
121
159
  - !ruby/object:Gem::Version
122
160
  version: '0'
123
- prerelease: false
124
161
  type: :development
125
- description: Daemonize OpeNER components and make them read from an SQS queue. JRuby compatible.
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ description: Toolkit for turning OpeNER components into daemons
126
169
  email:
127
170
  - wilco@sparkboxx.com
171
+ - development@olery.com
128
172
  executables: []
129
173
  extensions: []
130
174
  extra_rdoc_files: []
131
175
  files:
176
+ - LICENSE.txt
177
+ - README.md
132
178
  - lib/opener/daemons.rb
179
+ - lib/opener/daemons/configuration.rb
133
180
  - lib/opener/daemons/controller.rb
134
181
  - lib/opener/daemons/daemon.rb
135
- - lib/opener/daemons/opt_parser.rb
136
- - lib/opener/daemons/s3.rb
137
- - lib/opener/daemons/sqs.rb
182
+ - lib/opener/daemons/daemons.rb
183
+ - lib/opener/daemons/downloader.rb
184
+ - lib/opener/daemons/mapper.rb
185
+ - lib/opener/daemons/option_parser.rb
186
+ - lib/opener/daemons/pidfile.rb
187
+ - lib/opener/daemons/syslog.rb
188
+ - lib/opener/daemons/uploader.rb
138
189
  - lib/opener/daemons/version.rb
139
- - LICENSE.txt
190
+ - lib/opener/daemons/worker.rb
140
191
  - opener-daemons.gemspec
141
- - README.md
142
192
  homepage: http://opener-project.github.io
143
193
  licenses:
144
194
  - Apache 2.0
145
195
  metadata: {}
146
- post_install_message:
196
+ post_install_message:
147
197
  rdoc_options: []
148
198
  require_paths:
149
199
  - lib
150
200
  required_ruby_version: !ruby/object:Gem::Requirement
151
201
  requirements:
152
- - - '>='
202
+ - - ">="
153
203
  - !ruby/object:Gem::Version
154
- version: '0'
204
+ version: 1.9.2
155
205
  required_rubygems_version: !ruby/object:Gem::Requirement
156
206
  requirements:
157
- - - '>='
207
+ - - ">="
158
208
  - !ruby/object:Gem::Version
159
209
  version: '0'
160
210
  requirements: []
161
- rubyforge_project:
162
- rubygems_version: 2.1.9
163
- signing_key:
211
+ rubyforge_project:
212
+ rubygems_version: 2.2.2
213
+ signing_key:
164
214
  specification_version: 4
165
- summary: Daemonize OpeNER components and make them read from an SQS queue. JRuby compatible.
215
+ summary: Toolkit for turning OpeNER components into daemons
166
216
  test_files: []
217
+ has_rdoc: