inst-jobs 2.0.0 → 3.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 +4 -4
- data/db/migrate/20101216224513_create_delayed_jobs.rb +9 -7
- data/db/migrate/20110531144916_cleanup_delayed_jobs_indexes.rb +8 -13
- data/db/migrate/20110610213249_optimize_delayed_jobs.rb +8 -8
- data/db/migrate/20110831210257_add_delayed_jobs_next_in_strand.rb +25 -25
- data/db/migrate/20120510004759_delayed_jobs_delete_trigger_lock_for_update.rb +4 -8
- data/db/migrate/20120531150712_drop_psql_jobs_pop_fn.rb +1 -3
- data/db/migrate/20120607164022_delayed_jobs_use_advisory_locks.rb +11 -15
- data/db/migrate/20120607181141_index_jobs_on_locked_by.rb +1 -1
- data/db/migrate/20120608191051_add_jobs_run_at_index.rb +2 -2
- data/db/migrate/20120927184213_change_delayed_jobs_handler_to_text.rb +1 -1
- data/db/migrate/20140505215510_copy_failed_jobs_original_id.rb +2 -3
- data/db/migrate/20150807133223_add_max_concurrent_to_jobs.rb +9 -13
- data/db/migrate/20151210162949_improve_max_concurrent.rb +4 -8
- data/db/migrate/20161206323555_add_back_default_string_limits_jobs.rb +3 -2
- data/db/migrate/20181217155351_speed_up_max_concurrent_triggers.rb +13 -17
- data/db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb +8 -8
- data/db/migrate/20200824222232_speed_up_max_concurrent_delete_trigger.rb +72 -77
- data/db/migrate/20200825011002_add_strand_order_override.rb +93 -97
- data/db/migrate/20210809145804_add_n_strand_index.rb +12 -0
- data/db/migrate/20210812210128_add_singleton_column.rb +200 -0
- data/db/migrate/20210917232626_add_delete_conflicting_singletons_before_unlock_trigger.rb +27 -0
- data/db/migrate/20210928174754_fix_singleton_condition_in_before_insert.rb +56 -0
- data/db/migrate/20210929204903_update_conflicting_singleton_function_to_use_index.rb +27 -0
- data/db/migrate/20211101190934_update_after_delete_trigger_for_singleton_index.rb +137 -0
- data/db/migrate/20211207094200_update_after_delete_trigger_for_singleton_transition_cases.rb +171 -0
- data/db/migrate/20211220112800_fix_singleton_race_condition_insert.rb +59 -0
- data/db/migrate/20211220113000_fix_singleton_race_condition_delete.rb +207 -0
- data/db/migrate/20220127091200_fix_singleton_unique_constraint.rb +31 -0
- data/db/migrate/20220128084800_update_insert_trigger_for_singleton_unique_constraint_change.rb +60 -0
- data/db/migrate/20220128084900_update_delete_trigger_for_singleton_unique_constraint_change.rb +209 -0
- data/db/migrate/20220203063200_remove_old_singleton_index.rb +31 -0
- data/db/migrate/20220328152900_add_failed_jobs_indicies.rb +12 -0
- data/exe/inst_jobs +3 -2
- data/lib/delayed/backend/active_record.rb +226 -168
- data/lib/delayed/backend/base.rb +119 -72
- data/lib/delayed/batch.rb +11 -9
- data/lib/delayed/cli.rb +98 -84
- data/lib/delayed/core_ext/kernel.rb +4 -2
- data/lib/delayed/daemon.rb +70 -74
- data/lib/delayed/job_tracking.rb +26 -25
- data/lib/delayed/lifecycle.rb +28 -23
- data/lib/delayed/log_tailer.rb +17 -17
- data/lib/delayed/logging.rb +13 -16
- data/lib/delayed/message_sending.rb +43 -52
- data/lib/delayed/performable_method.rb +6 -8
- data/lib/delayed/periodic.rb +72 -68
- data/lib/delayed/plugin.rb +2 -4
- data/lib/delayed/pool.rb +205 -168
- data/lib/delayed/rails_reloader_plugin.rb +30 -0
- data/lib/delayed/server/helpers.rb +6 -6
- data/lib/delayed/server.rb +51 -54
- data/lib/delayed/settings.rb +96 -81
- data/lib/delayed/testing.rb +21 -22
- data/lib/delayed/version.rb +1 -1
- data/lib/delayed/work_queue/in_process.rb +21 -17
- data/lib/delayed/work_queue/parent_process/client.rb +55 -53
- data/lib/delayed/work_queue/parent_process/server.rb +245 -207
- data/lib/delayed/work_queue/parent_process.rb +52 -53
- data/lib/delayed/worker/consul_health_check.rb +32 -33
- data/lib/delayed/worker/health_check.rb +35 -27
- data/lib/delayed/worker/null_health_check.rb +3 -1
- data/lib/delayed/worker/process_helper.rb +11 -12
- data/lib/delayed/worker.rb +257 -244
- data/lib/delayed/yaml_extensions.rb +12 -10
- data/lib/delayed_job.rb +37 -37
- data/lib/inst-jobs.rb +1 -1
- data/spec/active_record_job_spec.rb +152 -139
- data/spec/delayed/cli_spec.rb +7 -7
- data/spec/delayed/daemon_spec.rb +10 -9
- data/spec/delayed/message_sending_spec.rb +16 -9
- data/spec/delayed/periodic_spec.rb +14 -21
- data/spec/delayed/server_spec.rb +38 -38
- data/spec/delayed/settings_spec.rb +26 -25
- data/spec/delayed/work_queue/in_process_spec.rb +8 -9
- data/spec/delayed/work_queue/parent_process/client_spec.rb +17 -12
- data/spec/delayed/work_queue/parent_process/server_spec.rb +118 -42
- data/spec/delayed/work_queue/parent_process_spec.rb +21 -23
- data/spec/delayed/worker/consul_health_check_spec.rb +37 -50
- data/spec/delayed/worker/health_check_spec.rb +60 -52
- data/spec/delayed/worker_spec.rb +53 -24
- data/spec/sample_jobs.rb +45 -15
- data/spec/shared/delayed_batch.rb +74 -67
- data/spec/shared/delayed_method.rb +143 -102
- data/spec/shared/performable_method.rb +39 -38
- data/spec/shared/shared_backend.rb +801 -440
- data/spec/shared/testing.rb +14 -14
- data/spec/shared/worker.rb +157 -149
- data/spec/shared_jobs_specs.rb +13 -13
- data/spec/spec_helper.rb +57 -56
- metadata +183 -103
- data/lib/delayed/backend/redis/bulk_update.lua +0 -50
- data/lib/delayed/backend/redis/destroy_job.lua +0 -2
- data/lib/delayed/backend/redis/enqueue.lua +0 -29
- data/lib/delayed/backend/redis/fail_job.lua +0 -5
- data/lib/delayed/backend/redis/find_available.lua +0 -3
- data/lib/delayed/backend/redis/functions.rb +0 -59
- data/lib/delayed/backend/redis/get_and_lock_next_available.lua +0 -17
- data/lib/delayed/backend/redis/includes/jobs_common.lua +0 -203
- data/lib/delayed/backend/redis/job.rb +0 -535
- data/lib/delayed/backend/redis/set_running.lua +0 -5
- data/lib/delayed/backend/redis/tickle_strand.lua +0 -2
- data/spec/gemfiles/42.gemfile +0 -7
- data/spec/gemfiles/50.gemfile +0 -7
- data/spec/gemfiles/51.gemfile +0 -7
- data/spec/gemfiles/52.gemfile +0 -7
- data/spec/gemfiles/60.gemfile +0 -7
- data/spec/redis_job_spec.rb +0 -148
| @@ -1,131 +1,183 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 4 | 
            -
               | 
| 3 | 
            +
            module UnlessInJob
         | 
| 4 | 
            +
              class << self
         | 
| 5 | 
            +
                attr_accessor :runs
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def run
         | 
| 8 | 
            +
                  self.runs += 1
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def run_later
         | 
| 12 | 
            +
                  delay(synchronous: Delayed::Job.in_delayed_job?).run
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            shared_examples_for "random ruby objects" do
         | 
| 18 | 
            +
              def set_queue(name) # rubocop:disable Naming/AccessorMethodName
         | 
| 5 19 | 
             
                old_name = Delayed::Settings.queue
         | 
| 6 20 | 
             
                Delayed::Settings.queue = name
         | 
| 7 21 | 
             
              ensure
         | 
| 8 22 | 
             
                Delayed::Settings.queue = old_name
         | 
| 9 23 | 
             
              end
         | 
| 10 24 |  | 
| 11 | 
            -
              it " | 
| 25 | 
            +
              it "respond_toes :delay method" do
         | 
| 12 26 | 
             
                Object.new.respond_to?(:delay)
         | 
| 13 27 | 
             
              end
         | 
| 14 28 |  | 
| 15 | 
            -
              it " | 
| 16 | 
            -
                 | 
| 29 | 
            +
              it "raises a ArgumentError if delay is called but the target method doesn't exist" do
         | 
| 30 | 
            +
                expect { Object.new.delay.method_that_deos_not_exist }.to raise_error(NoMethodError)
         | 
| 17 31 | 
             
              end
         | 
| 18 32 |  | 
| 19 | 
            -
              it " | 
| 20 | 
            -
                 | 
| 33 | 
            +
              it "adds a new entry to the job table when delay is called on it" do
         | 
| 34 | 
            +
                expect { Object.new.delay.to_s }.to change { Delayed::Job.jobs_count(:current) }.by(1)
         | 
| 21 35 | 
             
              end
         | 
| 22 36 |  | 
| 23 | 
            -
              it " | 
| 24 | 
            -
                 | 
| 37 | 
            +
              it "adds a new entry to the job table when delay is called on it with a queue" do
         | 
| 38 | 
            +
                expect { Object.new.delay(queue: "testqueue").to_s }.to change {
         | 
| 39 | 
            +
                                                                          Delayed::Job.jobs_count(:current, "testqueue")
         | 
| 40 | 
            +
                                                                        }.by(1)
         | 
| 25 41 | 
             
              end
         | 
| 26 42 |  | 
| 27 | 
            -
              it " | 
| 28 | 
            -
                 | 
| 43 | 
            +
              it "adds a new entry to the job table when delay is called on the class" do
         | 
| 44 | 
            +
                expect { Object.delay.to_s }.to change { Delayed::Job.jobs_count(:current) }.by(1)
         | 
| 29 45 | 
             
              end
         | 
| 30 46 |  | 
| 31 | 
            -
              it " | 
| 32 | 
            -
                 | 
| 47 | 
            +
              it "adds a new entry to the job table when delay is called on the class with a queue" do
         | 
| 48 | 
            +
                expect { Object.delay(queue: "testqueue").to_s }.to change { Delayed::Job.jobs_count(:current, "testqueue") }.by(1)
         | 
| 33 49 | 
             
              end
         | 
| 34 50 |  | 
| 35 51 | 
             
              context "class methods" do
         | 
| 36 52 | 
             
                context "handle_asynchronously" do
         | 
| 37 | 
            -
                  it " | 
| 53 | 
            +
                  it "works with default_async" do
         | 
| 38 54 | 
             
                    klass = Class.new do
         | 
| 39 55 | 
             
                      attr_reader :ran
         | 
| 40 | 
            -
             | 
| 56 | 
            +
             | 
| 57 | 
            +
                      def test_method
         | 
| 58 | 
            +
                        @ran = true
         | 
| 59 | 
            +
                      end
         | 
| 41 60 | 
             
                      handle_asynchronously :test_method
         | 
| 42 61 | 
             
                    end
         | 
| 43 62 | 
             
                    obj = klass.new
         | 
| 44 | 
            -
                     | 
| 45 | 
            -
                    obj.ran. | 
| 46 | 
            -
                     | 
| 47 | 
            -
                    obj.ran. | 
| 63 | 
            +
                    expect { obj.test_method }.to change { Delayed::Job.jobs_count(:current) }.by(1)
         | 
| 64 | 
            +
                    expect(obj.ran).to be_falsey
         | 
| 65 | 
            +
                    expect { obj.test_method(synchronous: true) }.not_to(change { Delayed::Job.jobs_count(:current) })
         | 
| 66 | 
            +
                    expect(obj.ran).to be true
         | 
| 48 67 | 
             
                  end
         | 
| 49 68 |  | 
| 50 | 
            -
                  it  | 
| 69 | 
            +
                  it "must work with enqueue args that are lambdas" do
         | 
| 51 70 | 
             
                    klass = Class.new do
         | 
| 52 71 | 
             
                      attr_reader :ran
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                       | 
| 72 | 
            +
             | 
| 73 | 
            +
                      def test_method
         | 
| 74 | 
            +
                        @ran = true
         | 
| 75 | 
            +
                      end
         | 
| 76 | 
            +
                      handle_asynchronously :test_method, singleton: ->(obj) { "foobar:#{obj.object_id}" }
         | 
| 55 77 | 
             
                    end
         | 
| 56 78 |  | 
| 57 79 | 
             
                    obj = klass.new
         | 
| 58 | 
            -
                     | 
| 80 | 
            +
                    expect { obj.test_method }.to change { Delayed::Job.jobs_count(:current) }.by(1)
         | 
| 59 81 | 
             
                  end
         | 
| 60 82 |  | 
| 61 | 
            -
                  it  | 
| 83 | 
            +
                  it "must work with kwargs in the original method" do
         | 
| 62 84 | 
             
                    klass = Class.new do
         | 
| 63 85 | 
             
                      attr_reader :run
         | 
| 64 | 
            -
             | 
| 86 | 
            +
             | 
| 87 | 
            +
                      def test_method(my_kwarg: nil)
         | 
| 88 | 
            +
                        @run = my_kwarg
         | 
| 89 | 
            +
                      end
         | 
| 65 90 | 
             
                      handle_asynchronously :test_method
         | 
| 66 91 |  | 
| 67 | 
            -
                      def other_test(arg) | 
| 92 | 
            +
                      def other_test(arg)
         | 
| 93 | 
            +
                        @foo = arg
         | 
| 94 | 
            +
                      end
         | 
| 68 95 | 
             
                      handle_asynchronously :other_test
         | 
| 69 96 | 
             
                    end
         | 
| 70 97 |  | 
| 71 98 | 
             
                    obj = klass.new
         | 
| 72 | 
            -
                    obj.test_method(my_kwarg:  | 
| 73 | 
            -
                    expect(obj.run).to eq  | 
| 99 | 
            +
                    obj.test_method(my_kwarg: "foo", synchronous: true)
         | 
| 100 | 
            +
                    expect(obj.run).to eq "foo"
         | 
| 74 101 | 
             
                  end
         | 
| 75 102 |  | 
| 76 | 
            -
                  it " | 
| 103 | 
            +
                  it "sends along enqueue args and args" do
         | 
| 77 104 | 
             
                    klass = Class.new do
         | 
| 78 105 | 
             
                      attr_accessor :ran
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                       | 
| 106 | 
            +
             | 
| 107 | 
            +
                      def test_method(*args)
         | 
| 108 | 
            +
                        @ran = args
         | 
| 109 | 
            +
                      end
         | 
| 110 | 
            +
                      handle_asynchronously(:test_method, enqueue_arg1: :thing)
         | 
| 81 111 | 
             
                    end
         | 
| 82 112 | 
             
                    obj = klass.new
         | 
| 83 | 
            -
                    method = double | 
| 84 | 
            -
             | 
| 85 | 
            -
                    expect(Delayed::PerformableMethod).to receive(:new) | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 113 | 
            +
                    method = double
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                    expect(Delayed::PerformableMethod).to receive(:new)
         | 
| 116 | 
            +
                      .with(obj,
         | 
| 117 | 
            +
                            :test_method,
         | 
| 118 | 
            +
                            args: [1, 2, 3],
         | 
| 119 | 
            +
                            kwargs: { synchronous: true },
         | 
| 120 | 
            +
                            on_failure: nil,
         | 
| 121 | 
            +
                            on_permanent_failure: nil,
         | 
| 122 | 
            +
                            sender: obj)
         | 
| 123 | 
            +
                      .and_return(method)
         | 
| 124 | 
            +
                    expect(Delayed::Job).to receive(:enqueue).with(method, enqueue_arg1: :thing)
         | 
| 125 | 
            +
                    obj.test_method(1, 2, 3)
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                    expect(Delayed::PerformableMethod).to receive(:new)
         | 
| 128 | 
            +
                      .with(obj,
         | 
| 129 | 
            +
                            :test_method,
         | 
| 130 | 
            +
                            args: [4],
         | 
| 131 | 
            +
                            kwargs: { synchronous: true },
         | 
| 132 | 
            +
                            on_failure: nil,
         | 
| 133 | 
            +
                            on_permanent_failure: nil,
         | 
| 134 | 
            +
                            sender: obj)
         | 
| 135 | 
            +
                      .and_return(method)
         | 
| 136 | 
            +
                    expect(Delayed::Job).to receive(:enqueue).with(method, enqueue_arg1: :thing)
         | 
| 91 137 | 
             
                    obj.test_method(4)
         | 
| 92 138 |  | 
| 93 | 
            -
                    obj.ran. | 
| 139 | 
            +
                    expect(obj.ran).to be_nil
         | 
| 94 140 | 
             
                    obj.test_method(7, synchronous: true)
         | 
| 95 | 
            -
                    obj.ran. | 
| 141 | 
            +
                    expect(obj.ran).to eq([7])
         | 
| 96 142 | 
             
                    obj.ran = nil
         | 
| 97 | 
            -
                    obj.ran. | 
| 98 | 
            -
                    obj.test_method(8,9, synchronous: true)
         | 
| 99 | 
            -
                    obj.ran. | 
| 143 | 
            +
                    expect(obj.ran).to be_nil
         | 
| 144 | 
            +
                    obj.test_method(8, 9, synchronous: true)
         | 
| 145 | 
            +
                    expect(obj.ran).to eq([8, 9])
         | 
| 100 146 | 
             
                  end
         | 
| 101 147 |  | 
| 102 | 
            -
                  it " | 
| 148 | 
            +
                  it "handles punctuation correctly" do
         | 
| 103 149 | 
             
                    klass = Class.new do
         | 
| 104 150 | 
             
                      attr_reader :ran
         | 
| 105 | 
            -
             | 
| 151 | 
            +
             | 
| 152 | 
            +
                      def test_method?
         | 
| 153 | 
            +
                        @ran = true
         | 
| 154 | 
            +
                      end
         | 
| 106 155 | 
             
                      handle_asynchronously :test_method?
         | 
| 107 156 | 
             
                    end
         | 
| 108 157 | 
             
                    obj = klass.new
         | 
| 109 | 
            -
                     | 
| 110 | 
            -
                    obj.ran. | 
| 111 | 
            -
                     | 
| 112 | 
            -
                    obj.ran. | 
| 158 | 
            +
                    expect { obj.test_method? }.to change { Delayed::Job.jobs_count(:current) }.by(1)
         | 
| 159 | 
            +
                    expect(obj.ran).to be_falsey
         | 
| 160 | 
            +
                    expect { obj.test_method?(synchronous: true) }.not_to(change { Delayed::Job.jobs_count(:current) })
         | 
| 161 | 
            +
                    expect(obj.ran).to be true
         | 
| 113 162 | 
             
                  end
         | 
| 114 163 |  | 
| 115 | 
            -
                  it " | 
| 164 | 
            +
                  it "handles assignment punctuation correctly" do
         | 
| 116 165 | 
             
                    klass = Class.new do
         | 
| 117 166 | 
             
                      attr_reader :ran
         | 
| 118 | 
            -
             | 
| 167 | 
            +
             | 
| 168 | 
            +
                      def test_method=(val)
         | 
| 169 | 
            +
                        @ran = val
         | 
| 170 | 
            +
                      end
         | 
| 119 171 | 
             
                      handle_asynchronously :test_method=
         | 
| 120 172 | 
             
                    end
         | 
| 121 173 | 
             
                    obj = klass.new
         | 
| 122 | 
            -
                     | 
| 123 | 
            -
                    obj.ran. | 
| 124 | 
            -
                     | 
| 125 | 
            -
                    obj.ran. | 
| 174 | 
            +
                    expect { obj.test_method = 3 }.to change { Delayed::Job.jobs_count(:current) }.by(1)
         | 
| 175 | 
            +
                    expect(obj.ran).to be_nil
         | 
| 176 | 
            +
                    expect { obj.send(:test_method=, 5, synchronous: true) }.not_to(change { Delayed::Job.jobs_count(:current) })
         | 
| 177 | 
            +
                    expect(obj.ran).to eq(5)
         | 
| 126 178 | 
             
                  end
         | 
| 127 179 |  | 
| 128 | 
            -
                  it " | 
| 180 | 
            +
                  it "correctlies sort out method accessibility" do
         | 
| 129 181 | 
             
                    klass1 = Class.new do
         | 
| 130 182 | 
             
                      def test_method; end
         | 
| 131 183 | 
             
                      handle_asynchronously :test_method
         | 
| @@ -133,114 +185,103 @@ shared_examples_for 'random ruby objects' do | |
| 133 185 |  | 
| 134 186 | 
             
                    klass2 = Class.new do
         | 
| 135 187 | 
             
                      protected
         | 
| 188 | 
            +
             | 
| 136 189 | 
             
                      def test_method; end
         | 
| 137 190 | 
             
                      handle_asynchronously :test_method
         | 
| 138 191 | 
             
                    end
         | 
| 139 192 |  | 
| 140 193 | 
             
                    klass3 = Class.new do
         | 
| 141 194 | 
             
                      private
         | 
| 195 | 
            +
             | 
| 142 196 | 
             
                      def test_method; end
         | 
| 143 197 | 
             
                      handle_asynchronously :test_method
         | 
| 144 198 | 
             
                    end
         | 
| 145 199 |  | 
| 146 | 
            -
                    klass1.public_method_defined?(:test_method). | 
| 147 | 
            -
                    klass2.protected_method_defined?(:test_method). | 
| 148 | 
            -
                    klass3.private_method_defined?(:test_method). | 
| 200 | 
            +
                    expect(klass1.public_method_defined?(:test_method)).to be true
         | 
| 201 | 
            +
                    expect(klass2.protected_method_defined?(:test_method)).to be true
         | 
| 202 | 
            +
                    expect(klass3.private_method_defined?(:test_method)).to be true
         | 
| 149 203 | 
             
                  end
         | 
| 150 204 | 
             
                end
         | 
| 151 205 | 
             
              end
         | 
| 152 206 |  | 
| 153 | 
            -
              it " | 
| 154 | 
            -
                story = Story.create : | 
| 207 | 
            +
              it "calls send later on methods which are wrapped with handle_asynchronously" do
         | 
| 208 | 
            +
                story = Story.create text: "Once upon..."
         | 
| 155 209 |  | 
| 156 210 | 
             
                expect { story.whatever(1, 5) }.to change { Delayed::Job.jobs_count(:current) }.by(1)
         | 
| 157 211 |  | 
| 158 212 | 
             
                job = Delayed::Job.list_jobs(:current, 1).first
         | 
| 159 | 
            -
                job.payload_object.class. | 
| 160 | 
            -
                job.payload_object.method. | 
| 161 | 
            -
                job.payload_object.args. | 
| 162 | 
            -
                job.payload_object.kwargs. | 
| 163 | 
            -
                job.payload_object.perform. | 
| 213 | 
            +
                expect(job.payload_object.class).to   eq(Delayed::PerformableMethod)
         | 
| 214 | 
            +
                expect(job.payload_object.method).to  eq(:whatever)
         | 
| 215 | 
            +
                expect(job.payload_object.args).to    eq([1, 5])
         | 
| 216 | 
            +
                expect(job.payload_object.kwargs).to  eq({ synchronous: true })
         | 
| 217 | 
            +
                expect(job.payload_object.perform).to eq("Once upon...")
         | 
| 164 218 | 
             
              end
         | 
| 165 219 |  | 
| 166 220 | 
             
              context "delay" do
         | 
| 167 | 
            -
                it " | 
| 221 | 
            +
                it "uses the default queue if there is one" do
         | 
| 168 222 | 
             
                  set_queue("testqueue") do
         | 
| 169 223 | 
             
                    "string".delay.reverse
         | 
| 170 224 | 
             
                    job = Delayed::Job.list_jobs(:current, 1).first
         | 
| 171 | 
            -
                    job.queue. | 
| 225 | 
            +
                    expect(job.queue).to eq("testqueue")
         | 
| 172 226 |  | 
| 173 227 | 
             
                    "string".delay(queue: nil).reverse
         | 
| 174 228 | 
             
                    job2 = Delayed::Job.list_jobs(:current, 2).last
         | 
| 175 | 
            -
                    job2.queue. | 
| 229 | 
            +
                    expect(job2.queue).to eq("testqueue")
         | 
| 176 230 | 
             
                  end
         | 
| 177 231 | 
             
                end
         | 
| 178 232 |  | 
| 179 | 
            -
                it " | 
| 233 | 
            +
                it "requires a queue" do
         | 
| 180 234 | 
             
                  expect { set_queue(nil) }.to raise_error(ArgumentError)
         | 
| 181 235 | 
             
                end
         | 
| 182 236 | 
             
              end
         | 
| 183 237 |  | 
| 184 238 | 
             
              context "delay with run_at" do
         | 
| 185 | 
            -
                it " | 
| 186 | 
            -
                   | 
| 239 | 
            +
                it "queues a new job" do
         | 
| 240 | 
            +
                  expect do
         | 
| 187 241 | 
             
                    "string".delay(run_at: 1.hour.from_now).length
         | 
| 188 | 
            -
                  end. | 
| 242 | 
            +
                  end.to change { Delayed::Job.jobs_count(:future) }.by(1)
         | 
| 189 243 | 
             
                end
         | 
| 190 244 |  | 
| 191 | 
            -
                it " | 
| 245 | 
            +
                it "schedules the job in the future" do
         | 
| 192 246 | 
             
                  time = 1.hour.from_now
         | 
| 193 247 | 
             
                  "string".delay(run_at: time).length
         | 
| 194 248 | 
             
                  job = Delayed::Job.list_jobs(:future, 1).first
         | 
| 195 | 
            -
                  job.run_at.to_i. | 
| 249 | 
            +
                  expect(job.run_at.to_i).to eq(time.to_i)
         | 
| 196 250 | 
             
                end
         | 
| 197 251 |  | 
| 198 | 
            -
                it " | 
| 199 | 
            -
                  "string".delay(run_at: 1.hour.from_now).count( | 
| 252 | 
            +
                it "stores payload as PerformableMethod" do
         | 
| 253 | 
            +
                  "string".delay(run_at: 1.hour.from_now).count("r")
         | 
| 200 254 | 
             
                  job = Delayed::Job.list_jobs(:future, 1).first
         | 
| 201 | 
            -
                  job.payload_object.class. | 
| 202 | 
            -
                  job.payload_object.method. | 
| 203 | 
            -
                  job.payload_object.args. | 
| 204 | 
            -
                  job.payload_object.perform. | 
| 255 | 
            +
                  expect(job.payload_object.class).to   eq(Delayed::PerformableMethod)
         | 
| 256 | 
            +
                  expect(job.payload_object.method).to  eq(:count)
         | 
| 257 | 
            +
                  expect(job.payload_object.args).to    eq(["r"])
         | 
| 258 | 
            +
                  expect(job.payload_object.perform).to eq(1)
         | 
| 205 259 | 
             
                end
         | 
| 206 260 |  | 
| 207 | 
            -
                it " | 
| 261 | 
            +
                it "uses the default queue if there is one" do
         | 
| 208 262 | 
             
                  set_queue("testqueue") do
         | 
| 209 263 | 
             
                    "string".delay(run_at: 1.hour.from_now).reverse
         | 
| 210 264 | 
             
                    job = Delayed::Job.list_jobs(:current, 1).first
         | 
| 211 | 
            -
                    job.queue. | 
| 265 | 
            +
                    expect(job.queue).to eq("testqueue")
         | 
| 212 266 | 
             
                  end
         | 
| 213 267 | 
             
                end
         | 
| 214 268 | 
             
              end
         | 
| 215 269 |  | 
| 216 270 | 
             
              describe "delay with synchronous argument" do
         | 
| 217 | 
            -
                module UnlessInJob
         | 
| 218 | 
            -
                  @runs = 0
         | 
| 219 | 
            -
                  def self.runs; @runs; end
         | 
| 220 | 
            -
             | 
| 221 | 
            -
                  def self.run
         | 
| 222 | 
            -
                    @runs += 1
         | 
| 223 | 
            -
                  end
         | 
| 224 | 
            -
             | 
| 225 | 
            -
                  def self.run_later
         | 
| 226 | 
            -
                    self.delay(synchronous: Delayed::Job.in_delayed_job?).run
         | 
| 227 | 
            -
                  end
         | 
| 228 | 
            -
                end
         | 
| 229 | 
            -
             | 
| 230 271 | 
             
                before do
         | 
| 231 | 
            -
                  UnlessInJob. | 
| 272 | 
            +
                  UnlessInJob.runs = 0
         | 
| 232 273 | 
             
                end
         | 
| 233 274 |  | 
| 234 | 
            -
                it " | 
| 275 | 
            +
                it "performs immediately if in job" do
         | 
| 235 276 | 
             
                  UnlessInJob.delay.run_later
         | 
| 236 277 | 
             
                  job = Delayed::Job.list_jobs(:current, 1).first
         | 
| 237 278 | 
             
                  job.invoke_job
         | 
| 238 | 
            -
                  UnlessInJob.runs. | 
| 279 | 
            +
                  expect(UnlessInJob.runs).to eq(1)
         | 
| 239 280 | 
             
                end
         | 
| 240 281 |  | 
| 241 | 
            -
                it " | 
| 282 | 
            +
                it "queues up for later if not in job" do
         | 
| 242 283 | 
             
                  UnlessInJob.run_later
         | 
| 243 | 
            -
                  UnlessInJob.runs. | 
| 284 | 
            +
                  expect(UnlessInJob.runs).to eq(0)
         | 
| 244 285 | 
             
                end
         | 
| 245 286 | 
             
              end
         | 
| 246 287 | 
             
            end
         | 
| @@ -1,73 +1,74 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            shared_examples_for  | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
                story = Story.create :text => 'Once upon...'
         | 
| 3 | 
            +
            shared_examples_for "Delayed::PerformableMethod" do
         | 
| 4 | 
            +
              it "does not ignore ActiveRecord::RecordNotFound errors because they are not always permanent" do
         | 
| 5 | 
            +
                story = Story.create text: "Once upon..."
         | 
| 7 6 | 
             
                p = Delayed::PerformableMethod.new(story, :tell)
         | 
| 8 7 | 
             
                story.destroy
         | 
| 9 | 
            -
                 | 
| 8 | 
            +
                expect { YAML.load(p.to_yaml) }.to raise_error(Delayed::Backend::RecordNotFound)
         | 
| 10 9 | 
             
              end
         | 
| 11 10 |  | 
| 12 | 
            -
              it " | 
| 13 | 
            -
                story = Story.create : | 
| 11 | 
            +
              it "stores the object using native YAML even if its an active record" do
         | 
| 12 | 
            +
                story = Story.create text: "Once upon..."
         | 
| 14 13 | 
             
                p = Delayed::PerformableMethod.new(story, :tell)
         | 
| 15 | 
            -
                p.class. | 
| 16 | 
            -
                p.object. | 
| 17 | 
            -
                p.method. | 
| 18 | 
            -
                p.args. | 
| 19 | 
            -
                p.perform. | 
| 14 | 
            +
                expect(p.class).to   eq(Delayed::PerformableMethod)
         | 
| 15 | 
            +
                expect(p.object).to  eq(story)
         | 
| 16 | 
            +
                expect(p.method).to  eq(:tell)
         | 
| 17 | 
            +
                expect(p.args).to    eq([])
         | 
| 18 | 
            +
                expect(p.perform).to eq("Once upon...")
         | 
| 20 19 | 
             
              end
         | 
| 21 20 |  | 
| 22 | 
            -
              it " | 
| 23 | 
            -
                Story.create!(: | 
| 21 | 
            +
              it "allows class methods to be called on ActiveRecord models" do
         | 
| 22 | 
            +
                Story.create!(text: "Once upon a...")
         | 
| 24 23 | 
             
                p = Delayed::PerformableMethod.new(Story, :count)
         | 
| 25 | 
            -
                 | 
| 24 | 
            +
                expect { expect(p.send(:perform)).to be 1 }.not_to raise_error
         | 
| 26 25 | 
             
              end
         | 
| 27 26 |  | 
| 28 | 
            -
              it " | 
| 27 | 
            +
              it "allows class methods to be called" do
         | 
| 29 28 | 
             
                p = Delayed::PerformableMethod.new(StoryReader, :reverse, args: ["ohai"])
         | 
| 30 | 
            -
                 | 
| 29 | 
            +
                expect { expect(p.send(:perform)).to eq("iaho") }.not_to raise_error
         | 
| 31 30 | 
             
              end
         | 
| 32 31 |  | 
| 33 | 
            -
              it " | 
| 32 | 
            +
              it "allows module methods to be called" do
         | 
| 34 33 | 
             
                p = Delayed::PerformableMethod.new(MyReverser, :reverse, args: ["ohai"])
         | 
| 35 | 
            -
                 | 
| 34 | 
            +
                expect { expect(p.send(:perform)).to eq("iaho") }.not_to raise_error
         | 
| 36 35 | 
             
              end
         | 
| 37 36 |  | 
| 38 | 
            -
              it " | 
| 39 | 
            -
                story = Story.create : | 
| 37 | 
            +
              it "stores arguments as native YAML if they are active record objects" do
         | 
| 38 | 
            +
                story = Story.create text: "Once upon..."
         | 
| 40 39 | 
             
                reader = StoryReader.new
         | 
| 41 40 | 
             
                p = Delayed::PerformableMethod.new(reader, :read, args: [story])
         | 
| 42 | 
            -
                p.class. | 
| 43 | 
            -
                p.method. | 
| 44 | 
            -
                p.args. | 
| 45 | 
            -
                p.perform. | 
| 41 | 
            +
                expect(p.class).to   eq(Delayed::PerformableMethod)
         | 
| 42 | 
            +
                expect(p.method).to  eq(:read)
         | 
| 43 | 
            +
                expect(p.args).to    eq([story])
         | 
| 44 | 
            +
                expect(p.perform).to eq("Epilog: Once upon...")
         | 
| 46 45 | 
             
              end
         | 
| 47 46 |  | 
| 48 | 
            -
              it " | 
| 49 | 
            -
                story = Story.create : | 
| 47 | 
            +
              it "deeplies de-AR-ize arguments in full name" do
         | 
| 48 | 
            +
                story = Story.create text: "Once upon..."
         | 
| 50 49 | 
             
                reader = StoryReader.new
         | 
| 51 | 
            -
                p = Delayed::PerformableMethod.new(reader, :read, args: [[ | 
| 52 | 
            -
                p.full_name. | 
| 50 | 
            +
                p = Delayed::PerformableMethod.new(reader, :read, args: [["arg1", story, { [:key, 1] => story }]])
         | 
| 51 | 
            +
                expect(p.full_name).to eq(
         | 
| 52 | 
            +
                  "StoryReader#read([\"arg1\", Story.find(#{story.id}), {[:key, 1] => Story.find(#{story.id})}])"
         | 
| 53 | 
            +
                )
         | 
| 53 54 | 
             
              end
         | 
| 54 55 |  | 
| 55 | 
            -
              it " | 
| 56 | 
            -
                story = Story.create : | 
| 56 | 
            +
              it "calls the on_failure callback" do
         | 
| 57 | 
            +
                story = Story.create text: "wat"
         | 
| 57 58 | 
             
                p = Delayed::PerformableMethod.new(story, :tell, on_failure: :text=)
         | 
| 58 | 
            -
                p.send(:on_failure,  | 
| 59 | 
            -
                story.text. | 
| 59 | 
            +
                p.send(:on_failure, "fail")
         | 
| 60 | 
            +
                expect(story.text).to eq("fail")
         | 
| 60 61 | 
             
              end
         | 
| 61 62 |  | 
| 62 | 
            -
              it " | 
| 63 | 
            -
                story = Story.create : | 
| 63 | 
            +
              it "calls the on_permanent_failure callback" do
         | 
| 64 | 
            +
                story = Story.create text: "wat"
         | 
| 64 65 | 
             
                p = Delayed::PerformableMethod.new(story, :tell, on_permanent_failure: :text=)
         | 
| 65 | 
            -
                p.send(:on_permanent_failure,  | 
| 66 | 
            -
                story.text. | 
| 66 | 
            +
                p.send(:on_permanent_failure, "fail_frd")
         | 
| 67 | 
            +
                expect(story.text).to eq("fail_frd")
         | 
| 67 68 | 
             
              end
         | 
| 68 69 |  | 
| 69 70 | 
             
              it "can still generate a name with no kwargs" do
         | 
| 70 | 
            -
                story = Story.create : | 
| 71 | 
            +
                story = Story.create text: "wat"
         | 
| 71 72 | 
             
                p = Delayed::PerformableMethod.new(story, :tell, kwargs: nil)
         | 
| 72 73 | 
             
                expect(p.full_name).to eq("Story.find(#{story.id}).tell()")
         | 
| 73 74 | 
             
              end
         |