joblin 0.1.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 +7 -0
- data/README.md +1 -0
- data/app/models/joblin/background_task/api_access.rb +148 -0
- data/app/models/joblin/background_task/attachments.rb +47 -0
- data/app/models/joblin/background_task/executor.rb +63 -0
- data/app/models/joblin/background_task/options.rb +75 -0
- data/app/models/joblin/background_task/retention_policy.rb +28 -0
- data/app/models/joblin/background_task.rb +72 -0
- data/app/models/joblin/concerns/job_working_dirs.rb +21 -0
- data/db/migrate/20250903184852_create_background_tasks.rb +12 -0
- data/joblin.gemspec +35 -0
- data/lib/joblin/batching/batch.rb +537 -0
- data/lib/joblin/batching/callback.rb +135 -0
- data/lib/joblin/batching/chain_builder.rb +247 -0
- data/lib/joblin/batching/compat/active_job.rb +108 -0
- data/lib/joblin/batching/compat/sidekiq/web/batches_assets/css/styles.less +182 -0
- data/lib/joblin/batching/compat/sidekiq/web/batches_assets/js/batch_tree.js +108 -0
- data/lib/joblin/batching/compat/sidekiq/web/batches_assets/js/util.js +2 -0
- data/lib/joblin/batching/compat/sidekiq/web/helpers.rb +41 -0
- data/lib/joblin/batching/compat/sidekiq/web/views/_batch_tree.erb +6 -0
- data/lib/joblin/batching/compat/sidekiq/web/views/_batches_table.erb +44 -0
- data/lib/joblin/batching/compat/sidekiq/web/views/_common.erb +13 -0
- data/lib/joblin/batching/compat/sidekiq/web/views/_jobs_table.erb +21 -0
- data/lib/joblin/batching/compat/sidekiq/web/views/_pagination.erb +26 -0
- data/lib/joblin/batching/compat/sidekiq/web/views/batch.erb +81 -0
- data/lib/joblin/batching/compat/sidekiq/web/views/batches.erb +23 -0
- data/lib/joblin/batching/compat/sidekiq/web/views/pool.erb +137 -0
- data/lib/joblin/batching/compat/sidekiq/web/views/pools.erb +47 -0
- data/lib/joblin/batching/compat/sidekiq/web.rb +218 -0
- data/lib/joblin/batching/compat/sidekiq.rb +149 -0
- data/lib/joblin/batching/compat.rb +20 -0
- data/lib/joblin/batching/context_hash.rb +157 -0
- data/lib/joblin/batching/hier_batch_ids.lua +25 -0
- data/lib/joblin/batching/jobs/base_job.rb +7 -0
- data/lib/joblin/batching/jobs/concurrent_batch_job.rb +20 -0
- data/lib/joblin/batching/jobs/managed_batch_job.rb +175 -0
- data/lib/joblin/batching/jobs/serial_batch_job.rb +20 -0
- data/lib/joblin/batching/pool.rb +254 -0
- data/lib/joblin/batching/pool_refill.lua +47 -0
- data/lib/joblin/batching/schedule_callback.lua +14 -0
- data/lib/joblin/batching/status.rb +89 -0
- data/lib/joblin/engine.rb +15 -0
- data/lib/joblin/lazy_access.rb +72 -0
- data/lib/joblin/uniqueness/compat/active_job.rb +75 -0
- data/lib/joblin/uniqueness/compat/sidekiq.rb +135 -0
- data/lib/joblin/uniqueness/compat.rb +20 -0
- data/lib/joblin/uniqueness/configuration.rb +25 -0
- data/lib/joblin/uniqueness/job_uniqueness.rb +49 -0
- data/lib/joblin/uniqueness/lock_context.rb +199 -0
- data/lib/joblin/uniqueness/locksmith.rb +92 -0
- data/lib/joblin/uniqueness/on_conflict/base.rb +32 -0
- data/lib/joblin/uniqueness/on_conflict/log.rb +13 -0
- data/lib/joblin/uniqueness/on_conflict/null_strategy.rb +9 -0
- data/lib/joblin/uniqueness/on_conflict/raise.rb +11 -0
- data/lib/joblin/uniqueness/on_conflict/reject.rb +21 -0
- data/lib/joblin/uniqueness/on_conflict/reschedule.rb +20 -0
- data/lib/joblin/uniqueness/on_conflict.rb +62 -0
- data/lib/joblin/uniqueness/strategy/base.rb +107 -0
- data/lib/joblin/uniqueness/strategy/until_and_while_executing.rb +35 -0
- data/lib/joblin/uniqueness/strategy/until_executed.rb +20 -0
- data/lib/joblin/uniqueness/strategy/until_executing.rb +20 -0
- data/lib/joblin/uniqueness/strategy/until_expired.rb +16 -0
- data/lib/joblin/uniqueness/strategy/while_executing.rb +26 -0
- data/lib/joblin/uniqueness/strategy.rb +27 -0
- data/lib/joblin/uniqueness/unique_job_common.rb +79 -0
- data/lib/joblin/version.rb +3 -0
- data/lib/joblin.rb +37 -0
- data/spec/batching/batch_spec.rb +493 -0
- data/spec/batching/callback_spec.rb +38 -0
- data/spec/batching/compat/active_job_spec.rb +107 -0
- data/spec/batching/compat/sidekiq_spec.rb +127 -0
- data/spec/batching/context_hash_spec.rb +54 -0
- data/spec/batching/flow_spec.rb +82 -0
- data/spec/batching/integration/fail_then_succeed.rb +42 -0
- data/spec/batching/integration/integration.rb +57 -0
- data/spec/batching/integration/nested.rb +88 -0
- data/spec/batching/integration/simple.rb +47 -0
- data/spec/batching/integration/workflow.rb +134 -0
- data/spec/batching/integration_helper.rb +50 -0
- data/spec/batching/pool_spec.rb +161 -0
- data/spec/batching/status_spec.rb +76 -0
- data/spec/batching/support/base_job.rb +19 -0
- data/spec/batching/support/sample_callback.rb +2 -0
- data/spec/internal/config/database.yml +5 -0
- data/spec/internal/config/routes.rb +5 -0
- data/spec/internal/config/storage.yml +3 -0
- data/spec/internal/db/combustion_test.sqlite +0 -0
- data/spec/internal/db/schema.rb +6 -0
- data/spec/internal/log/test.log +48200 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/models/background_task_spec.rb +41 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/uniqueness/compat/active_job_spec.rb +49 -0
- data/spec/uniqueness/compat/sidekiq_spec.rb +68 -0
- data/spec/uniqueness/lock_context_spec.rb +106 -0
- data/spec/uniqueness/on_conflict/log_spec.rb +11 -0
- data/spec/uniqueness/on_conflict/raise_spec.rb +10 -0
- data/spec/uniqueness/on_conflict/reschedule_spec.rb +63 -0
- data/spec/uniqueness/on_conflict_spec.rb +16 -0
- data/spec/uniqueness/spec_helper.rb +19 -0
- data/spec/uniqueness/strategy/base_spec.rb +100 -0
- data/spec/uniqueness/strategy/until_and_while_executing_spec.rb +48 -0
- data/spec/uniqueness/strategy/until_executed_spec.rb +23 -0
- data/spec/uniqueness/strategy/until_executing_spec.rb +23 -0
- data/spec/uniqueness/strategy/until_expired_spec.rb +23 -0
- data/spec/uniqueness/strategy/while_executing_spec.rb +33 -0
- data/spec/uniqueness/support/lock_strategy.rb +28 -0
- data/spec/uniqueness/support/on_conflict.rb +24 -0
- data/spec/uniqueness/support/test_worker.rb +19 -0
- data/spec/uniqueness/unique_job_common_spec.rb +45 -0
- metadata +308 -0
| 
            File without changes
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::BackgroundTask, type: :model do
         | 
| 4 | 
            +
              let(:task) { Joblin::BackgroundTask.create!(type: 'Joblin::BackgroundTask') }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              describe '#options' do
         | 
| 7 | 
            +
                it 'saves changes' do
         | 
| 8 | 
            +
                  task.options['foo'] = 'bar'
         | 
| 9 | 
            +
                  task.save!
         | 
| 10 | 
            +
                  expect(task.reload.extra_options).to eq({ "foo" => 'bar' })
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                it 'stores references' do
         | 
| 14 | 
            +
                  task.options['ref'] = task
         | 
| 15 | 
            +
                  task.save!
         | 
| 16 | 
            +
                  task.reload
         | 
| 17 | 
            +
                  expect(task.options['ref']).to eq(task)
         | 
| 18 | 
            +
                  expect(task.extra_options.to_h).to eq({ 'ref' => task.to_gid.to_s })
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                it 'is indifferent' do
         | 
| 22 | 
            +
                  task.options[:foo] = 'bar'
         | 
| 23 | 
            +
                  task.save!
         | 
| 24 | 
            +
                  task.reload
         | 
| 25 | 
            +
                  expect(task.options[:foo]).to eq('bar')
         | 
| 26 | 
            +
                  expect(task.options['foo']).to eq('bar')
         | 
| 27 | 
            +
                  expect(task.options[:updated_at]).to eq(task.updated_at)
         | 
| 28 | 
            +
                  expect(task.options['updated_at']).to eq(task.updated_at)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                it 'reads from columns' do
         | 
| 32 | 
            +
                  expect(task.options[:updated_at]).to eq(task.updated_at)
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                it 'writes to columns' do
         | 
| 36 | 
            +
                  dt = 3.days.ago
         | 
| 37 | 
            +
                  task.options[:updated_at] = dt
         | 
| 38 | 
            +
                  expect(task.updated_at).to eq(dt)
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            require 'bundler'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Bundler.require :default, :development
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Combustion.initialize! :active_record, :active_job
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            require 'redis'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            require 'rspec/rails'
         | 
| 10 | 
            +
            # If you're using Capybara:
         | 
| 11 | 
            +
            # require 'capybara/rails'
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            require 'sidekiq'
         | 
| 14 | 
            +
            require 'sidekiq/rails'
         | 
| 15 | 
            +
            require 'sidekiq/testing'
         | 
| 16 | 
            +
            Sidekiq::Testing.fake!
         | 
| 17 | 
            +
            Sidekiq::Testing.server_middleware do |chain|
         | 
| 18 | 
            +
              chain.add Joblin::Batching::Compat::Sidekiq::ServerMiddleware
         | 
| 19 | 
            +
            end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            Dir[File.dirname(__FILE__) + "/batching/support/**/*.rb"].each {|f| require f }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            RSpec.configure do |config|
         | 
| 24 | 
            +
              config.use_transactional_fixtures = true
         | 
| 25 | 
            +
            end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            def set_batch_context(ctx)
         | 
| 28 | 
            +
              allow_any_instance_of(ActiveJob::Base).to receive(:batch_context).and_return(ctx.with_indifferent_access)
         | 
| 29 | 
            +
            end
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::Compat::ActiveJob do
         | 
| 4 | 
            +
              context 'Job Extension' do
         | 
| 5 | 
            +
                it 'includes UniqueJobExtension' do
         | 
| 6 | 
            +
                  expect(ActiveJob::Base < Joblin::Uniqueness::Compat::ActiveJob::JobExtension).to be true
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                it 'has the ensure_uniqueness method' do
         | 
| 10 | 
            +
                  expect(ActiveJob::Base.method(:ensure_uniqueness)).to be_present
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              context 'Job' do
         | 
| 15 | 
            +
                let(:test_job) do
         | 
| 16 | 
            +
                  Class.new(ActiveJob::Base) do
         | 
| 17 | 
            +
                    ensure_uniqueness(
         | 
| 18 | 
            +
                      strategy: :until_executed,
         | 
| 19 | 
            +
                    )
         | 
| 20 | 
            +
                    def perform; end
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                before(:each) do
         | 
| 25 | 
            +
                  stub_const('TestJob', test_job)
         | 
| 26 | 
            +
                  ActiveJob::Base.queue_adapter = :sidekiq
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                it 'runs as expected' do
         | 
| 30 | 
            +
                  strategy = Joblin::Uniqueness::Strategy::UntilExecuted.new(nil)
         | 
| 31 | 
            +
                  allow_any_instance_of(Joblin::Uniqueness::LockContext).to receive(:lock_strategy) do |lock_context|
         | 
| 32 | 
            +
                    strategy.instance_variable_set(:@lock_context, lock_context)
         | 
| 33 | 
            +
                    strategy
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                  allow(Joblin::Uniqueness::Strategy::UntilExecuted).to receive(:new).and_return(strategy)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  expect(strategy).to receive(:on_enqueue).and_call_original
         | 
| 38 | 
            +
                  expect(strategy).to receive(:on_perform).and_call_original
         | 
| 39 | 
            +
                  expect(strategy).to receive(:batch_callback).with(:complete, anything).and_call_original
         | 
| 40 | 
            +
                  expect(strategy).to receive(:batch_callback).with(:success, anything).and_call_original
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  expect_any_instance_of(test_job).to receive(:perform)
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  Sidekiq::Testing.inline! do
         | 
| 45 | 
            +
                    test_job.perform_later
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
            end
         | 
| @@ -0,0 +1,68 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::Compat::Sidekiq do
         | 
| 4 | 
            +
              let(:config) { defined?(Sidekiq::Config) ? double(Sidekiq::Config) : class_double(Sidekiq) }
         | 
| 5 | 
            +
              let(:client_middleware) { double(Sidekiq::Middleware::Chain) }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              context 'client' do
         | 
| 8 | 
            +
                it 'adds client middleware' do
         | 
| 9 | 
            +
                  allow(Sidekiq).to receive(:configure_client).and_yield(config)
         | 
| 10 | 
            +
                  expect(config).to receive(:client_middleware).and_yield(client_middleware)
         | 
| 11 | 
            +
                  expect(client_middleware).to receive(:insert_before).with(anything, Joblin::Uniqueness::Compat::Sidekiq::ClientMiddleware)
         | 
| 12 | 
            +
                  Joblin::Uniqueness::Compat::Sidekiq.configure
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              context 'server' do
         | 
| 17 | 
            +
                let(:server_middleware) { double(Sidekiq::Middleware::Chain) }
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                it 'adds client and server middleware' do
         | 
| 20 | 
            +
                  allow(Sidekiq).to receive(:configure_server).and_yield(config)
         | 
| 21 | 
            +
                  expect(config).to receive(:client_middleware).and_yield(client_middleware)
         | 
| 22 | 
            +
                  expect(config).to receive(:server_middleware).and_yield(server_middleware)
         | 
| 23 | 
            +
                  expect(client_middleware).to receive(:insert_before).with(anything, Joblin::Uniqueness::Compat::Sidekiq::ClientMiddleware)
         | 
| 24 | 
            +
                  expect(server_middleware).to receive(:insert_after).with(anything, Joblin::Uniqueness::Compat::Sidekiq::ServerMiddleware)
         | 
| 25 | 
            +
                  Joblin::Uniqueness::Compat::Sidekiq.configure
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              context 'Job Extension' do
         | 
| 30 | 
            +
                let!(:dummy_worker) do
         | 
| 31 | 
            +
                  Class.new do
         | 
| 32 | 
            +
                    include Sidekiq::Worker
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                it 'includes UniqueJobExtension' do
         | 
| 37 | 
            +
                  expect(dummy_worker < Joblin::Uniqueness::Compat::Sidekiq::WorkerExtension).to be true
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                it 'has the ensure_uniqueness method' do
         | 
| 41 | 
            +
                  expect(dummy_worker.method(:ensure_uniqueness)).to be_present
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              context 'Job' do
         | 
| 46 | 
            +
                include_context 'with TestWorker'
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                it 'runs as expected' do
         | 
| 49 | 
            +
                  strategy = Joblin::Uniqueness::Strategy::UntilExecuted.new(nil)
         | 
| 50 | 
            +
                  allow_any_instance_of(Joblin::Uniqueness::LockContext).to receive(:lock_strategy) do |lock_context|
         | 
| 51 | 
            +
                    strategy.instance_variable_set(:@lock_context, lock_context)
         | 
| 52 | 
            +
                    strategy
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                  allow(Joblin::Uniqueness::Strategy::UntilExecuted).to receive(:new).and_return(strategy)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  expect(strategy).to receive(:on_enqueue).and_call_original
         | 
| 57 | 
            +
                  expect(strategy).to receive(:on_perform).and_call_original
         | 
| 58 | 
            +
                  expect(strategy).to receive(:batch_callback).with(:complete, anything).and_call_original
         | 
| 59 | 
            +
                  expect(strategy).to receive(:batch_callback).with(:success, anything).and_call_original
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  expect_any_instance_of(TestWorker).to receive(:perform)
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  Sidekiq::Testing.inline! do
         | 
| 64 | 
            +
                    worker.perform_async
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
            end
         | 
| @@ -0,0 +1,106 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::LockContext do
         | 
| 4 | 
            +
              let!(:worker) do
         | 
| 5 | 
            +
                Class.new do
         | 
| 6 | 
            +
                  include Sidekiq::Worker
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  ensure_uniqueness(
         | 
| 9 | 
            +
                    strategy: :until_executed,
         | 
| 10 | 
            +
                  )
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def perform; end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              before(:each) { stub_const('TestWorker', worker) }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              let(:lock_context) { described_class.new(context_data) }
         | 
| 19 | 
            +
              let(:context_data) { { queue: 'default', job_clazz: 'TestWorker', args: [1,2,3], kwargs: { foo: 'bar' } } }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              describe '#base_key' do
         | 
| 22 | 
            +
                let(:scope) { :per_queue }
         | 
| 23 | 
            +
                before(:each) do
         | 
| 24 | 
            +
                  TestWorker.unique_job_options[:scope] = scope
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                it 'returns matching keys for equal hashes' do
         | 
| 28 | 
            +
                  context_data[:args] = [{ foo: 'bar', bar: 'foo' }]
         | 
| 29 | 
            +
                  key1 = lock_context.base_key
         | 
| 30 | 
            +
                  lock_context.instance_variable_set(:@base_key, nil)
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  context_data[:args] = [{ bar: 'foo', foo: 'bar' }]
         | 
| 33 | 
            +
                  key2 = lock_context.base_key
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  expect(key1).to eq key2
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                context 'when scope is a Proc' do
         | 
| 39 | 
            +
                  let(:scope) { ->(queue:) { "blob" } }
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  it 'returns the base key' do
         | 
| 42 | 
            +
                    expect(lock_context.base_key).to match /^uniquejob:blob:.*/
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                context 'when scope is :global' do
         | 
| 47 | 
            +
                  let(:scope) { :global }
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  it 'returns the base key' do
         | 
| 50 | 
            +
                    expect(lock_context.base_key).to match /^uniquejob:TestWorker:.*/
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                context 'when scope is :per_queue' do
         | 
| 55 | 
            +
                  let(:scope) { :per_queue }
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  it 'returns the base key' do
         | 
| 58 | 
            +
                    expect(lock_context.base_key).to match /^uniquejob:TestWorker:default:.*/
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                context 'when scope is not a Proc, :global, or :per_queue' do
         | 
| 63 | 
            +
                  let(:scope) { 'foo' }
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  it 'returns the base key' do
         | 
| 66 | 
            +
                    expect(lock_context.base_key).to match /^uniquejob:foo:.*/
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              describe '#call_conflict_strategy' do
         | 
| 72 | 
            +
                before(:each) do
         | 
| 73 | 
            +
                  worker.unique_job_options[:on_conflict] = :raise
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                it 'invokes the conflict strategy' do
         | 
| 77 | 
            +
                  expect_any_instance_of(Joblin::Uniqueness::OnConflict::Raise).to receive(:call)
         | 
| 78 | 
            +
                  lock_context.send(:call_conflict_strategy, :perform)
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
              describe '#conflict_strategy_for' do
         | 
| 83 | 
            +
                before(:each) do
         | 
| 84 | 
            +
                  worker.unique_job_options[:on_conflict] = :raise
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                it 'resolves a united conflict strategy' do
         | 
| 88 | 
            +
                  expect(lock_context.send(:conflict_strategy_for, :perform)).to be_a Joblin::Uniqueness::OnConflict::Raise
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                it 'resolves enqueue strategy' do
         | 
| 92 | 
            +
                  worker.unique_job_options[:on_conflict] = { enqueue: :log, perform: :raise }
         | 
| 93 | 
            +
                  expect(lock_context.send(:conflict_strategy_for, :enqueue)).to be_a Joblin::Uniqueness::OnConflict::Log
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                it 'resolves perform strategy' do
         | 
| 97 | 
            +
                  worker.unique_job_options[:on_conflict] = { enqueue: :log, perform: :reject }
         | 
| 98 | 
            +
                  expect(lock_context.send(:conflict_strategy_for, :perform)).to be_a Joblin::Uniqueness::OnConflict::Reject
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                it 'resolves null strategy' do
         | 
| 102 | 
            +
                  worker.unique_job_options[:on_conflict] = { enqueue: :log }
         | 
| 103 | 
            +
                  expect(lock_context.send(:conflict_strategy_for, :perform)).to be_a Joblin::Uniqueness::OnConflict::NullStrategy
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
            end
         | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::OnConflict::Log do
         | 
| 4 | 
            +
              include_context "on_conflict specs"
         | 
| 5 | 
            +
              include_examples "OnConflict is compatible with", %i[until_executing while_executing until_executed until_and_while_executing until_expired]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              it "logs" do
         | 
| 8 | 
            +
                expect(Joblin::Uniqueness.logger).to receive(:info)
         | 
| 9 | 
            +
                on_conflict.call
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
            end
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::OnConflict::Raise do
         | 
| 4 | 
            +
              include_context "on_conflict specs"
         | 
| 5 | 
            +
              include_examples "OnConflict is compatible with", %i[until_executing while_executing until_executed until_and_while_executing until_expired]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              it "raises an error" do
         | 
| 8 | 
            +
                expect { on_conflict.call }.to raise_error(Joblin::Uniqueness::Conflict)
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::OnConflict::Reschedule do
         | 
| 4 | 
            +
              include_context "on_conflict specs"
         | 
| 5 | 
            +
              include_examples "OnConflict is compatible with", %i[while_executing]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              it "calls reenqueue" do
         | 
| 8 | 
            +
                expect(lock_context).to receive(:reenqueue) do |*args, **kwargs|
         | 
| 9 | 
            +
                  expect(Thread.current[:unique_jobs_previous_context]).to be_present
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
                on_conflict.call
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              it "reschedules successfully" do
         | 
| 15 | 
            +
                TestWorker.unique_job_options.merge!({ strategy: :until_and_while_executing, on_conflict: { enqueue: :raise, perform: :reschedule }})
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                lock_context.handle_lifecycle!(:enqueue) {}
         | 
| 18 | 
            +
                lock_context.handle_lifecycle!(:perform) {}
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                lock_context2 = Joblin::Uniqueness::Compat::Sidekiq::SidekiqLockContext.new({ jid: 'j2', queue: 'default', job_clazz: 'TestWorker'}, job_instance: {})
         | 
| 21 | 
            +
                lock_context2.handle_lifecycle!(:enqueue) {}
         | 
| 22 | 
            +
                lock_context2.handle_lifecycle!(:perform) {}
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              it "maintains a consistent lock_id" do
         | 
| 26 | 
            +
                TestWorker.clear
         | 
| 27 | 
            +
                TestWorker.unique_job_options.merge!({ strategy: :while_executing, on_conflict: :reschedule })
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                lock_context.handle_lifecycle!(:enqueue) {}
         | 
| 30 | 
            +
                lock_context.handle_lifecycle!(:perform) {}
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                TestWorker.perform_async
         | 
| 33 | 
            +
                j1 = TestWorker.jobs[0]
         | 
| 34 | 
            +
                TestWorker.perform_one
         | 
| 35 | 
            +
                j2 = TestWorker.jobs[0]
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                expect(j1).not_to eq(j2)
         | 
| 38 | 
            +
                expect(j1['uniqueness_cache_data']['lid']).to be_present
         | 
| 39 | 
            +
                expect(j1['uniqueness_cache_data']['lid']).to eq(j2['uniqueness_cache_data']['lid'])
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              it "unlocks after rescheduling" do
         | 
| 43 | 
            +
                TestWorker.clear
         | 
| 44 | 
            +
                TestWorker.unique_job_options.merge!({ strategy: :while_executing, on_conflict: :reschedule })
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                lock_context.handle_lifecycle!(:enqueue) {}
         | 
| 47 | 
            +
                lock_context.handle_lifecycle!(:perform) {}
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                TestWorker.perform_async
         | 
| 50 | 
            +
                expect(TestWorker.jobs.size).to eq(1)
         | 
| 51 | 
            +
                TestWorker.perform_one
         | 
| 52 | 
            +
                expect(TestWorker.jobs.size).to eq(1)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                lock_context.lock_strategy.send(:unlock)
         | 
| 55 | 
            +
                Sidekiq::Worker.drain_all
         | 
| 56 | 
            +
                expect(TestWorker.jobs.size).to eq(0)
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                # Run another worker to validate that the lock was released
         | 
| 59 | 
            +
                TestWorker.perform_async
         | 
| 60 | 
            +
                TestWorker.perform_one
         | 
| 61 | 
            +
                expect(TestWorker.jobs.size).to eq(0)
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::OnConflict do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              describe ".validate!" do
         | 
| 6 | 
            +
                it "passes a valid pair" do
         | 
| 7 | 
            +
                  described_class.validate!(:reject, :while_executing)
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                it "raises an error if the strategy is not valid for the given action" do
         | 
| 11 | 
            +
                  expect do
         | 
| 12 | 
            +
                    described_class.validate!(:reject, :until_executed)
         | 
| 13 | 
            +
                  end.to raise_error(ArgumentError)
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            require_relative "../spec_helper"
         | 
| 2 | 
            +
            require "joblin/uniqueness/job_uniqueness"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'sidekiq/testing'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            require 'redis'
         | 
| 7 | 
            +
            Redis.silence_deprecations = true
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            Dir[File.join(File.dirname(__FILE__), "./support/**/*.rb")].sort.each { |f| require f }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            Sidekiq::Testing.server_middleware do |chain|
         | 
| 12 | 
            +
              chain.insert_after Joblin::Batching::Compat::Sidekiq::ServerMiddleware, Joblin::Uniqueness::Compat::Sidekiq::ServerMiddleware
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            RSpec.configure do |config|
         | 
| 16 | 
            +
              config.before(:each) do
         | 
| 17 | 
            +
                Joblin.redis.flushdb
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -0,0 +1,100 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::Strategy::Base do
         | 
| 4 | 
            +
              include_context 'with TestWorker'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let!(:jid) { worker.perform_async }
         | 
| 7 | 
            +
              let(:context) { Joblin::Uniqueness::LockContext.new({ jid: jid, queue: 'default', job_clazz: 'TestWorker' }) }
         | 
| 8 | 
            +
              let(:strategy) { Joblin::Uniqueness::Strategy::UntilExecuted.new(context) }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              describe '#wrap_in_batch' do
         | 
| 11 | 
            +
                it 'does not wrap if re-enqueuing' do
         | 
| 12 | 
            +
                  Thread.current[:unique_jobs_previous_context] = context
         | 
| 13 | 
            +
                  expect(Joblin::Batching::Batch).not_to receive(:new)
         | 
| 14 | 
            +
                  strategy.send(:wrap_in_batch, &->{ })
         | 
| 15 | 
            +
                ensure
         | 
| 16 | 
            +
                  Thread.current[:unique_jobs_previous_context] = nil
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                context 'when the job fails' do
         | 
| 20 | 
            +
                  before(:each) do
         | 
| 21 | 
            +
                    TestWorker.unique_job_options[:strategy] = :until_executed
         | 
| 22 | 
            +
                    allow_any_instance_of(worker).to receive(:perform) do |w|
         | 
| 23 | 
            +
                      @bid = w.bid
         | 
| 24 | 
            +
                      raise 'error'
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  context 'unlock_on_failure: :any' do
         | 
| 29 | 
            +
                    before(:each) { TestWorker.unique_job_options[:unlock_on_failure] = :any }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    it 'unlocks on any failure' do
         | 
| 32 | 
            +
                      expect(strategy).to be_locked
         | 
| 33 | 
            +
                      expect{ Sidekiq::Worker.drain_all }.to raise_error('error')
         | 
| 34 | 
            +
                      Sidekiq::Worker.drain_all
         | 
| 35 | 
            +
                      expect(strategy).not_to be_locked
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  context 'unlock_on_failure: :death' do
         | 
| 40 | 
            +
                    before(:each) { TestWorker.unique_job_options[:unlock_on_failure] = :death }
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    it 'does not unlock on any failure' do
         | 
| 43 | 
            +
                      expect(strategy).to be_locked
         | 
| 44 | 
            +
                      expect{ Sidekiq::Worker.drain_all }.to raise_error('error')
         | 
| 45 | 
            +
                      Sidekiq::Worker.drain_all
         | 
| 46 | 
            +
                      expect(strategy).to be_locked
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    it 'it unlocks on death' do
         | 
| 50 | 
            +
                      expect{ Sidekiq::Worker.drain_all }.to raise_error('error')
         | 
| 51 | 
            +
                      Sidekiq::Worker.drain_all
         | 
| 52 | 
            +
                      expect(strategy).to be_locked
         | 
| 53 | 
            +
                      Joblin::Batching::Batch.process_dead_job(@bid, jid)
         | 
| 54 | 
            +
                      Sidekiq::Worker.drain_all
         | 
| 55 | 
            +
                      expect(strategy).not_to be_locked
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  context 'unlock_on_failure: :stagnant' do
         | 
| 60 | 
            +
                    before(:each) { TestWorker.unique_job_options[:unlock_on_failure] = :stagnant }
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    it 'does not unlock on any failure' do
         | 
| 63 | 
            +
                      expect(strategy).to be_locked
         | 
| 64 | 
            +
                      expect{ Sidekiq::Worker.drain_all }.to raise_error('error')
         | 
| 65 | 
            +
                      Sidekiq::Worker.drain_all
         | 
| 66 | 
            +
                      expect(strategy).to be_locked
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    it 'it unlocks on stagnation' do
         | 
| 70 | 
            +
                      expect{ Sidekiq::Worker.drain_all }.to raise_error('error')
         | 
| 71 | 
            +
                      Sidekiq::Worker.drain_all
         | 
| 72 | 
            +
                      expect(strategy).to be_locked
         | 
| 73 | 
            +
                      Joblin::Batching::Batch.process_dead_job(@bid, jid)
         | 
| 74 | 
            +
                      Sidekiq::Worker.drain_all
         | 
| 75 | 
            +
                      expect(strategy).not_to be_locked
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  context 'unlock_on_failure: :expire' do
         | 
| 80 | 
            +
                    before(:each) { TestWorker.unique_job_options[:unlock_on_failure] = :expire }
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                    it 'does not unlock on any failure' do
         | 
| 83 | 
            +
                      expect(strategy).to be_locked
         | 
| 84 | 
            +
                      expect{ Sidekiq::Worker.drain_all }.to raise_error('error')
         | 
| 85 | 
            +
                      Sidekiq::Worker.drain_all
         | 
| 86 | 
            +
                      expect(strategy).to be_locked
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                    it 'does not unlock on death' do
         | 
| 90 | 
            +
                      expect{ Sidekiq::Worker.drain_all }.to raise_error('error')
         | 
| 91 | 
            +
                      Sidekiq::Worker.drain_all
         | 
| 92 | 
            +
                      expect(strategy).to be_locked
         | 
| 93 | 
            +
                      Joblin::Batching::Batch.process_dead_job(@bid, jid)
         | 
| 94 | 
            +
                      Sidekiq::Worker.drain_all
         | 
| 95 | 
            +
                      expect(strategy).to be_locked
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::Strategy::UntilAndWhileExecuting do
         | 
| 4 | 
            +
              include_context 'lock strategy specs', strategy: :until_and_while_executing
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              include_examples "a lock implementation"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              describe "#on_enqueue" do
         | 
| 9 | 
            +
                it "locks the queue" do
         | 
| 10 | 
            +
                  process_one.on_enqueue {}
         | 
| 11 | 
            +
                  expect(process_one).to be_locked
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                it "does not lock the runtime lock" do
         | 
| 15 | 
            +
                  process_one.on_enqueue {}
         | 
| 16 | 
            +
                  expect(process_one.send(:runtime_lock)).to_not be_locked
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              describe "#on_perform" do
         | 
| 21 | 
            +
                it "unlocks the queue" do
         | 
| 22 | 
            +
                  process_one.on_perform do
         | 
| 23 | 
            +
                    expect(process_one).to_not be_locked
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                it "locks the runtime lock" do
         | 
| 28 | 
            +
                  process_one.on_perform do
         | 
| 29 | 
            +
                    expect(process_one.send(:runtime_lock)).to be_locked
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                it "unlocks the runtime lock after processing" do
         | 
| 34 | 
            +
                  process_one.on_perform do
         | 
| 35 | 
            +
                    process_one.send(:runtime_lock).batch_callback(:success, nil)
         | 
| 36 | 
            +
                    expect(process_one.send(:runtime_lock)).to_not be_locked
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                it "prevents other processes from executing" do
         | 
| 41 | 
            +
                  process_one.on_perform do
         | 
| 42 | 
            +
                    expect do
         | 
| 43 | 
            +
                      process_two.on_perform { }
         | 
| 44 | 
            +
                    end.to raise_error(Joblin::Uniqueness::CouldNotLockError)
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::Strategy::UntilExecuted do
         | 
| 4 | 
            +
              include_context 'lock strategy specs', strategy: :until_executed
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              include_examples "a lock implementation"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              describe "#on_enqueue" do
         | 
| 9 | 
            +
                it "locks the queue" do
         | 
| 10 | 
            +
                  process_one.on_enqueue {}
         | 
| 11 | 
            +
                  expect(process_one).to be_locked
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              describe "#on_perform" do
         | 
| 16 | 
            +
                it "unlocks after processing" do
         | 
| 17 | 
            +
                  process_one.on_enqueue {}
         | 
| 18 | 
            +
                  process_one.on_perform {}
         | 
| 19 | 
            +
                  process_one.batch_callback(:success, nil)
         | 
| 20 | 
            +
                  expect(process_one).to_not be_locked
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::Strategy::UntilExecuting do
         | 
| 4 | 
            +
              include_context 'lock strategy specs', strategy: :until_executing
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              include_examples "a lock implementation"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              describe "#on_enqueue" do
         | 
| 9 | 
            +
                it "locks the queue" do
         | 
| 10 | 
            +
                  process_one.on_enqueue {}
         | 
| 11 | 
            +
                  expect(process_one).to be_locked
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              describe "#on_perform" do
         | 
| 16 | 
            +
                it "unlocks before processing" do
         | 
| 17 | 
            +
                  process_one.on_enqueue {}
         | 
| 18 | 
            +
                  process_one.on_perform do
         | 
| 19 | 
            +
                    expect(process_one).to_not be_locked
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::Strategy::UntilExpired do
         | 
| 4 | 
            +
              include_context 'lock strategy specs', strategy: :until_expired
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              # include_examples "a lock implementation"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              describe "#on_enqueue" do
         | 
| 9 | 
            +
                it "locks the queue" do
         | 
| 10 | 
            +
                  process_one.on_enqueue {}
         | 
| 11 | 
            +
                  expect(process_one).to be_locked
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              describe "#on_perform" do
         | 
| 16 | 
            +
                it "does not unlock after processing" do
         | 
| 17 | 
            +
                  process_one.on_enqueue {}
         | 
| 18 | 
            +
                  process_one.on_perform {}
         | 
| 19 | 
            +
                  process_one.batch_callback(:success, nil)
         | 
| 20 | 
            +
                  expect(process_one).to be_locked
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            require 'uniqueness/spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Joblin::Uniqueness::Strategy::WhileExecuting do
         | 
| 4 | 
            +
              include_context 'lock strategy specs', strategy: :while_executing
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              include_examples "a lock implementation"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              describe "#on_enqueue" do
         | 
| 9 | 
            +
                it "does not lock jobs" do
         | 
| 10 | 
            +
                  expect(process_one.on_enqueue {})
         | 
| 11 | 
            +
                  expect(process_one).not_to be_locked
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  expect(process_two.on_enqueue {})
         | 
| 14 | 
            +
                  expect(process_two).not_to be_locked
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              describe "#on_perform" do
         | 
| 19 | 
            +
                it "locks the process" do
         | 
| 20 | 
            +
                  process_one.on_perform do
         | 
| 21 | 
            +
                    expect(process_one).to be_locked
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                it "prevents other processes from executing" do
         | 
| 26 | 
            +
                  process_one.on_perform do
         | 
| 27 | 
            +
                    expect do
         | 
| 28 | 
            +
                      process_two.on_perform { }
         | 
| 29 | 
            +
                    end.to raise_error(Joblin::Uniqueness::CouldNotLockError)
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         |