parallel_minion 1.2.1 → 1.4.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: ec80ef2321aa78ba6f8b6dc7b16452f1ccb15a9b
4
- data.tar.gz: f3a394698da183ce6e64c8137ac7cf50cae98943
2
+ SHA256:
3
+ metadata.gz: 8ee831ee7f2939c246ff997e0abbdeca9f2779a4faa21d68d1cd6d4e27c09b52
4
+ data.tar.gz: e681733d3cbd2e9da49a0552e070a9fa52be776208d2bbfa02943752fd3b6a53
5
5
  SHA512:
6
- metadata.gz: 946b4306251796613bf5a44b89d32016aa0a9133048caaaa698206151aeb5e9dc4684e377230d767b2fb8bcc2f952a83c18c140f96bcb7e5c44fdee10f88c16c
7
- data.tar.gz: 1f52084ea14e186ff3796f8276fbc879bb99ada6d0b05fead4513b26a4611a471064c2ebbbc0cdb27ced7e1e9a41135674083436b2737108a54b921f640fb1fc
6
+ metadata.gz: aa0986ec9d4c9c8713f9a19a37ba32739af5c184fd558e1ce9860a2b38de5caf6ccb8aa1a933fb4969f9ca94224a21386fd608551b6d582d0e2418976b9c26c6
7
+ data.tar.gz: 8d7b3ca45414d9154311fed2fa3d7ab487f201224532e07304c1f8965265d0d8bb96a44da10aa4b82b940869df0c60c3e91e1fbd43390f0595cc91a6aef716e8
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
- parallel_minion [![Build Status](https://secure.travis-ci.org/reidmorrison/parallel_minion.png?branch=master)](http://travis-ci.org/reidmorrison/parallel_minion)
2
- ===============
1
+ # Parallel Minion
2
+ [![Gem Version](https://img.shields.io/gem/v/parallel_minion.svg)](https://rubygems.org/gems/parallel_minion) [![Build Status](https://github.com/reidmorrison/parallel_minion/workflows/build/badge.svg)](https://github.com/reidmorrison/parallel_minion/actions?query=workflow%3Abuild) [![Downloads](https://img.shields.io/gem/dt/parallel_minion.svg)](https://rubygems.org/gems/parallel_minion) [![License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](http://opensource.org/licenses/Apache-2.0) ![](https://img.shields.io/badge/status-Production%20Ready-blue.svg)
3
3
 
4
- Pragmatic approach to parallel processing in Ruby
4
+ Wrap Ruby code with a minion so that it is run on a parallel thread.
5
5
 
6
6
  ## Description
7
7
 
@@ -46,12 +46,20 @@ has been achieved by moving existing blocks of code into Minions.
46
46
 
47
47
  gem install parallel_minion
48
48
 
49
+ ## Rails 7.2 compatibility
50
+
51
+ - **Apps** need **Ruby ≥ 3.1** (Rails 7.2 requirement).
52
+ - **Code:** Thread cleanup uses `ActiveRecord::Base.connection_handler.clear_active_connections!` instead of `ActiveRecord::Base.clear_active_connections!` because Rails 7 deprecates the latter.
53
+ - **Railtie:** Unchanged (`config.parallel_minion` as before).
54
+ - **CI:** `rails_7.2` Appraisal `gemfiles/rails_7.2.gemfile`, Ruby 3.2. The 7.2 appraisal pins **Minitest ~> 5.0** (tests use `stub`, removed in Minitest 6).
55
+ - **sqlite3 (dev):** The 7.2 appraisal allows `sqlite3 >= 1.4` (including 2.x). Other gemfiles use `sqlite3 >= 1.5, < 2` to skip **1.4.4**, which often fails to compile on modern toolchains (all OSes).
56
+
49
57
  ## Meta
50
58
 
51
59
  * Code: `git clone git://github.com/reidmorrison/parallel_minion.git`
52
60
  * Home: <https://github.com/reidmorrison/parallel_minion>
53
61
  * Bugs: <http://github.com/reidmorrison/parallel_minion/issues>
54
- * Gems: <http://rubygems.org/gems/parallel_minion>
62
+ * Gems: <https://rubygems.org/gems/parallel_minion>
55
63
 
56
64
  This project uses [Semantic Versioning](http://semver.org/).
57
65
 
data/Rakefile CHANGED
@@ -1,30 +1,30 @@
1
1
  # Setup bundler to avoid having to run bundle exec all the time.
2
- require 'rubygems'
3
- require 'bundler/setup'
2
+ require "rubygems"
3
+ require "bundler/setup"
4
4
 
5
- require 'rake/testtask'
6
- require_relative 'lib/parallel_minion/version'
5
+ require "rake/testtask"
6
+ require_relative "lib/parallel_minion/version"
7
7
 
8
8
  task :gem do
9
- system 'gem build parallel_minion.gemspec'
9
+ system "gem build parallel_minion.gemspec"
10
10
  end
11
11
 
12
- task :publish => :gem do
13
- system "git tag -a v#{ParallelMinion::VERSION} -m 'Tagging #{ParallelMinion::VERSION}'"
14
- system 'git push --tags'
12
+ task publish: :gem do
13
+ # system "git tag -a v#{ParallelMinion::VERSION} -m 'Tagging #{ParallelMinion::VERSION}'"
14
+ # system "git push --tags"
15
15
  system "gem push parallel_minion-#{ParallelMinion::VERSION}.gem"
16
16
  system "rm parallel_minion-#{ParallelMinion::VERSION}.gem"
17
17
  end
18
18
 
19
19
  Rake::TestTask.new(:test) do |t|
20
- t.pattern = 'test/**/*_test.rb'
20
+ t.pattern = "test/**/*_test.rb"
21
21
  t.verbose = true
22
22
  t.warning = false
23
23
  end
24
24
 
25
25
  # By default run tests against all appraisals
26
26
  if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
27
- require 'appraisal'
27
+ require "appraisal"
28
28
  task default: :appraisal
29
29
  else
30
30
  task default: :test
@@ -22,7 +22,7 @@ module ParallelMinion
22
22
  # Metrics [String]
23
23
  attr_reader :metric, :wait_metric
24
24
 
25
- attr_reader :on_timeout, :log_exception, :start_time
25
+ attr_reader :on_timeout, :log_exception, :start_time, :on_exception_level
26
26
 
27
27
  # Give an infinite amount of time to wait for a Minion to complete a task
28
28
  INFINITE = 0
@@ -40,8 +40,8 @@ module ParallelMinion
40
40
  # - Production:
41
41
  # Batch processing in Rocket Job where throughput is more important than latency.
42
42
  # http://rocketjob.io
43
- def self.enabled=(enabled)
44
- @enabled = enabled
43
+ class << self
44
+ attr_writer :enabled
45
45
  end
46
46
 
47
47
  # Returns whether minions are enabled to run in their own threads
@@ -54,8 +54,8 @@ module ParallelMinion
54
54
  #
55
55
  # Example:
56
56
  # ...
57
- def self.scoped_classes
58
- @scoped_classes
57
+ class << self
58
+ attr_reader :scoped_classes
59
59
  end
60
60
 
61
61
  def self.scoped_classes=(scoped_classes)
@@ -70,11 +70,12 @@ module ParallelMinion
70
70
  # :trace, :debug, :info, :warn, :error, :fatal
71
71
  def self.started_log_level=(level)
72
72
  raise(ArgumentError, "Invalid log level: #{level}") unless SemanticLogger::LEVELS.include?(level)
73
+
73
74
  @started_log_level = level
74
75
  end
75
76
 
76
- def self.started_log_level
77
- @started_log_level
77
+ class << self
78
+ attr_reader :started_log_level
78
79
  end
79
80
 
80
81
  # Change the log level for the Completed log message.
@@ -85,18 +86,18 @@ module ParallelMinion
85
86
  # :trace, :debug, :info, :warn, :error, :fatal
86
87
  def self.completed_log_level=(level)
87
88
  raise(ArgumentError, "Invalid log level: #{level}") unless SemanticLogger::LEVELS.include?(level)
89
+
88
90
  @completed_log_level = level
89
91
  end
90
92
 
91
- def self.completed_log_level
92
- @completed_log_level
93
+ class << self
94
+ attr_reader :completed_log_level
93
95
  end
94
96
 
95
97
  self.started_log_level = :info
96
98
  self.completed_log_level = :info
97
99
  self.enabled = true
98
100
  self.scoped_classes = []
99
- logger.name = 'Minion'
100
101
 
101
102
  # Create a new Minion
102
103
  #
@@ -177,6 +178,10 @@ module ParallelMinion
177
178
  # Any unhandled exception raised in the block will not be logged
178
179
  # Default: :partial
179
180
  #
181
+ # :on_exception_level [:trace | :debug | :info | :warn | :error | :fatal]
182
+ # Override the log level only when an exception occurs.
183
+ # Default: ParallelMinion::Minion.completed_log_level
184
+ #
180
185
  # :enabled [Boolean]
181
186
  # Override the global setting: `ParallelMinion::Minion.enabled?` for this minion instance.
182
187
  #
@@ -193,25 +198,54 @@ module ParallelMinion
193
198
  # thread.pool.enabled=true
194
199
  #
195
200
  # Example:
196
- # ParallelMinion::Minion.new(10.days.ago, description: 'Doing something else in parallel', timeout: 1000) do |date|
201
+ # ParallelMinion::Minion.new(
202
+ # 10.days.ago,
203
+ # description: 'Doing something else in parallel',
204
+ # timeout: 1000
205
+ # ) do |date|
197
206
  # MyTable.where('created_at <= ?', date).count
198
207
  # end
199
- def initialize(*arguments, description: 'Minion', metric: nil, log_exception: nil, enabled: self.class.enabled?, timeout: INFINITE, on_timeout: nil, wait_metric: nil, &block)
200
- raise 'Missing mandatory block that Minion must perform' unless block
201
- @start_time = Time.now
202
- @exception = nil
203
- @arguments = arguments
204
- @timeout = timeout.to_f
205
- @description = description.to_s
206
- @metric = metric
207
- @log_exception = log_exception
208
- @enabled = enabled
209
- @on_timeout = on_timeout
210
-
211
- @wait_metric = (wait_metric || "#{metric}/wait") if @metric
212
-
213
- # When minion is disabled it is obvious in the logs since the name will now be 'Inline' instead of 'Minion'
214
- self.logger = SemanticLogger['Inline'] unless @enabled
208
+ #
209
+ # Example, when the result is being ignored, log full exception as an error:
210
+ # ParallelMinion::Minion.new(
211
+ # customer,
212
+ # description: "We don't care about the result",
213
+ # log_exception: :full,
214
+ # on_exception_level: :error
215
+ # ) do |customer|
216
+ # customer.save!
217
+ # end
218
+ def initialize(*arguments,
219
+ description: "Minion",
220
+ metric: nil,
221
+ log_exception: nil,
222
+ on_exception_level: self.class.completed_log_level,
223
+ enabled: self.class.enabled?,
224
+ timeout: INFINITE,
225
+ on_timeout: nil,
226
+ wait_metric: nil,
227
+ &block)
228
+ raise "Missing mandatory block that Minion must perform" unless block
229
+
230
+ @start_time = Time.now
231
+ @exception = nil
232
+ @arguments = arguments
233
+ @timeout = timeout.to_f
234
+ @description = description.to_s
235
+ @metric = metric
236
+ @log_exception = log_exception
237
+ @on_exception_level = on_exception_level
238
+ @enabled = enabled
239
+ @on_timeout = on_timeout
240
+
241
+ @wait_metric = (wait_metric || "#{metric}/wait") if @metric
242
+
243
+ # When minion is disabled make it obvious in the logs by setting the name to 'Inline' instead of 'Minion'.
244
+ unless @enabled
245
+ l = self.class.logger.dup
246
+ l.name = "Inline"
247
+ self.logger = l
248
+ end
215
249
 
216
250
  @enabled ? run(&block) : run_inline(&block)
217
251
  end
@@ -225,7 +259,12 @@ module ParallelMinion
225
259
  # Return nil if Minion is still working and has time left to finish
226
260
  if working?
227
261
  ms = time_left
228
- logger.measure(self.class.completed_log_level, "Waited for Minion to complete: #{description}", min_duration: 0.01, metric: wait_metric) do
262
+ logger.measure(
263
+ self.class.completed_log_level,
264
+ "Waited for Minion to complete: #{description}",
265
+ min_duration: 0.01,
266
+ metric: wait_metric
267
+ ) do
229
268
  if @thread.join(ms.nil? ? nil : ms / 1000).nil?
230
269
  @thread.raise(@on_timeout.new("Minion: #{description} timed out")) if @on_timeout
231
270
  logger.warn("Timed out waiting for: #{description}")
@@ -257,8 +296,9 @@ module ParallelMinion
257
296
  # Returns 0 if no time is left
258
297
  # Returns nil if their is no time limit. I.e. :timeout was set to Minion::INFINITE (infinite time left)
259
298
  def time_left
260
- return nil if (timeout == 0) || (timeout == -1)
261
- duration = timeout - (Time.now - start_time) * 1000
299
+ return nil if timeout.zero? || (timeout == -1)
300
+
301
+ duration = timeout - ((Time.now - start_time) * 1000)
262
302
  duration <= 0 ? 0 : duration
263
303
  end
264
304
 
@@ -272,32 +312,40 @@ module ParallelMinion
272
312
  if defined?(ActiveRecord)
273
313
  if ActiveRecord::VERSION::MAJOR >= 4
274
314
  def self.current_scopes
275
- scoped_classes.collect { |klass| klass.all }
315
+ scoped_classes.collect(&:all)
276
316
  end
277
317
  else
278
318
  def self.current_scopes
279
- scoped_classes.collect { |klass| klass.scoped }
319
+ scoped_classes.collect(&:scoped)
280
320
  end
281
321
  end
282
322
  end
283
323
 
284
324
  private
285
325
 
326
+ # rubocop:disable Lint/RescueException
327
+
286
328
  # Run the supplied block of code in the current thread.
287
329
  # Useful for debugging, testing, and when running in batch environments.
288
330
  def run_inline(&block)
289
- begin
290
- logger.public_send(self.class.started_log_level, "Started #{@description}")
291
- logger.measure(self.class.completed_log_level, "Completed #{@description}", log_exception: @log_exception, metric: metric) do
292
- @result = instance_exec(*arguments, &block)
293
- end
294
- rescue Exception => exc
295
- @exception = exc
296
- ensure
297
- @duration = Time.now - start_time
331
+ logger.public_send(self.class.started_log_level, "Started #{description}")
332
+ logger.measure(
333
+ self.class.completed_log_level,
334
+ "Completed #{description}",
335
+ log_exception: log_exception,
336
+ on_exception_level: on_exception_level,
337
+ metric: metric
338
+ ) do
339
+ @result = instance_exec(*arguments, &block)
298
340
  end
341
+ rescue Exception => e
342
+ @exception = e
343
+ ensure
344
+ @duration = Time.now - start_time
299
345
  end
300
346
 
347
+ # rubocop:enable Lint/RescueException
348
+
301
349
  def run(&block)
302
350
  # Capture tags from current thread
303
351
  tags = SemanticLogger.tags
@@ -316,17 +364,26 @@ module ParallelMinion
316
364
  SemanticLogger.tagged(*tags) do
317
365
  SemanticLogger.named_tagged(named_tags) do
318
366
  logger.public_send(self.class.started_log_level, "Started #{description}")
367
+ # rubocop:disable Lint/RescueException
319
368
  begin
320
- proc = Proc.new { run_in_scope(scopes, &block) }
321
- logger.measure(self.class.completed_log_level, "Completed #{description}", log_exception: log_exception, metric: metric, &proc)
322
- rescue Exception => exc
323
- @exception = exc
369
+ proc = proc { run_in_scope(scopes, &block) }
370
+ logger.measure(
371
+ self.class.completed_log_level,
372
+ "Completed #{description}",
373
+ log_exception: log_exception,
374
+ on_exception_level: on_exception_level,
375
+ metric: metric,
376
+ &proc
377
+ )
378
+ rescue Exception => e
379
+ @exception = e
324
380
  nil
325
381
  ensure
326
382
  @duration = Time.now - start_time
327
383
  # Return any database connections used by this thread back to the pool
328
- ActiveRecord::Base.clear_active_connections! if defined?(ActiveRecord::Base)
384
+ ActiveRecord::Base.connection_handler.clear_active_connections! if defined?(ActiveRecord::Base)
329
385
  end
386
+ # rubocop:enable Lint/RescueException
330
387
  end
331
388
  end
332
389
  end
@@ -338,12 +395,11 @@ module ParallelMinion
338
395
  else
339
396
  # Use the captured scope when running the block.
340
397
  # Each Class to scope requires passing a block to .scoping.
341
- proc = Proc.new { instance_exec(*@arguments, &block) }
398
+ proc = proc { instance_exec(*@arguments, &block) }
342
399
  first = scopes.shift
343
- scopes.each { |scope| proc = Proc.new { scope.scoping(&proc) } }
400
+ scopes.each { |scope| proc = proc { scope.scoping(&proc) } }
344
401
  @result = first.scoping(&proc)
345
402
  end
346
403
  end
347
-
348
404
  end
349
405
  end
@@ -1,5 +1,5 @@
1
- module ParallelMinion #:nodoc:
2
- class Railtie < Rails::Railtie #:nodoc:
1
+ module ParallelMinion # :nodoc:
2
+ class Railtie < Rails::Railtie # :nodoc:
3
3
  #
4
4
  # Make the ParallelMinion config available in the Rails application config
5
5
  #
@@ -26,6 +26,5 @@ module ParallelMinion #:nodoc:
26
26
  # end
27
27
  # end
28
28
  config.parallel_minion = ::ParallelMinion::Minion
29
-
30
29
  end
31
30
  end
@@ -1,3 +1,3 @@
1
- module ParallelMinion #:nodoc
2
- VERSION = '1.2.1'
1
+ module ParallelMinion
2
+ VERSION = "1.4.0".freeze
3
3
  end
@@ -1,8 +1,7 @@
1
- require 'thread'
2
- require 'semantic_logger'
1
+ require "semantic_logger"
3
2
 
4
3
  module ParallelMinion
5
- autoload :Minion, 'parallel_minion/minion'
4
+ autoload :Minion, "parallel_minion/minion"
6
5
  end
7
6
 
8
- require 'parallel_minion/railtie' if defined?(Rails)
7
+ require "parallel_minion/railtie" if defined?(Rails)
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallel_minion
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reid Morrison
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2017-05-10 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: semantic_logger
@@ -24,10 +23,6 @@ dependencies:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
25
  version: '4.0'
27
- description: Parallel Minion allows you to take existing blocks of code and wrap them
28
- in a minion so that they can run asynchronously in a separate thread
29
- email:
30
- - reidmo@gmail.com
31
26
  executables: []
32
27
  extensions: []
33
28
  extra_rdoc_files: []
@@ -39,16 +34,11 @@ files:
39
34
  - lib/parallel_minion/minion.rb
40
35
  - lib/parallel_minion/railtie.rb
41
36
  - lib/parallel_minion/version.rb
42
- - test/config/database.yml
43
- - test/minion_scope_test.rb
44
- - test/minion_test.rb
45
- - test/test_db.sqlite3
46
- - test/test_helper.rb
47
37
  homepage: https://github.com/reidmorrison/parallel_minion
48
38
  licenses:
49
39
  - Apache License V2.0
50
- metadata: {}
51
- post_install_message:
40
+ metadata:
41
+ rubygems_mfa_required: 'true'
52
42
  rdoc_options: []
53
43
  require_paths:
54
44
  - lib
@@ -56,21 +46,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
56
46
  requirements:
57
47
  - - ">="
58
48
  - !ruby/object:Gem::Version
59
- version: '2.1'
49
+ version: '2.5'
60
50
  required_rubygems_version: !ruby/object:Gem::Requirement
61
51
  requirements:
62
52
  - - ">="
63
53
  - !ruby/object:Gem::Version
64
54
  version: '0'
65
55
  requirements: []
66
- rubyforge_project:
67
- rubygems_version: 2.6.11
68
- signing_key:
56
+ rubygems_version: 3.6.9
69
57
  specification_version: 4
70
- summary: Pragmatic approach to parallel and asynchronous processing in Ruby
71
- test_files:
72
- - test/config/database.yml
73
- - test/minion_scope_test.rb
74
- - test/minion_test.rb
75
- - test/test_db.sqlite3
76
- - test/test_helper.rb
58
+ summary: Wrap Ruby code with a minion so that it is run on a parallel thread
59
+ test_files: []
@@ -1,5 +0,0 @@
1
- test:
2
- adapter: sqlite3
3
- database: test/test_db.sqlite3
4
- pool: 5
5
- timeout: 5000
@@ -1,59 +0,0 @@
1
- require_relative 'test_helper'
2
- require 'erb'
3
- require 'active_record'
4
-
5
- ActiveRecord::Base.logger = SemanticLogger[ActiveRecord]
6
- ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read('test/config/database.yml')).result)
7
- ActiveRecord::Base.establish_connection(:test)
8
-
9
- ActiveRecord::Schema.define :version => 0 do
10
- create_table :people, :force => true do |t|
11
- t.string :name
12
- t.string :state
13
- t.string :zip_code
14
- end
15
- end
16
-
17
- class Person < ActiveRecord::Base
18
- end
19
-
20
- class MinionScopeTest < Minitest::Test
21
- describe ParallelMinion::Minion do
22
- [false, true].each do |enabled|
23
- describe ".new with enabled: #{enabled.inspect}" do
24
- before do
25
- Person.create(name: 'Jack', state: 'FL', zip_code: 38729)
26
- Person.create(name: 'John', state: 'FL', zip_code: 35363)
27
- Person.create(name: 'Jill', state: 'FL', zip_code: 73534)
28
- Person.create(name: 'Joe', state: 'NY', zip_code: 45325)
29
- Person.create(name: 'Jane', state: 'NY', zip_code: 45325)
30
- Person.create(name: 'James', state: 'CA', zip_code: 123123)
31
- # Instruct Minions to adhere to any dynamic scopes for Person model
32
- ParallelMinion::Minion.scoped_classes << Person
33
- ParallelMinion::Minion.enabled = enabled
34
- end
35
-
36
- after do
37
- Person.destroy_all
38
- ParallelMinion::Minion.scoped_classes.clear
39
- SemanticLogger.flush
40
- end
41
-
42
- it 'copy across model scope' do
43
- assert_equal 6, Person.count
44
-
45
- Person.unscoped.where(state: 'FL').scoping { Person.count }
46
-
47
- Person.unscoped.where(state: 'FL').scoping do
48
- assert_equal 3, Person.count
49
- minion = ParallelMinion::Minion.new(description: 'Scope Test', log_exception: :full) do
50
- Person.count
51
- end
52
- assert_equal 3, minion.result
53
- end
54
- end
55
-
56
- end
57
- end
58
- end
59
- end
data/test/minion_test.rb DELETED
@@ -1,207 +0,0 @@
1
- require_relative './test_helper'
2
-
3
- # Test ParallelMinion standalone without Rails
4
- # Run this test standalone to verify it has no Rails dependencies
5
- class MinionTest < Minitest::Test
6
- include SemanticLogger::Loggable
7
-
8
- describe ParallelMinion::Minion do
9
-
10
- [false, true].each do |enabled|
11
- describe enabled ? 'enabled' : 'disabled' do
12
- before do
13
- ParallelMinion::Minion.enabled = enabled
14
- $log_structs.clear
15
- end
16
-
17
- it 'without parameters' do
18
- minion = ParallelMinion::Minion.new { 196 }
19
- assert_equal 196, minion.result
20
- end
21
-
22
- it 'with a description' do
23
- minion = ParallelMinion::Minion.new(description: 'Test') { 197 }
24
- assert_equal 197, minion.result
25
- end
26
-
27
- it 'with an argument' do
28
- p1 = {name: 198}
29
- minion = ParallelMinion::Minion.new(p1, description: 'Test') do |v|
30
- v[:name]
31
- end
32
- assert_equal 198, minion.result
33
- end
34
-
35
- it 'raise exception' do
36
- minion = ParallelMinion::Minion.new(description: 'Test') { raise "An exception" }
37
- assert_raises RuntimeError do
38
- minion.result
39
- end
40
- end
41
-
42
- it 'has correct logger name' do
43
- minion = ParallelMinion::Minion.new { 196 }
44
- name = enabled ? 'Minion' : 'Inline'
45
- assert_equal name, minion.logger.name
46
- end
47
-
48
- # TODO Blocks still have access to their original scope if variables cannot be
49
- # resolved first by the parameters, then by the values in Minion itself
50
- # it 'not have access to local variables' do
51
- # name = 'Jack'
52
- # minion = ParallelMinion::Minion.new(description: 'Test') { puts name }
53
- # assert_raises NameError do
54
- # minion.result
55
- # end
56
- # end
57
-
58
- it 'run minion' do
59
- hash = {value: 23}
60
- value = 47
61
- minion = ParallelMinion::Minion.new(hash, description: 'Test') do |h|
62
- value = 321
63
- h[:value] = 123
64
- 456
65
- end
66
- assert_equal 456, minion.result
67
- assert_equal 123, hash[:value]
68
- assert_equal 321, value
69
- end
70
-
71
- it 'copy across logging tags' do
72
- minion = nil
73
- SemanticLogger.tagged('TAG') do
74
- assert_equal 'TAG', SemanticLogger.tags.last
75
- minion = ParallelMinion::Minion.new(description: 'Tag Test') do
76
- logger.info "Tag Test"
77
- logger.tags.last
78
- end
79
- end
80
- assert_equal 'TAG', minion.result
81
- end
82
-
83
- it 'copy across named tags' do
84
- minion = nil
85
- SemanticLogger.named_tagged(tag: 'TAG') do
86
- assert_equal({tag: 'TAG'}, SemanticLogger.named_tags)
87
- minion = ParallelMinion::Minion.new(description: 'Named Tags Test') do
88
- logger.info "Named Tags Test"
89
- SemanticLogger.named_tags
90
- end
91
- end
92
- assert_equal({tag: 'TAG'}, minion.result)
93
- end
94
-
95
- it 'copy across tags and named tags' do
96
- minion = nil
97
- SemanticLogger.tagged('TAG') do
98
- SemanticLogger.named_tagged(tag: 'TAG') do
99
- assert_equal({tag: 'TAG'}, SemanticLogger.named_tags)
100
- assert_equal 'TAG', SemanticLogger.tags.last
101
- minion = ParallelMinion::Minion.new(description: 'Tags Test') do
102
- logger.info "Tags Test"
103
- [SemanticLogger.named_tags, SemanticLogger.tags.last]
104
- end
105
-
106
- assert_equal({tag: 'TAG'}, minion.result.first)
107
- assert_equal 'TAG', minion.result.last
108
- end
109
- end
110
-
111
- end
112
-
113
- it 'include metric' do
114
- metric_name = 'model/method'
115
- hash = {value: 23}
116
- value = 47
117
- minion = ParallelMinion::Minion.new(hash, description: 'Test', metric: metric_name) do |h|
118
- value = 321
119
- h[:value] = 123
120
- sleep 1
121
- 456
122
- end
123
- assert_equal 456, minion.result
124
- assert_equal 123, hash[:value]
125
- assert_equal 321, value
126
- SemanticLogger.flush
127
- assert log = $log_structs.first, -> { $log_structs.ai }
128
- if enabled
129
- # Completed log message
130
- assert_equal metric_name, log.metric, -> { $log_structs.ai }
131
- # Wait log message
132
- assert log = $log_structs.last, -> { $log_structs.ai }
133
- assert_equal "#{metric_name}/wait", log.metric, -> { $log_structs.ai }
134
- else
135
- # Timeout and wait has no effect when run inline
136
- assert_equal metric_name, log.metric, -> { $log_structs.ai }
137
- end
138
- end
139
-
140
- it 'handle multiple minions concurrently' do
141
- # Start 10 minions
142
- minions = 10.times.collect do |i|
143
- # Each Minion returns its index in the collection
144
- ParallelMinion::Minion.new(i, description: "Minion:#{i}") { |counter| counter }
145
- end
146
- assert_equal 10, minions.count
147
- # Fetch the result from each Minion
148
- minions.each_with_index do |minion, index|
149
- assert_equal index, minion.result
150
- end
151
- end
152
-
153
- it 'timeout' do
154
- if enabled
155
- minion = ParallelMinion::Minion.new(description: 'Test', timeout: 100) { sleep 1 }
156
- assert_nil minion.result
157
- end
158
- end
159
-
160
- it 'timeout and terminate thread with Exception' do
161
- if enabled
162
- minion = ParallelMinion::Minion.new(description: 'Test', timeout: 100, on_timeout: Timeout::Error) { sleep 1 }
163
- assert_nil minion.result
164
- # Give time for thread to terminate
165
- sleep 0.1
166
- assert_equal Timeout::Error, minion.exception.class
167
- assert_equal false, minion.working?
168
- assert_equal true, minion.completed?
169
- assert_equal true, minion.failed?
170
- assert_equal 0, minion.time_left
171
- end
172
- end
173
-
174
- it 'make description instance variable available' do
175
- minion = ParallelMinion::Minion.new(description: 'Test') do
176
- description
177
- end
178
- assert_equal 'Test', minion.result
179
- end
180
-
181
- it 'make timeout instance variable available' do
182
- minion = ParallelMinion::Minion.new(description: 'Test', timeout: 1000) do
183
- timeout
184
- end
185
- assert_equal 1000, minion.result
186
- end
187
-
188
- it 'make enabled? method available' do
189
- minion = ParallelMinion::Minion.new(description: 'Test') do
190
- enabled?
191
- end
192
- assert_equal enabled, minion.result
193
- end
194
-
195
- it 'keep the original arguments' do
196
- minion = ParallelMinion::Minion.new(1, 'data', 14.1, description: 'Test') do |num, str, float|
197
- num + float
198
- end
199
- assert_equal 15.1, minion.result
200
- assert_equal [1, 'data', 14.1], minion.arguments
201
- end
202
- end
203
-
204
- end
205
-
206
- end
207
- end
data/test/test_db.sqlite3 DELETED
Binary file
data/test/test_helper.rb DELETED
@@ -1,14 +0,0 @@
1
- #$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
-
3
- require 'minitest/autorun'
4
- require 'parallel_minion'
5
- require 'semantic_logger'
6
-
7
- SemanticLogger.default_level = :trace
8
- SemanticLogger.add_appender(file_name: 'test.log', formatter: :color)
9
-
10
- # Setup global callback for metric so that it can be tested below
11
- $log_structs = []
12
- SemanticLogger.on_metric do |log_struct|
13
- $log_structs << log_struct.dup
14
- end