checker_jobs 0.1.2.pre → 1.0.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,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bd7238a9e052db0d3953584be6cf3d082ae6b171
4
- data.tar.gz: a4bf0b5505b76cbc4c23b195bdb9af6bc14c8f7d
2
+ SHA256:
3
+ metadata.gz: dff9e8e2b91b729928d02a856b2a1848afe909ed2c17a5ba39cded6f992e8087
4
+ data.tar.gz: 11ae8c80cb23614057e45fbdb70de548cb7dac6e9e3368564a586a0d247272e9
5
5
  SHA512:
6
- metadata.gz: fb9d91c1b2eacb5f86cc4304fdaf4bb7bee7f5addb90094e7f81df44fab5795f211f3e7891e654522313fd875ed0546951cd39cc0d2904ccf6f88c80113dcade
7
- data.tar.gz: '0586d068670200ddf86e62f848bf5ed636992eb4b6de358653183b8cad61e3c519ce31c741933c43077d9839fdf3bc98e7aa736fc02690293ec06a98cb335a8e'
6
+ metadata.gz: bf7ed95487af7d2d5df3a8c884d17a66fa90fef168a7c7c72b6551a595ae12c46765024117e54b02e821aadc0d1b0c79a566ff45472a4dc97181b7b503f0f0c4
7
+ data.tar.gz: 6754adfa0d2849ee8cabecd9e379489908f85d2a6bf349dbba75d3513645a0269f8f7e5848d375a4854b5fd93cd3b50c05c5e137d93a470099f9b4dd6a1dd02c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- checker_jobs (0.1.2.pre)
4
+ checker_jobs (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -41,7 +41,7 @@ GEM
41
41
  coderay (1.1.2)
42
42
  concurrent-ruby (1.0.5)
43
43
  connection_pool (2.2.1)
44
- crass (1.0.3)
44
+ crass (1.0.4)
45
45
  daemons (1.2.6)
46
46
  diff-lcs (1.3)
47
47
  docile (1.1.5)
@@ -109,16 +109,16 @@ GEM
109
109
  byebug (~> 9.1)
110
110
  pry (~> 0.10)
111
111
  public_suffix (3.0.1)
112
- rack (2.0.4)
113
- rack-protection (2.0.1)
112
+ rack (2.0.5)
113
+ rack-protection (2.0.3)
114
114
  rack
115
115
  rack-test (0.8.2)
116
116
  rack (>= 1.0, < 3)
117
117
  rails-dom-testing (2.0.3)
118
118
  activesupport (>= 4.2.0)
119
119
  nokogiri (>= 1.6)
120
- rails-html-sanitizer (1.0.3)
121
- loofah (~> 2.0)
120
+ rails-html-sanitizer (1.0.4)
121
+ loofah (~> 2.2, >= 2.2.2)
122
122
  rainbow (2.2.2)
123
123
  rake
124
124
  rake (10.5.0)
@@ -160,10 +160,10 @@ GEM
160
160
  json (>= 1.8, < 3)
161
161
  simplecov-html (~> 0.10.0)
162
162
  simplecov-html (0.10.2)
163
- sinatra (2.0.1)
163
+ sinatra (2.0.3)
164
164
  mustermann (~> 1.0)
165
165
  rack (~> 2.0)
166
- rack-protection (= 2.0.1)
166
+ rack-protection (= 2.0.3)
167
167
  tilt (~> 2.0)
168
168
  skinny (0.2.2)
169
169
  eventmachine (~> 1.0)
data/README.md CHANGED
@@ -41,7 +41,7 @@ class UsersChecker
41
41
 
42
42
  options sidekiq: { queue: :slow }
43
43
 
44
- notify "oss@drivy.com"
44
+ notify :email, to: "oss@drivy.com"
45
45
 
46
46
  ensure_no :negative_rental_credit do
47
47
  # The following code is an over-simplification
@@ -74,26 +74,30 @@ gem 'checker_jobs'
74
74
 
75
75
  ## Usage
76
76
 
77
- Have a look at the `examples` directory of the repository to get a clearer idea
78
- about how to use and the gem is offering.
77
+ Have a look at the examples directory of the repository to get a clearer idea about how to use and the gem is offering.
79
78
 
80
79
  ### Configure
81
80
 
82
- At the moment this gems supports [Drivy][gh-drivy]'s stack which includes
83
- [Sidekiq][gh-sidekiq] and [Rails][rails]. It has been designed to supports more
84
- than Sidekiq a job processor and more that ActionMailer as a notification
85
- gateway. If you're on the same stack as we are, configuration looks like this:
86
-
87
81
  ``` ruby
88
82
  require "checker_jobs"
89
83
 
90
- CheckerJobs.configure do |config|
91
- config.repository_url = { github: "drivy/checker_jobs" }
84
+ CheckerJobs.configure do |c|
85
+ c.jobs_processor = :sidekiq
86
+
87
+ c.notifier :email do |options|
88
+ options[:formatter_class] = CheckerJobs::Notifiers::EmailDefaultFormatter
89
+ options[:email_options] = {
90
+ from: "oss@drivy.com",
91
+ reply_to: "no-reply@drivy.com",
92
+ }
93
+ end
92
94
 
93
- config.jobs_processor = :sidekiq
95
+ c.notifier :logger do |options|
96
+ options[:logdev] = STDOUT
97
+ options[:level] = Logger::INFO
98
+ end
94
99
 
95
- config.emails_backend = :action_mailer
96
- config.emails_options = { from: "oss@drivy.com", reply_to: "no-reply@drivy.com" }
100
+ c.repository_url = { github: "drivy/checker_jobs" }
97
101
  end
98
102
 
99
103
  ```
@@ -105,6 +109,21 @@ are already configured.
105
109
  If you're on a different stack and you'll like to add a new job processor or
106
110
  notification backend in this gem, [drop us a line][d-jobs].
107
111
 
112
+ ### Job Processor
113
+
114
+ At the moment, only [Sidekiq][gh-sidekiq] is supported as a job processor to asynchronously check for data inconsitencies.
115
+ The gem is designed to supports more processor.
116
+ PRs are appreciated 🙏
117
+
118
+ ### Notifiers
119
+
120
+ We support different kind of notifiers, as of today we have the following:
121
+
122
+ - `:email`: uses `ActionMailer` to send emails. You can pass it any `ActionMailer` options.
123
+ - `:logger`: Uses `Logger` to output inconsitencies in the log. Takes the following params:
124
+ - `logdev`: The log device. This is a filename (String) or IO object (typically STDOUT, STDERR, or an open file).
125
+ - `level`: Logging severity threshold (e.g. Logger::INFO)
126
+
108
127
  ### Write checkers
109
128
 
110
129
  A checker is a class that inherits `CheckerJobs::Base` and uses the
@@ -116,7 +135,7 @@ class UserChecker
116
135
 
117
136
  options sidekiq: { queue: :fast }
118
137
 
119
- notify "tech@drivy.com"
138
+ notify :email, to: "oss@drivy.com"
120
139
 
121
140
  ensure_no :user_without_email do
122
141
  UserRepository.missing_email.size
@@ -128,7 +147,7 @@ The `UserChecker` will have the same interface as your usual jobs. In this
128
147
  example, `UserChecker` will be a `Sidekiq::Worker`. Its `#perform` method will
129
148
  run the check named `:user_without_email` and if
130
149
  `UserRepository.missing_email.size` is greater than 0 then an email will be
131
- fired through ActionMailer to `tech@drivy.com`.
150
+ fired through ActionMailer to `oss@drivy.com`.
132
151
 
133
152
  ### Schedule checks
134
153
 
@@ -150,10 +169,3 @@ You'll find out that the CI is setup to run test coverage and linting.
150
169
  ## License
151
170
 
152
171
  The gem is available as open source under the terms of the [MIT License][licence].
153
-
154
-
155
- [d-jobs]: https://www.drivy.com/jobs
156
- [gh-drivy]: https://github.com/drivy
157
- [gh-sidekiq]: https://github.com/mperham/sidekiq
158
- [licence]: http://opensource.org/licenses/MIT
159
- [rails]: http://rubyonrails.org
data/checker_jobs.gemspec CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ["Drivy", "Nicolas Zermati"]
9
9
  spec.email = ["oss@drivy.com"]
10
10
 
11
- spec.summary = "Asynchronous data consistency checks"
11
+ spec.summary = "Regression tests for data"
12
12
  spec.description = ""
13
13
  spec.homepage = "https://github.com/drivy/checker_jobs"
14
14
  spec.license = "MIT"
@@ -21,8 +21,13 @@ CheckerJobs.configure do |config|
21
21
 
22
22
  config.jobs_processor = :sidekiq
23
23
 
24
- config.emails_backend = :action_mailer
25
- config.emails_options = { from: "oss@drivy.com", reply_to: "no-reply@drivy.com" }
24
+ config.notifier :email do |options|
25
+ options[:formatter_class] = CheckerJobs::Notifiers::EmailDefaultFormatter
26
+ options[:email_options] = {
27
+ from: "oss@drivy.com",
28
+ reply_to: "no-reply@drivy.com",
29
+ }
30
+ end
26
31
 
27
32
  config.around_check = -> {
28
33
  puts "Starting check #{check.name}..."
@@ -40,7 +45,7 @@ class UserChecker
40
45
 
41
46
  options sidekiq: { queue: :fast }
42
47
 
43
- notify "tech@drivy.com"
48
+ notify :email, to: "tech@drivy.com"
44
49
 
45
50
  ensure_no :inconsistent_payment do
46
51
  UserRepository.missing_email.size
@@ -10,9 +10,8 @@ CheckerJobs::Checks::Base = Struct.new(:klass, :name, :options, :block) do
10
10
  private
11
11
 
12
12
  def notify(count:, entries: nil)
13
- CheckerJobs.configuration.emails_backend_class.
14
- new(self, count, entries).
15
- notify
13
+ notifier_class = CheckerJobs.configuration.notifier_class(klass.notifier)
14
+ notifier_class.new(self, count, entries).notify
16
15
  end
17
16
 
18
17
  def handle_result(_result)
@@ -4,23 +4,31 @@ require "checker_jobs/jobs_processors"
4
4
  class CheckerJobs::Configuration
5
5
  DEFAULT_TIME_BETWEEN_CHECKS = 15 * 60 # 15 minutes, expressed in seconds
6
6
 
7
+ NOTIFIER_CLASSES = {
8
+ email: "CheckerJobs::Notifiers::Email",
9
+ logger: "CheckerJobs::Notifiers::Logger",
10
+ }.freeze
11
+
7
12
  attr_accessor :jobs_processor,
8
- :emails_backend,
9
- :emails_options,
10
- :emails_formatter_class,
13
+ :notifiers_options,
11
14
  :time_between_checks,
12
15
  :repository_url,
13
16
  :around_check
14
17
 
15
18
  def self.default
16
19
  new.tap do |config|
17
- config.emails_options = {}
18
- config.emails_formatter_class = CheckerJobs::EmailsBackends::DefaultFormatter
20
+ config.notifiers_options = {}
19
21
  config.time_between_checks = DEFAULT_TIME_BETWEEN_CHECKS
20
22
  config.around_check = ->(&block) { block.call }
21
23
  end
22
24
  end
23
25
 
26
+ def notifier(notifier_symbol)
27
+ options = {}
28
+ yield(options)
29
+ @notifiers_options[notifier_symbol] = options
30
+ end
31
+
24
32
  def jobs_processor_module
25
33
  case jobs_processor
26
34
  when :sidekiq
@@ -30,12 +38,10 @@ class CheckerJobs::Configuration
30
38
  end
31
39
  end
32
40
 
33
- def emails_backend_class
34
- case emails_backend
35
- when :action_mailer
36
- CheckerJobs::EmailsBackends::ActionMailer
37
- else
38
- raise CheckerJobs::UnsupportedConfigurationOption.new(:emails_backend, emails_backend)
41
+ def notifier_class(notifier)
42
+ notifier_class_name = NOTIFIER_CLASSES.fetch(notifier) do
43
+ raise CheckerJobs::UnsupportedConfigurationOption.new(:notifier, notifier)
39
44
  end
45
+ Object.const_get(notifier_class_name)
40
46
  end
41
47
  end
@@ -16,8 +16,9 @@ module CheckerJobs::DSL
16
16
  @options = options_hash
17
17
  end
18
18
 
19
- def notify(target)
20
- @notification_target = target
19
+ def notify(notifier, notifier_options = {})
20
+ @notifier = notifier
21
+ @notifier_options = notifier_options
21
22
  end
22
23
 
23
24
  def interval(duration)
@@ -40,10 +41,14 @@ module CheckerJobs::DSL
40
41
  # Private API
41
42
  #
42
43
 
43
- def notification_target
44
- raise CheckerJobs::MissingNotificationTarget, self.class unless defined?(@notification_target)
44
+ def notifier
45
+ raise CheckerJobs::MissingNotifier, self.class unless defined?(@notifier)
46
+ @notifier
47
+ end
45
48
 
46
- @notification_target
49
+ def notifier_options
50
+ raise CheckerJobs::MissingNotifier, self.class unless defined?(@notifier)
51
+ @notifier_options
47
52
  end
48
53
 
49
54
  def time_between_checks
@@ -1,4 +1,5 @@
1
- module CheckerJobs::EmailsBackends
2
- autoload :ActionMailer, "checker_jobs/emails_backends/action_mailer"
3
- autoload :DefaultFormatter, "checker_jobs/emails_backends/default_formatter"
1
+ module CheckerJobs::Notifiers
2
+ autoload :Email, "checker_jobs/notifiers/email"
3
+ autoload :EmailDefaultFormatter, "checker_jobs/notifiers/email_default_formatter"
4
+ autoload :Logger, "checker_jobs/notifiers/logger"
4
5
  end
@@ -2,7 +2,10 @@ module CheckerJobs
2
2
  class Error < StandardError
3
3
  end
4
4
 
5
- class MissingNotificationTarget < Error
5
+ class MissingNotifier < Error
6
+ end
7
+
8
+ class InvalidNotifierOptions < Error
6
9
  end
7
10
 
8
11
  class Unconfigured < Error
@@ -1,9 +1,12 @@
1
1
  require "action_mailer"
2
2
 
3
- class CheckerJobs::EmailsBackends::ActionMailer
3
+ class CheckerJobs::Notifiers::Email
4
4
  def initialize(check, count, entries)
5
5
  @check = check
6
6
  @formatter = formatter_class.new(check, count, entries)
7
+ @defaults = { subject: @formatter.subject }
8
+
9
+ raise CheckerJobs::InvalidNotifierOptions unless valid?
7
10
  end
8
11
 
9
12
  def notify
@@ -12,15 +15,22 @@ class CheckerJobs::EmailsBackends::ActionMailer
12
15
 
13
16
  private
14
17
 
18
+ def valid?
19
+ options[:to].is_a?(String)
20
+ end
21
+
15
22
  def options
16
- CheckerJobs.configuration.emails_options.merge({
17
- to: @check.klass.notification_target,
18
- subject: @formatter.subject,
19
- })
23
+ @options ||= @defaults.
24
+ merge(notifier_options[:email_options]).
25
+ merge(@check.klass.notifier_options)
20
26
  end
21
27
 
22
28
  def formatter_class
23
- CheckerJobs.configuration.emails_formatter_class
29
+ notifier_options[:formatter_class] || CheckerJobs::Notifiers::EmailDefaultFormatter
30
+ end
31
+
32
+ def notifier_options
33
+ CheckerJobs.configuration.notifiers_options[@check.klass.notifier]
24
34
  end
25
35
 
26
36
  # Simple mailer class based on ActionMailer to send HTML emails while reusing
@@ -1,4 +1,4 @@
1
- class CheckerJobs::EmailsBackends::DefaultFormatter
1
+ class CheckerJobs::Notifiers::EmailDefaultFormatter
2
2
  def initialize(check, count, entries)
3
3
  @check = check
4
4
  @count = count
@@ -0,0 +1,51 @@
1
+ require "logger"
2
+
3
+ class CheckerJobs::Notifiers::Logger
4
+ DEFAULT_LEVEL = Logger::INFO
5
+ DEFAULT_LOGDEV = STDOUT
6
+
7
+ def initialize(check, count, entries)
8
+ @check = check
9
+ @count = count
10
+ @entries = entries
11
+ raise CheckerJobs::InvalidNotifierOptions unless valid?
12
+
13
+ @logger = Logger.new(logdev)
14
+ @logger.level = level
15
+ end
16
+
17
+ def notify
18
+ @logger.add(level, format, @check.name.tr("_", " ").capitalize)
19
+ end
20
+
21
+ # override this
22
+ def format
23
+ "found #{@count} entries"
24
+ end
25
+
26
+ private
27
+
28
+ def valid?
29
+ (logdev.is_a?(String) || logdev.is_a?(IO)) &&
30
+ [
31
+ Logger::UNKNOWN, Logger::FATAL, Logger::ERROR,
32
+ Logger::WARN, Logger::INFO, Logger::DEBUG
33
+ ].include?(level)
34
+ end
35
+
36
+ def level
37
+ @level ||= @check.klass.notifier_options[:level] ||
38
+ notifier_options[:level] ||
39
+ DEFAULT_LEVEL
40
+ end
41
+
42
+ def logdev
43
+ @logdev ||= @check.klass.notifier_options[:logdev] ||
44
+ notifier_options[:logdev] ||
45
+ DEFAULT_LOGDEV
46
+ end
47
+
48
+ def notifier_options
49
+ CheckerJobs.configuration.notifiers_options[@check.klass.notifier]
50
+ end
51
+ end
@@ -1,3 +1,3 @@
1
1
  module CheckerJobs
2
- VERSION = "0.1.2.pre".freeze
2
+ VERSION = "1.0.0".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: checker_jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2.pre
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Drivy
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-04-03 00:00:00.000000000 Z
12
+ date: 2018-07-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionmailer
@@ -210,11 +210,12 @@ files:
210
210
  - lib/checker_jobs/configuration.rb
211
211
  - lib/checker_jobs/dsl.rb
212
212
  - lib/checker_jobs/emails_backends.rb
213
- - lib/checker_jobs/emails_backends/action_mailer.rb
214
- - lib/checker_jobs/emails_backends/default_formatter.rb
215
213
  - lib/checker_jobs/errors.rb
216
214
  - lib/checker_jobs/jobs_processors.rb
217
215
  - lib/checker_jobs/jobs_processors/sidekiq.rb
216
+ - lib/checker_jobs/notifiers/email.rb
217
+ - lib/checker_jobs/notifiers/email_default_formatter.rb
218
+ - lib/checker_jobs/notifiers/logger.rb
218
219
  - lib/checker_jobs/version.rb
219
220
  homepage: https://github.com/drivy/checker_jobs
220
221
  licenses:
@@ -231,13 +232,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
231
232
  version: '0'
232
233
  required_rubygems_version: !ruby/object:Gem::Requirement
233
234
  requirements:
234
- - - ">"
235
+ - - ">="
235
236
  - !ruby/object:Gem::Version
236
- version: 1.3.1
237
+ version: '0'
237
238
  requirements: []
238
239
  rubyforge_project:
239
- rubygems_version: 2.6.14
240
+ rubygems_version: 2.7.6
240
241
  signing_key:
241
242
  specification_version: 4
242
- summary: Asynchronous data consistency checks
243
+ summary: Regression tests for data
243
244
  test_files: []