fleiss 0.1.3 → 0.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
2
  SHA256:
3
- metadata.gz: 45bf4b9f2a7a9d88cbdd4feb8fb2992d6545554695c791a1f327a5a26da3e53d
4
- data.tar.gz: 4434eac634c36952365be272f5f8327462577db2cc338c97b1f242f2f59d14bf
3
+ metadata.gz: 2d7f27ee73ed5c0434f79ec98f0c249f4f41ece528807cabc3efd29f8ebf79c0
4
+ data.tar.gz: e597168cfb8931240110ad45b4ee49937128bdb4dce826d142954253ce29dc9d
5
5
  SHA512:
6
- metadata.gz: d008669212582e7e5190ee0901024555c5031d0295b934d08dd91508d0b83251ea7790540c0e4d8339cae15b6aa9c6c043d5fc39eaa18bc5a696a30e23bc4a0f
7
- data.tar.gz: fc3f5555a6290abebd712e545172fea30eb4be0074da2eb86bc1cb136216af563054111d45599f2e9ddb3560a94c00256e7a8d00b3f7b69e849d39264911131d
6
+ metadata.gz: 737815c833f1ff98e4c18c54709b7671ecd26cabb8500e5f93375a4ac528b4a8344381fe906db2e27726e2217de036a406aa83263514e2475798e5a15831f037
7
+ data.tar.gz: dae7da18743673e38465150031a48734e7911d7894c0131a8d9469d472650f30ea53a73d6217bcc6c4f237c93fa8dfd147ad9df4ac3542e1f015e75dbbda4c4c
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  .rubocop-*
2
2
  pkg/
3
+ spec/tmp
@@ -1,5 +1,8 @@
1
1
  inherit_from:
2
- - https://bitbucket.org/bsm/misc/raw/master/rubocop/default.yml
2
+ - https://gitlab.com/bsm/misc/raw/master/rubocop/default.yml
3
+
4
+ AllCops:
5
+ TargetRubyVersion: "2.6"
3
6
 
4
7
  Security/Open:
5
8
  Exclude:
@@ -1,8 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.5
4
- - 2.4
3
+ - 2.7
4
+ - 2.6
5
5
  before_install:
6
+ - gem install bundler
6
7
  - mysql -e 'CREATE DATABASE fleiss_test;'
7
8
  - psql -c 'CREATE DATABASE fleiss_test;' -U postgres
8
9
  services:
@@ -1,73 +1,74 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fleiss (0.1.3)
5
- activejob (>= 5.0)
6
- activerecord (>= 5.0)
4
+ fleiss (0.4.0)
5
+ activejob (>= 6.0)
6
+ activerecord (>= 6.0)
7
7
  concurrent-ruby
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- activejob (5.2.2)
13
- activesupport (= 5.2.2)
12
+ activejob (6.0.3.1)
13
+ activesupport (= 6.0.3.1)
14
14
  globalid (>= 0.3.6)
15
- activemodel (5.2.2)
16
- activesupport (= 5.2.2)
17
- activerecord (5.2.2)
18
- activemodel (= 5.2.2)
19
- activesupport (= 5.2.2)
20
- arel (>= 9.0)
21
- activesupport (5.2.2)
15
+ activemodel (6.0.3.1)
16
+ activesupport (= 6.0.3.1)
17
+ activerecord (6.0.3.1)
18
+ activemodel (= 6.0.3.1)
19
+ activesupport (= 6.0.3.1)
20
+ activesupport (6.0.3.1)
22
21
  concurrent-ruby (~> 1.0, >= 1.0.2)
23
22
  i18n (>= 0.7, < 2)
24
23
  minitest (~> 5.1)
25
24
  tzinfo (~> 1.1)
26
- arel (9.0.0)
25
+ zeitwerk (~> 2.2, >= 2.2.2)
27
26
  ast (2.4.0)
28
- concurrent-ruby (1.1.3)
27
+ concurrent-ruby (1.1.6)
29
28
  diff-lcs (1.3)
30
- globalid (0.4.1)
29
+ globalid (0.4.2)
31
30
  activesupport (>= 4.2.0)
32
- i18n (1.2.0)
31
+ i18n (1.8.2)
33
32
  concurrent-ruby (~> 1.0)
34
- jaro_winkler (1.5.1)
35
- minitest (5.11.3)
36
- mysql2 (0.5.2)
37
- parallel (1.12.1)
38
- parser (2.5.3.0)
33
+ minitest (5.14.1)
34
+ mysql2 (0.5.3)
35
+ parallel (1.19.1)
36
+ parser (2.7.1.3)
39
37
  ast (~> 2.4.0)
40
- pg (1.1.3)
41
- powerpack (0.1.2)
38
+ pg (1.2.3)
42
39
  rainbow (3.0.0)
43
- rake (12.3.2)
44
- rspec (3.8.0)
45
- rspec-core (~> 3.8.0)
46
- rspec-expectations (~> 3.8.0)
47
- rspec-mocks (~> 3.8.0)
48
- rspec-core (3.8.0)
49
- rspec-support (~> 3.8.0)
50
- rspec-expectations (3.8.2)
40
+ rake (13.0.1)
41
+ rexml (3.2.4)
42
+ rspec (3.9.0)
43
+ rspec-core (~> 3.9.0)
44
+ rspec-expectations (~> 3.9.0)
45
+ rspec-mocks (~> 3.9.0)
46
+ rspec-core (3.9.2)
47
+ rspec-support (~> 3.9.3)
48
+ rspec-expectations (3.9.2)
51
49
  diff-lcs (>= 1.2.0, < 2.0)
52
- rspec-support (~> 3.8.0)
53
- rspec-mocks (3.8.0)
50
+ rspec-support (~> 3.9.0)
51
+ rspec-mocks (3.9.1)
54
52
  diff-lcs (>= 1.2.0, < 2.0)
55
- rspec-support (~> 3.8.0)
56
- rspec-support (3.8.0)
57
- rubocop (0.61.1)
58
- jaro_winkler (~> 1.5.1)
53
+ rspec-support (~> 3.9.0)
54
+ rspec-support (3.9.3)
55
+ rubocop (0.84.0)
59
56
  parallel (~> 1.10)
60
- parser (>= 2.5, != 2.5.1.1)
61
- powerpack (~> 0.1)
57
+ parser (>= 2.7.0.1)
62
58
  rainbow (>= 2.2.2, < 4.0)
59
+ rexml
60
+ rubocop-ast (>= 0.0.3)
63
61
  ruby-progressbar (~> 1.7)
64
- unicode-display_width (~> 1.4.0)
65
- ruby-progressbar (1.10.0)
66
- sqlite3 (1.3.13)
62
+ unicode-display_width (>= 1.4.0, < 2.0)
63
+ rubocop-ast (0.0.3)
64
+ parser (>= 2.7.0.1)
65
+ ruby-progressbar (1.10.1)
66
+ sqlite3 (1.4.2)
67
67
  thread_safe (0.3.6)
68
- tzinfo (1.2.5)
68
+ tzinfo (1.2.7)
69
69
  thread_safe (~> 0.1)
70
- unicode-display_width (1.4.0)
70
+ unicode-display_width (1.7.0)
71
+ zeitwerk (2.3.0)
71
72
 
72
73
  PLATFORMS
73
74
  ruby
@@ -83,4 +84,4 @@ DEPENDENCIES
83
84
  sqlite3
84
85
 
85
86
  BUNDLED WITH
86
- 1.16.4
87
+ 2.1.4
data/bin/fleiss CHANGED
@@ -5,17 +5,20 @@ $LOAD_PATH.push(lib_dir) unless $LOAD_PATH.include?(lib_dir)
5
5
 
6
6
  require 'fleiss/cli'
7
7
 
8
+ STDOUT.sync = true
9
+ STDERR.sync = true
10
+
8
11
  cli = Fleiss::CLI.instance
9
12
  begin
10
13
  cli.parse!
11
14
  cli.run!
12
15
  rescue ArgumentError => e
13
- STDERR.puts " ! #{e.message}\n"
16
+ warn " ! #{e.message}\n"
14
17
  STDERR.puts
15
- STDERR.puts cli.parser
18
+ warn cli.parser
16
19
  exit 1
17
20
  rescue StandardError => e
18
- STDERR.puts e.message
19
- STDERR.puts e.backtrace.join("\n")
21
+ warn e.message
22
+ warn e.backtrace.join("\n")
20
23
  exit 1
21
24
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'fleiss'
3
- s.version = '0.1.3'
3
+ s.version = '0.4.0'
4
4
  s.authors = ['Black Square Media Ltd']
5
5
  s.email = ['info@blacksquaremedia.com']
6
6
  s.summary = %(Minimialist background jobs backed by ActiveJob and ActiveRecord.)
@@ -12,10 +12,10 @@ Gem::Specification.new do |s|
12
12
  s.files = `git ls-files -z`.split("\x0").reject {|f| f.match(%r{^spec/}) }
13
13
  s.test_files = `git ls-files -z -- spec/*`.split("\x0")
14
14
  s.require_paths = ['lib']
15
- s.required_ruby_version = '>= 2.2'
15
+ s.required_ruby_version = '>= 2.6'
16
16
 
17
- s.add_dependency 'activejob', '>= 5.0'
18
- s.add_dependency 'activerecord', '>= 5.0'
17
+ s.add_dependency 'activejob', '>= 6.0'
18
+ s.add_dependency 'activerecord', '>= 6.0'
19
19
  s.add_dependency 'concurrent-ruby'
20
20
 
21
21
  s.add_development_dependency 'bundler'
@@ -1,9 +1,15 @@
1
+ require 'active_job'
2
+ require 'active_job/queue_adapters/fleiss_adapter'
3
+ require 'fleiss/backend'
4
+
1
5
  module Fleiss
2
6
  DEFAULT_QUEUE = 'default'.freeze
3
7
 
4
8
  def self.backend
5
- self::Backend::ActiveRecord
9
+ @backend ||= self::Backend::ActiveRecord
6
10
  end
7
- end
8
11
 
9
- require 'fleiss/backend'
12
+ def self.backend=(value)
13
+ @backend = value
14
+ end
15
+ end
@@ -8,15 +8,19 @@ module Fleiss
8
8
  scope :in_queue, ->(qs) { where(queue_name: Array.wrap(qs)) }
9
9
  scope :finished, -> { where.not(finished_at: nil) }
10
10
  scope :not_finished, -> { where(finished_at: nil) }
11
- scope :not_expired, ->(now=Time.zone.now) { where(arel_table[:expires_at].eq(nil).or(arel_table[:expires_at].gt(now))) }
11
+ scope :not_expired, ->(now = Time.zone.now) { where(arel_table[:expires_at].eq(nil).or(arel_table[:expires_at].gt(now))) }
12
12
  scope :started, -> { where(arel_table[:started_at].not_eq(nil)) }
13
13
  scope :not_started, -> { where(arel_table[:started_at].eq(nil)) }
14
- scope :scheduled, ->(now=Time.zone.now) { where(arel_table[:scheduled_at].gt(now)) }
14
+ scope :scheduled, ->(now = Time.zone.now) { where(arel_table[:scheduled_at].gt(now)) }
15
15
  end
16
16
 
17
17
  module ClassMethods
18
+ def wrap_perform(&block)
19
+ connection_pool.with_connection(&block)
20
+ end
21
+
18
22
  # @return [ActiveRecord::Relation] pending scope
19
- def pending(now=Time.zone.now)
23
+ def pending(now = Time.zone.now)
20
24
  not_finished
21
25
  .not_expired(now)
22
26
  .not_started
@@ -2,7 +2,6 @@ require 'singleton'
2
2
  require 'optparse'
3
3
  require 'yaml'
4
4
  require 'erb'
5
- require 'logger'
6
5
 
7
6
  module Fleiss
8
7
  class CLI
@@ -15,7 +14,6 @@ module Fleiss
15
14
  require: [],
16
15
  concurrency: 10,
17
16
  wait_time: 1.0,
18
- logfile: STDOUT,
19
17
  }.freeze
20
18
 
21
19
  attr_reader :opts
@@ -24,7 +22,7 @@ module Fleiss
24
22
  @opts = DEFAULT_OPTIONS.dup
25
23
  end
26
24
 
27
- def parse!(argv=ARGV)
25
+ def parse!(argv = ARGV)
28
26
  parser.parse!(argv)
29
27
 
30
28
  # Check config file
@@ -46,14 +44,11 @@ module Fleiss
46
44
  opts[:require].each {|n| require n }
47
45
  require 'fleiss/worker'
48
46
 
49
- logdev = opts[:logfile]
50
- logdev.sync = true if logdev.respond_to?(:sync=)
51
-
47
+ ActiveJob::Base.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(opts[:logfile])) if opts[:logfile]
52
48
  Fleiss::Worker.run \
53
49
  queues: opts[:queues],
54
50
  concurrency: opts[:concurrency],
55
- wait_time: opts[:wait_time],
56
- logger: Logger.new(logdev)
51
+ wait_time: opts[:wait_time]
57
52
  end
58
53
 
59
54
  def parser # rubocop:disable Metrics/MethodLength
@@ -0,0 +1,22 @@
1
+ require 'fleiss'
2
+ require 'concurrent/executor/simple_executor_service'
3
+
4
+ class Fleiss::Executor < Concurrent::SimpleExecutorService
5
+ attr_reader :max_size
6
+
7
+ def post(&block)
8
+ super unless capacity.zero?
9
+ end
10
+
11
+ def capacity
12
+ val = @max_size - @count.value
13
+ val.positive? ? val : 0
14
+ end
15
+
16
+ private
17
+
18
+ def ns_initialize(opts = {})
19
+ super()
20
+ @max_size = opts.fetch(:max_size, 1).to_i
21
+ end
22
+ end
@@ -1,11 +1,9 @@
1
1
  require 'fleiss'
2
- require 'concurrent/executor/fixed_thread_pool'
3
- require 'concurrent/atomic/atomic_fixnum'
4
- require 'logger'
2
+ require 'fleiss/executor'
5
3
  require 'securerandom'
6
4
 
7
5
  class Fleiss::Worker
8
- attr_reader :queues, :uuid, :wait_time, :logger
6
+ attr_reader :queues, :uuid, :wait_time
9
7
 
10
8
  # Shortcut for new(*args).run
11
9
  def self.run(*args)
@@ -18,24 +16,22 @@ class Fleiss::Worker
18
16
  # @option [Array<String>] :queues queues to watch. Default: ["default"]
19
17
  # @option [Integer] :concurrency the number of concurrent pool. Default: 10
20
18
  # @option [Numeric] :wait_time maximum time (in seconds) to wait for jobs when retrieving next batch. Default: 1s.
21
- # @option [Logger] :logger optional logger.
22
- def initialize(queues: [Fleiss::DEFAULT_QUEUE], concurrency: 10, wait_time: 1, logger: nil)
19
+ def initialize(queues: [Fleiss::DEFAULT_QUEUE], concurrency: 10, wait_time: 1)
23
20
  @uuid = SecureRandom.uuid
24
21
  @queues = Array(queues)
25
- @pool = Concurrent::FixedThreadPool.new(concurrency, fallback_policy: :discard)
22
+ @pool = Fleiss::Executor.new(max_size: concurrency)
26
23
  @wait_time = wait_time
27
- @logger = logger || Logger.new(nil)
28
24
  end
29
25
 
30
26
  # Run starts the worker
31
27
  def run
32
- logger.info "Worker #{uuid} starting - queues: #{queues.inspect}, concurrency: #{@pool.max_length}"
28
+ log(:info) { "Worker #{uuid} starting - queues: #{queues.inspect}, concurrency: #{@pool.max_size}" }
33
29
  loop do
34
30
  run_cycle
35
31
  sleep @wait_time
36
32
  end
37
33
  rescue SignalException => e
38
- logger.info "Worker #{uuid} received #{e.message}. Shutting down..."
34
+ log(:info) { "Worker #{uuid} received #{e.message}. Shutting down..." }
39
35
  ensure
40
36
  @pool.shutdown
41
37
  @pool.wait_for_termination
@@ -43,20 +39,31 @@ class Fleiss::Worker
43
39
 
44
40
  private
45
41
 
42
+ def log(severity, &block)
43
+ logger = ActiveJob::Base.logger
44
+ if logger.respond_to?(:tagged)
45
+ logger.tagged('Fleiss') { logger.send(severity, &block) }
46
+ else
47
+ logger.send(severity, &block)
48
+ end
49
+ end
50
+
46
51
  def run_cycle
47
- return if @pool.shuttingdown?
52
+ return unless @pool.running?
48
53
 
49
- capacity = @pool.max_length - @pool.scheduled_task_count + @pool.completed_task_count
50
- return unless capacity.positive?
54
+ limit = @pool.capacity
55
+ return unless limit.positive?
51
56
 
52
57
  batch = Fleiss.backend
53
58
  .in_queue(queues)
54
59
  .pending
55
- .limit(capacity)
60
+ .limit(limit)
56
61
  .to_a
57
62
 
58
63
  batch.each do |job|
59
- @pool.post { perform(job) }
64
+ @pool.post do
65
+ Fleiss.backend.wrap_perform { perform(job) }
66
+ end
60
67
  end
61
68
  rescue StandardError => e
62
69
  handle_exception e, 'running cycle'
@@ -67,7 +74,7 @@ class Fleiss::Worker
67
74
  owner = "#{uuid}/#{thread_id}"
68
75
  return unless job.start(owner)
69
76
 
70
- logger.info { "Worker #{uuid} execute job ##{job.id} (by thread #{thread_id})" }
77
+ log(:info) { "Worker #{uuid} execute job ##{job.id} (by thread #{thread_id})" }
71
78
  finished = false
72
79
  begin
73
80
  ActiveJob::Base.execute job.job_data
@@ -83,12 +90,12 @@ class Fleiss::Worker
83
90
  end
84
91
 
85
92
  def handle_exception(err, intro)
86
- lines = [
87
- "Worker #{uuid} error on #{intro}:",
88
- "#{err.class.name}: #{err.message}",
89
- err.backtrace,
90
- ].compact.flatten
91
-
92
- logger.error lines.join("\n")
93
+ log(:error) do
94
+ [
95
+ "Worker #{uuid} error on #{intro}:",
96
+ "#{err.class.name}: #{err.message}",
97
+ err.backtrace,
98
+ ].compact.flatten.join("\n")
99
+ end
93
100
  end
94
101
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'fleiss/executor'
3
+
4
+ RSpec.describe Fleiss::Executor do
5
+ subject { described_class.new max_size: 2 }
6
+ after { subject.kill }
7
+
8
+ it 'should check capacity' do
9
+ expect(described_class.new.capacity).to eq(1)
10
+
11
+ expect(subject.capacity).to eq(2)
12
+ subject.post { sleep(1) }
13
+ expect(subject.capacity).to eq(1)
14
+ subject.post { sleep(1) }
15
+ expect(subject.capacity).to eq(0)
16
+ end
17
+
18
+ it 'should discard execution when capacity is reached' do
19
+ n = Concurrent::AtomicFixnum.new(0)
20
+ 10.times do
21
+ 10.times { subject.post { n.increment } }
22
+ sleep(0.001)
23
+ end
24
+ subject.shutdown
25
+ subject.wait_for_termination(1)
26
+ expect(n.value).to be_within(10).of(20)
27
+ end
28
+ end
@@ -5,15 +5,19 @@ require 'fleiss'
5
5
  require 'fleiss/backend/active_record/migration'
6
6
  require 'active_job'
7
7
  require 'active_job/queue_adapters/fleiss_adapter'
8
- require 'tempfile'
8
+ require 'fileutils'
9
9
 
10
10
  ActiveJob::Base.queue_adapter = :fleiss
11
11
  ActiveJob::Base.logger = Logger.new(nil)
12
12
 
13
13
  Time.zone_default = Time.find_zone!('UTC')
14
14
 
15
- database_url = ENV['DATABASE_URL'] || "sqlite3://#{Tempfile.new(['fleiss-test', '.sqlite3']).path}"
16
- ActiveRecord::Base.configurations['test'] = { 'url' => database_url, 'pool' => 20 }
15
+ tmpdir = File.expand_path('./tmp', __dir__)
16
+ FileUtils.rm_rf tmpdir
17
+ FileUtils.mkdir_p tmpdir
18
+
19
+ database_url = ENV['DATABASE_URL'] || "sqlite3://#{tmpdir}/fleiss-test.sqlite3"
20
+ ActiveRecord::Base.configurations = { 'test' => { 'url' => database_url, 'pool' => 20 } }
17
21
 
18
22
  ActiveRecord::Base.establish_connection :test
19
23
  ActiveRecord::Base.connection.drop_table('fleiss_jobs', if_exists: true)
@@ -32,7 +36,7 @@ class TestJob < ActiveJob::Base
32
36
  72.hours
33
37
  end
34
38
 
35
- def perform(msg=nil)
39
+ def perform(msg = nil)
36
40
  raise 'Failing' if msg == 'raise'
37
41
 
38
42
  self.class.performed.push(msg)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fleiss
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Black Square Media Ltd
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-19 00:00:00.000000000 Z
11
+ date: 2020-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '5.0'
19
+ version: '6.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '5.0'
26
+ version: '6.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activerecord
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '5.0'
33
+ version: '6.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '5.0'
40
+ version: '6.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: concurrent-ruby
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -176,8 +176,10 @@ files:
176
176
  - lib/fleiss/backend/active_record/concern.rb
177
177
  - lib/fleiss/backend/active_record/migration.rb
178
178
  - lib/fleiss/cli.rb
179
+ - lib/fleiss/executor.rb
179
180
  - lib/fleiss/worker.rb
180
181
  - spec/fleiss/backend/active_record_spec.rb
182
+ - spec/fleiss/executor_spec.rb
181
183
  - spec/fleiss/worker_spec.rb
182
184
  - spec/fleiss_spec.rb
183
185
  - spec/spec_helper.rb
@@ -193,20 +195,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
193
195
  requirements:
194
196
  - - ">="
195
197
  - !ruby/object:Gem::Version
196
- version: '2.2'
198
+ version: '2.6'
197
199
  required_rubygems_version: !ruby/object:Gem::Requirement
198
200
  requirements:
199
201
  - - ">="
200
202
  - !ruby/object:Gem::Version
201
203
  version: '0'
202
204
  requirements: []
203
- rubyforge_project:
204
- rubygems_version: 2.7.7
205
+ rubygems_version: 3.1.2
205
206
  signing_key:
206
207
  specification_version: 4
207
208
  summary: Minimialist background jobs backed by ActiveJob and ActiveRecord.
208
209
  test_files:
209
210
  - spec/fleiss/backend/active_record_spec.rb
211
+ - spec/fleiss/executor_spec.rb
210
212
  - spec/fleiss/worker_spec.rb
211
213
  - spec/fleiss_spec.rb
212
214
  - spec/spec_helper.rb