switchman-inst-jobs 3.2.4 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/db/migrate/20101216224513_create_delayed_jobs.rb +1 -1
- data/db/migrate/20110208031356_add_delayed_jobs_tag.rb +1 -1
- data/db/migrate/20110426161613_add_delayed_jobs_max_attempts.rb +1 -1
- data/db/migrate/20110516225834_add_delayed_jobs_strand.rb +1 -1
- data/db/migrate/20110531144916_cleanup_delayed_jobs_indexes.rb +1 -1
- data/db/migrate/20110610213249_optimize_delayed_jobs.rb +1 -1
- data/db/migrate/20110831210257_add_delayed_jobs_next_in_strand.rb +1 -1
- data/db/migrate/20120510004759_delayed_jobs_delete_trigger_lock_for_update.rb +1 -1
- data/db/migrate/20120531150712_drop_psql_jobs_pop_fn.rb +1 -1
- data/db/migrate/20120607164022_delayed_jobs_use_advisory_locks.rb +1 -1
- data/db/migrate/20120607181141_index_jobs_on_locked_by.rb +2 -2
- 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/20140505215131_add_failed_jobs_original_job_id.rb +1 -1
- data/db/migrate/20140505215510_copy_failed_jobs_original_id.rb +2 -2
- data/db/migrate/20140505223637_drop_failed_jobs_original_id.rb +1 -1
- data/db/migrate/20140512213941_add_source_to_jobs.rb +1 -1
- data/db/migrate/20150807133223_add_max_concurrent_to_jobs.rb +1 -1
- data/db/migrate/20151123210429_add_expires_at_to_jobs.rb +1 -1
- data/db/migrate/20151210162949_improve_max_concurrent.rb +1 -1
- data/db/migrate/20161206323555_add_back_default_string_limits_jobs.rb +1 -1
- data/db/migrate/20170308045400_add_shard_id_to_delayed_jobs.rb +1 -11
- data/db/migrate/20170308045401_add_delayed_jobs_shard_id_to_switchman_shards.rb +5 -0
- data/db/migrate/20181217155351_speed_up_max_concurrent_triggers.rb +1 -1
- data/db/migrate/20190726154743_make_critical_columns_not_null.rb +1 -1
- data/db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb +2 -2
- data/db/migrate/20200824222232_speed_up_max_concurrent_delete_trigger.rb +1 -1
- data/db/migrate/20200825011002_add_strand_order_override.rb +2 -2
- data/lib/switchman_inst_jobs/active_record/connection_adapters/connection_pool.rb +15 -0
- data/lib/switchman_inst_jobs/delayed/backend/base.rb +10 -9
- data/lib/switchman_inst_jobs/delayed/pool.rb +1 -1
- data/lib/switchman_inst_jobs/delayed/worker/health_check.rb +10 -12
- data/lib/switchman_inst_jobs/delayed/worker.rb +2 -2
- data/lib/switchman_inst_jobs/engine.rb +6 -4
- data/lib/switchman_inst_jobs/jobs_migrator.rb +23 -21
- data/lib/switchman_inst_jobs/switchman/shard.rb +8 -21
- data/lib/switchman_inst_jobs/version.rb +1 -1
- data/lib/switchman_inst_jobs.rb +8 -0
- metadata +39 -36
- data/db/migrate/20210809145804_add_n_strand_index.rb +0 -12
- data/db/migrate/20210812210128_add_singleton_column.rb +0 -200
- data/db/migrate/20210917232626_add_delete_conflicting_singletons_before_unlock_trigger.rb +0 -27
- data/db/migrate/20210928174754_fix_singleton_condition_in_before_insert.rb +0 -56
- data/db/migrate/20210929204903_update_conflicting_singleton_function_to_use_index.rb +0 -27
| @@ -22,12 +22,12 @@ module SwitchmanInstJobs | |
| 22 22 | 
             
                  def hold_jobs!(wait: false)
         | 
| 23 23 | 
             
                    self.jobs_held = true
         | 
| 24 24 | 
             
                    save! if changed?
         | 
| 25 | 
            -
                    delayed_jobs_shard.activate( | 
| 25 | 
            +
                    delayed_jobs_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
         | 
| 26 26 | 
             
                      lock_jobs_for_hold
         | 
| 27 27 | 
             
                    end
         | 
| 28 28 | 
             
                    return unless wait
         | 
| 29 29 |  | 
| 30 | 
            -
                    delayed_jobs_shard.activate( | 
| 30 | 
            +
                    delayed_jobs_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
         | 
| 31 31 | 
             
                      while ::Delayed::Job.where(shard_id: id).
         | 
| 32 32 | 
             
                          where.not(locked_at: nil).
         | 
| 33 33 | 
             
                          where.not(locked_by: ::Delayed::Backend::Base::ON_HOLD_LOCKED_BY).exists?
         | 
| @@ -47,7 +47,7 @@ module SwitchmanInstJobs | |
| 47 47 | 
             
                      Rails.logger.debug('Waiting for caches to clear')
         | 
| 48 48 | 
             
                      sleep(65)
         | 
| 49 49 | 
             
                    end
         | 
| 50 | 
            -
                    delayed_jobs_shard.activate( | 
| 50 | 
            +
                    delayed_jobs_shard.activate(::Delayed::Backend::ActiveRecord::AbstractJob) do
         | 
| 51 51 | 
             
                      ::Delayed::Job.where(locked_by: ::Delayed::Backend::Base::ON_HOLD_LOCKED_BY, shard_id: id).
         | 
| 52 52 | 
             
                        in_batches(of: 10_000).
         | 
| 53 53 | 
             
                        update_all(
         | 
| @@ -75,22 +75,14 @@ module SwitchmanInstJobs | |
| 75 75 | 
             
                      remove_instance_variable(:@delayed_jobs_shards) if instance_variable_defined?(:@delayed_jobs_shards)
         | 
| 76 76 | 
             
                    end
         | 
| 77 77 |  | 
| 78 | 
            -
                    def current(category = :primary)
         | 
| 79 | 
            -
                      if category == :delayed_jobs
         | 
| 80 | 
            -
                        active_shards[category] || super(:primary).delayed_jobs_shard
         | 
| 81 | 
            -
                      else
         | 
| 82 | 
            -
                        super
         | 
| 83 | 
            -
                      end
         | 
| 84 | 
            -
                    end
         | 
| 85 | 
            -
             | 
| 86 78 | 
             
                    def activate!(categories)
         | 
| 87 79 | 
             
                      if !@skip_delayed_job_auto_activation &&
         | 
| 88 | 
            -
                         !categories[ | 
| 89 | 
            -
                         categories[ | 
| 90 | 
            -
                         categories[ | 
| 80 | 
            +
                         !categories[::Delayed::Backend::ActiveRecord::AbstractJob] &&
         | 
| 81 | 
            +
                         categories[::ActiveRecord::Base] &&
         | 
| 82 | 
            +
                         categories[::ActiveRecord::Base] != ::Switchman::Shard.current(::ActiveRecord::Base)
         | 
| 91 83 | 
             
                        skip_delayed_job_auto_activation do
         | 
| 92 | 
            -
                          categories[ | 
| 93 | 
            -
                            categories[ | 
| 84 | 
            +
                          categories[::Delayed::Backend::ActiveRecord::AbstractJob] =
         | 
| 85 | 
            +
                            categories[::ActiveRecord::Base].delayed_jobs_shard
         | 
| 94 86 | 
             
                        end
         | 
| 95 87 | 
             
                      end
         | 
| 96 88 | 
             
                      super
         | 
| @@ -104,11 +96,6 @@ module SwitchmanInstJobs | |
| 104 96 | 
             
                      @skip_delayed_job_auto_activation = was
         | 
| 105 97 | 
             
                    end
         | 
| 106 98 |  | 
| 107 | 
            -
                    def create
         | 
| 108 | 
            -
                      db = ::Switchman::DatabaseServer.server_for_new_shard
         | 
| 109 | 
            -
                      db.create_new_shard
         | 
| 110 | 
            -
                    end
         | 
| 111 | 
            -
             | 
| 112 99 | 
             
                    def periodic_clear_shard_cache
         | 
| 113 100 | 
             
                      # TODO: make this configurable
         | 
| 114 101 | 
             
                      @timed_cache ||= TimedCache.new(-> { 60.to_i.seconds.ago }) do
         | 
    
        data/lib/switchman_inst_jobs.rb
    CHANGED
    
    | @@ -5,6 +5,9 @@ module SwitchmanInstJobs | |
| 5 5 | 
             
              cattr_accessor :delayed_jobs_shard_fallback
         | 
| 6 6 |  | 
| 7 7 | 
             
              def self.initialize_active_record
         | 
| 8 | 
            +
                ::ActiveRecord::ConnectionAdapters::ConnectionPool.prepend(
         | 
| 9 | 
            +
                  ActiveRecord::ConnectionAdapters::ConnectionPool
         | 
| 10 | 
            +
                )
         | 
| 8 11 | 
             
                ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(
         | 
| 9 12 | 
             
                  ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
         | 
| 10 13 | 
             
                )
         | 
| @@ -14,6 +17,10 @@ module SwitchmanInstJobs | |
| 14 17 | 
             
                ::Delayed::Backend::ActiveRecord::Job.prepend(
         | 
| 15 18 | 
             
                  Delayed::Backend::Base
         | 
| 16 19 | 
             
                )
         | 
| 20 | 
            +
                ::Delayed::Backend::Redis::Job.prepend(
         | 
| 21 | 
            +
                  Delayed::Backend::Base
         | 
| 22 | 
            +
                )
         | 
| 23 | 
            +
                ::Delayed::Backend::Redis::Job.column :shard_id, :integer
         | 
| 17 24 | 
             
                ::Delayed::Pool.prepend Delayed::Pool
         | 
| 18 25 | 
             
                ::Delayed::Worker.prepend Delayed::Worker
         | 
| 19 26 | 
             
                ::Delayed::Worker::HealthCheck.prepend Delayed::Worker::HealthCheck
         | 
| @@ -32,6 +39,7 @@ module SwitchmanInstJobs | |
| 32 39 | 
             
              end
         | 
| 33 40 | 
             
            end
         | 
| 34 41 |  | 
| 42 | 
            +
            require 'switchman_inst_jobs/active_record/connection_adapters/connection_pool'
         | 
| 35 43 | 
             
            require 'switchman_inst_jobs/active_record/connection_adapters/postgresql_adapter'
         | 
| 36 44 | 
             
            require 'switchman_inst_jobs/active_record/migration'
         | 
| 37 45 | 
             
            require 'switchman_inst_jobs/delayed/settings'
         | 
    
        metadata
    CHANGED
    
    | @@ -1,35 +1,35 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: switchman-inst-jobs
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 4.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Bryan Petty
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021- | 
| 11 | 
            +
            date: 2021-05-24 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: inst-jobs
         | 
| 15 15 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 16 | 
             
                requirements:
         | 
| 17 | 
            -
                - - " | 
| 17 | 
            +
                - - "~>"
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: 2. | 
| 20 | 
            -
                - - " | 
| 19 | 
            +
                    version: '2.0'
         | 
| 20 | 
            +
                - - ">="
         | 
| 21 21 | 
             
                  - !ruby/object:Gem::Version
         | 
| 22 | 
            -
                    version:  | 
| 22 | 
            +
                    version: 2.3.1
         | 
| 23 23 | 
             
              type: :runtime
         | 
| 24 24 | 
             
              prerelease: false
         | 
| 25 25 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 26 26 | 
             
                requirements:
         | 
| 27 | 
            -
                - - " | 
| 27 | 
            +
                - - "~>"
         | 
| 28 28 | 
             
                  - !ruby/object:Gem::Version
         | 
| 29 | 
            -
                    version: 2. | 
| 30 | 
            -
                - - " | 
| 29 | 
            +
                    version: '2.0'
         | 
| 30 | 
            +
                - - ">="
         | 
| 31 31 | 
             
                  - !ruby/object:Gem::Version
         | 
| 32 | 
            -
                    version:  | 
| 32 | 
            +
                    version: 2.3.1
         | 
| 33 33 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 34 34 | 
             
              name: parallel
         | 
| 35 35 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -50,34 +50,40 @@ dependencies: | |
| 50 50 | 
             
                requirements:
         | 
| 51 51 | 
             
                - - ">="
         | 
| 52 52 | 
             
                  - !ruby/object:Gem::Version
         | 
| 53 | 
            -
                    version: ' | 
| 53 | 
            +
                    version: '6.1'
         | 
| 54 54 | 
             
                - - "<"
         | 
| 55 55 | 
             
                  - !ruby/object:Gem::Version
         | 
| 56 | 
            -
                    version: '6. | 
| 56 | 
            +
                    version: '6.2'
         | 
| 57 57 | 
             
              type: :runtime
         | 
| 58 58 | 
             
              prerelease: false
         | 
| 59 59 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 60 60 | 
             
                requirements:
         | 
| 61 61 | 
             
                - - ">="
         | 
| 62 62 | 
             
                  - !ruby/object:Gem::Version
         | 
| 63 | 
            -
                    version: ' | 
| 63 | 
            +
                    version: '6.1'
         | 
| 64 64 | 
             
                - - "<"
         | 
| 65 65 | 
             
                  - !ruby/object:Gem::Version
         | 
| 66 | 
            -
                    version: '6. | 
| 66 | 
            +
                    version: '6.2'
         | 
| 67 67 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 68 68 | 
             
              name: switchman
         | 
| 69 69 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 70 70 | 
             
                requirements:
         | 
| 71 71 | 
             
                - - "~>"
         | 
| 72 72 | 
             
                  - !ruby/object:Gem::Version
         | 
| 73 | 
            -
                    version: ' | 
| 73 | 
            +
                    version: '3.0'
         | 
| 74 | 
            +
                - - ">="
         | 
| 75 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 76 | 
            +
                    version: 3.0.1
         | 
| 74 77 | 
             
              type: :runtime
         | 
| 75 78 | 
             
              prerelease: false
         | 
| 76 79 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 77 80 | 
             
                requirements:
         | 
| 78 81 | 
             
                - - "~>"
         | 
| 79 82 | 
             
                  - !ruby/object:Gem::Version
         | 
| 80 | 
            -
                    version: ' | 
| 83 | 
            +
                    version: '3.0'
         | 
| 84 | 
            +
                - - ">="
         | 
| 85 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 86 | 
            +
                    version: 3.0.1
         | 
| 81 87 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 82 88 | 
             
              name: bundler
         | 
| 83 89 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -110,16 +116,16 @@ dependencies: | |
| 110 116 | 
             
              name: diplomat
         | 
| 111 117 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 112 118 | 
             
                requirements:
         | 
| 113 | 
            -
                - - " | 
| 119 | 
            +
                - - "~>"
         | 
| 114 120 | 
             
                  - !ruby/object:Gem::Version
         | 
| 115 | 
            -
                    version:  | 
| 121 | 
            +
                    version: 2.5.1
         | 
| 116 122 | 
             
              type: :development
         | 
| 117 123 | 
             
              prerelease: false
         | 
| 118 124 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 119 125 | 
             
                requirements:
         | 
| 120 | 
            -
                - - " | 
| 126 | 
            +
                - - "~>"
         | 
| 121 127 | 
             
                  - !ruby/object:Gem::Version
         | 
| 122 | 
            -
                    version:  | 
| 128 | 
            +
                    version: 2.5.1
         | 
| 123 129 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 124 130 | 
             
              name: newrelic_rpm
         | 
| 125 131 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -182,70 +188,70 @@ dependencies: | |
| 182 188 | 
             
                requirements:
         | 
| 183 189 | 
             
                - - "~>"
         | 
| 184 190 | 
             
                  - !ruby/object:Gem::Version
         | 
| 185 | 
            -
                    version: '3. | 
| 191 | 
            +
                    version: '3.10'
         | 
| 186 192 | 
             
              type: :development
         | 
| 187 193 | 
             
              prerelease: false
         | 
| 188 194 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 189 195 | 
             
                requirements:
         | 
| 190 196 | 
             
                - - "~>"
         | 
| 191 197 | 
             
                  - !ruby/object:Gem::Version
         | 
| 192 | 
            -
                    version: '3. | 
| 198 | 
            +
                    version: '3.10'
         | 
| 193 199 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 194 200 | 
             
              name: rspec-rails
         | 
| 195 201 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 196 202 | 
             
                requirements:
         | 
| 197 203 | 
             
                - - "~>"
         | 
| 198 204 | 
             
                  - !ruby/object:Gem::Version
         | 
| 199 | 
            -
                    version: ' | 
| 205 | 
            +
                    version: '5.0'
         | 
| 200 206 | 
             
              type: :development
         | 
| 201 207 | 
             
              prerelease: false
         | 
| 202 208 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 203 209 | 
             
                requirements:
         | 
| 204 210 | 
             
                - - "~>"
         | 
| 205 211 | 
             
                  - !ruby/object:Gem::Version
         | 
| 206 | 
            -
                    version: ' | 
| 212 | 
            +
                    version: '5.0'
         | 
| 207 213 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 208 214 | 
             
              name: rubocop
         | 
| 209 215 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 210 216 | 
             
                requirements:
         | 
| 211 217 | 
             
                - - "~>"
         | 
| 212 218 | 
             
                  - !ruby/object:Gem::Version
         | 
| 213 | 
            -
                    version: 1. | 
| 219 | 
            +
                    version: '1.15'
         | 
| 214 220 | 
             
              type: :development
         | 
| 215 221 | 
             
              prerelease: false
         | 
| 216 222 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 217 223 | 
             
                requirements:
         | 
| 218 224 | 
             
                - - "~>"
         | 
| 219 225 | 
             
                  - !ruby/object:Gem::Version
         | 
| 220 | 
            -
                    version: 1. | 
| 226 | 
            +
                    version: '1.15'
         | 
| 221 227 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 222 228 | 
             
              name: rubocop-rails
         | 
| 223 229 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 224 230 | 
             
                requirements:
         | 
| 225 231 | 
             
                - - "~>"
         | 
| 226 232 | 
             
                  - !ruby/object:Gem::Version
         | 
| 227 | 
            -
                    version: 2. | 
| 233 | 
            +
                    version: '2.10'
         | 
| 228 234 | 
             
              type: :development
         | 
| 229 235 | 
             
              prerelease: false
         | 
| 230 236 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 231 237 | 
             
                requirements:
         | 
| 232 238 | 
             
                - - "~>"
         | 
| 233 239 | 
             
                  - !ruby/object:Gem::Version
         | 
| 234 | 
            -
                    version: 2. | 
| 240 | 
            +
                    version: '2.10'
         | 
| 235 241 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 236 242 | 
             
              name: simplecov
         | 
| 237 243 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 238 244 | 
             
                requirements:
         | 
| 239 245 | 
             
                - - "~>"
         | 
| 240 246 | 
             
                  - !ruby/object:Gem::Version
         | 
| 241 | 
            -
                    version: '0. | 
| 247 | 
            +
                    version: '0.21'
         | 
| 242 248 | 
             
              type: :development
         | 
| 243 249 | 
             
              prerelease: false
         | 
| 244 250 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 245 251 | 
             
                requirements:
         | 
| 246 252 | 
             
                - - "~>"
         | 
| 247 253 | 
             
                  - !ruby/object:Gem::Version
         | 
| 248 | 
            -
                    version: '0. | 
| 254 | 
            +
                    version: '0.21'
         | 
| 249 255 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 250 256 | 
             
              name: wwtd
         | 
| 251 257 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -289,6 +295,7 @@ files: | |
| 289 295 | 
             
            - db/migrate/20151210162949_improve_max_concurrent.rb
         | 
| 290 296 | 
             
            - db/migrate/20161206323555_add_back_default_string_limits_jobs.rb
         | 
| 291 297 | 
             
            - db/migrate/20170308045400_add_shard_id_to_delayed_jobs.rb
         | 
| 298 | 
            +
            - db/migrate/20170308045401_add_delayed_jobs_shard_id_to_switchman_shards.rb
         | 
| 292 299 | 
             
            - db/migrate/20181217155351_speed_up_max_concurrent_triggers.rb
         | 
| 293 300 | 
             
            - db/migrate/20190726154743_make_critical_columns_not_null.rb
         | 
| 294 301 | 
             
            - db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb
         | 
| @@ -296,13 +303,9 @@ files: | |
| 296 303 | 
             
            - db/migrate/20200822014259_add_block_stranded_to_switchman_shards.rb
         | 
| 297 304 | 
             
            - db/migrate/20200824222232_speed_up_max_concurrent_delete_trigger.rb
         | 
| 298 305 | 
             
            - db/migrate/20200825011002_add_strand_order_override.rb
         | 
| 299 | 
            -
            - db/migrate/20210809145804_add_n_strand_index.rb
         | 
| 300 | 
            -
            - db/migrate/20210812210128_add_singleton_column.rb
         | 
| 301 | 
            -
            - db/migrate/20210917232626_add_delete_conflicting_singletons_before_unlock_trigger.rb
         | 
| 302 | 
            -
            - db/migrate/20210928174754_fix_singleton_condition_in_before_insert.rb
         | 
| 303 | 
            -
            - db/migrate/20210929204903_update_conflicting_singleton_function_to_use_index.rb
         | 
| 304 306 | 
             
            - lib/switchman-inst-jobs.rb
         | 
| 305 307 | 
             
            - lib/switchman_inst_jobs.rb
         | 
| 308 | 
            +
            - lib/switchman_inst_jobs/active_record/connection_adapters/connection_pool.rb
         | 
| 306 309 | 
             
            - lib/switchman_inst_jobs/active_record/connection_adapters/postgresql_adapter.rb
         | 
| 307 310 | 
             
            - lib/switchman_inst_jobs/active_record/migration.rb
         | 
| 308 311 | 
             
            - lib/switchman_inst_jobs/delayed/backend/base.rb
         | 
| @@ -340,7 +343,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 340 343 | 
             
                - !ruby/object:Gem::Version
         | 
| 341 344 | 
             
                  version: '0'
         | 
| 342 345 | 
             
            requirements: []
         | 
| 343 | 
            -
            rubygems_version: 3. | 
| 346 | 
            +
            rubygems_version: 3.2.15
         | 
| 344 347 | 
             
            signing_key:
         | 
| 345 348 | 
             
            specification_version: 4
         | 
| 346 349 | 
             
            summary: Switchman and Instructure Jobs compatibility gem.
         | 
| @@ -1,12 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            class AddNStrandIndex < ActiveRecord::Migration[5.2]
         | 
| 4 | 
            -
              disable_ddl_transaction!
         | 
| 5 | 
            -
             | 
| 6 | 
            -
              def change
         | 
| 7 | 
            -
                add_index :delayed_jobs, %i[strand next_in_strand id],
         | 
| 8 | 
            -
                          name: 'n_strand_index',
         | 
| 9 | 
            -
                          where: 'strand IS NOT NULL',
         | 
| 10 | 
            -
                          algorithm: :concurrently
         | 
| 11 | 
            -
              end
         | 
| 12 | 
            -
            end
         | 
| @@ -1,200 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            class AddSingletonColumn < ActiveRecord::Migration[5.2]
         | 
| 4 | 
            -
              disable_ddl_transaction!
         | 
| 5 | 
            -
             | 
| 6 | 
            -
              def change
         | 
| 7 | 
            -
                add_column :delayed_jobs, :singleton, :string, if_not_exists: true
         | 
| 8 | 
            -
                add_column :failed_jobs, :singleton, :string, if_not_exists: true
         | 
| 9 | 
            -
                # only one job can be queued in a singleton
         | 
| 10 | 
            -
                add_index :delayed_jobs,
         | 
| 11 | 
            -
                          :singleton,
         | 
| 12 | 
            -
                          where: 'singleton IS NOT NULL AND locked_by IS NULL',
         | 
| 13 | 
            -
                          unique: true,
         | 
| 14 | 
            -
                          name: 'index_delayed_jobs_on_singleton_not_running',
         | 
| 15 | 
            -
                          algorithm: :concurrently
         | 
| 16 | 
            -
                # only one job can be running for a singleton
         | 
| 17 | 
            -
                add_index :delayed_jobs,
         | 
| 18 | 
            -
                          :singleton,
         | 
| 19 | 
            -
                          where: 'singleton IS NOT NULL AND locked_by IS NOT NULL',
         | 
| 20 | 
            -
                          unique: true,
         | 
| 21 | 
            -
                          name: 'index_delayed_jobs_on_singleton_running',
         | 
| 22 | 
            -
                          algorithm: :concurrently
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                reversible do |direction|
         | 
| 25 | 
            -
                  direction.up do
         | 
| 26 | 
            -
                    execute(<<~SQL)
         | 
| 27 | 
            -
                      CREATE OR REPLACE FUNCTION #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn')} () RETURNS trigger AS $$
         | 
| 28 | 
            -
                      DECLARE
         | 
| 29 | 
            -
                        running_count integer;
         | 
| 30 | 
            -
                        should_lock boolean;
         | 
| 31 | 
            -
                        should_be_precise boolean;
         | 
| 32 | 
            -
                        update_query varchar;
         | 
| 33 | 
            -
                        skip_locked varchar;
         | 
| 34 | 
            -
                      BEGIN
         | 
| 35 | 
            -
                        IF OLD.strand IS NOT NULL THEN
         | 
| 36 | 
            -
                          should_lock := true;
         | 
| 37 | 
            -
                          should_be_precise := OLD.id % (OLD.max_concurrent * 4) = 0;
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                          IF NOT should_be_precise AND OLD.max_concurrent > 16 THEN
         | 
| 40 | 
            -
                            running_count := (SELECT COUNT(*) FROM (
         | 
| 41 | 
            -
                              SELECT 1 as one FROM delayed_jobs WHERE strand = OLD.strand AND next_in_strand = 't' LIMIT OLD.max_concurrent
         | 
| 42 | 
            -
                            ) subquery_for_count);
         | 
| 43 | 
            -
                            should_lock := running_count < OLD.max_concurrent;
         | 
| 44 | 
            -
                          END IF;
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                          IF should_lock THEN
         | 
| 47 | 
            -
                            PERFORM pg_advisory_xact_lock(half_md5_as_bigint(OLD.strand));
         | 
| 48 | 
            -
                          END IF;
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                          -- note that we don't really care if the row we're deleting has a singleton, or if it even
         | 
| 51 | 
            -
                          -- matches the row(s) we're going to update. we just need to make sure that whatever
         | 
| 52 | 
            -
                          -- singleton we grab isn't already running (which is a simple existence check, since
         | 
| 53 | 
            -
                          -- the unique indexes ensure there is at most one singleton running, and one queued)
         | 
| 54 | 
            -
                          update_query := 'UPDATE delayed_jobs SET next_in_strand=true WHERE id IN (
         | 
| 55 | 
            -
                            SELECT id FROM delayed_jobs j2
         | 
| 56 | 
            -
                              WHERE next_in_strand=false AND
         | 
| 57 | 
            -
                                j2.strand=$1.strand AND
         | 
| 58 | 
            -
                                (j2.singleton IS NULL OR NOT EXISTS (SELECT 1 FROM delayed_jobs j3 WHERE j3.singleton=j2.singleton AND j3.id<>j2.id))
         | 
| 59 | 
            -
                              ORDER BY j2.strand_order_override ASC, j2.id ASC
         | 
| 60 | 
            -
                              LIMIT ';
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                          IF should_be_precise THEN
         | 
| 63 | 
            -
                            running_count := (SELECT COUNT(*) FROM (
         | 
| 64 | 
            -
                              SELECT 1 FROM delayed_jobs WHERE strand = OLD.strand AND next_in_strand = 't' LIMIT OLD.max_concurrent
         | 
| 65 | 
            -
                            ) s);
         | 
| 66 | 
            -
                            IF running_count < OLD.max_concurrent THEN
         | 
| 67 | 
            -
                              update_query := update_query || '($1.max_concurrent - $2)';
         | 
| 68 | 
            -
                            ELSE
         | 
| 69 | 
            -
                              -- we have too many running already; just bail
         | 
| 70 | 
            -
                              RETURN OLD;
         | 
| 71 | 
            -
                            END IF;
         | 
| 72 | 
            -
                          ELSE
         | 
| 73 | 
            -
                            update_query := update_query || '1';
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                            -- n-strands don't require precise ordering; we can make this query more performant
         | 
| 76 | 
            -
                            IF OLD.max_concurrent > 1 THEN
         | 
| 77 | 
            -
                              skip_locked := ' SKIP LOCKED';
         | 
| 78 | 
            -
                            END IF;
         | 
| 79 | 
            -
                          END IF;
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                          update_query := update_query || ' FOR UPDATE' || COALESCE(skip_locked, '') || ')';
         | 
| 82 | 
            -
                          EXECUTE update_query USING OLD, running_count;
         | 
| 83 | 
            -
                        ELSIF OLD.singleton IS NOT NULL THEN
         | 
| 84 | 
            -
                          UPDATE delayed_jobs SET next_in_strand = 't' WHERE singleton=OLD.singleton AND next_in_strand=false;
         | 
| 85 | 
            -
                        END IF;
         | 
| 86 | 
            -
                        RETURN OLD;
         | 
| 87 | 
            -
                      END;
         | 
| 88 | 
            -
                      $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
         | 
| 89 | 
            -
                    SQL
         | 
| 90 | 
            -
                    execute(<<~SQL)
         | 
| 91 | 
            -
                      CREATE OR REPLACE FUNCTION #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')} () RETURNS trigger AS $$
         | 
| 92 | 
            -
                      BEGIN
         | 
| 93 | 
            -
                        IF NEW.strand IS NOT NULL THEN
         | 
| 94 | 
            -
                          PERFORM pg_advisory_xact_lock(half_md5_as_bigint(NEW.strand));
         | 
| 95 | 
            -
                          IF (SELECT COUNT(*) FROM (
         | 
| 96 | 
            -
                              SELECT 1 FROM delayed_jobs WHERE strand = NEW.strand AND next_in_strand=true LIMIT NEW.max_concurrent
         | 
| 97 | 
            -
                            ) s) = NEW.max_concurrent THEN
         | 
| 98 | 
            -
                            NEW.next_in_strand := false;
         | 
| 99 | 
            -
                          END IF;
         | 
| 100 | 
            -
                        END IF;
         | 
| 101 | 
            -
                        IF NEW.singleton IS NOT NULL THEN
         | 
| 102 | 
            -
                          PERFORM 1 FROM delayed_jobs WHERE singleton = NEW.singleton;
         | 
| 103 | 
            -
                          IF FOUND THEN
         | 
| 104 | 
            -
                            NEW.next_in_strand := false;
         | 
| 105 | 
            -
                          END IF;
         | 
| 106 | 
            -
                        END IF;
         | 
| 107 | 
            -
                        RETURN NEW;
         | 
| 108 | 
            -
                      END;
         | 
| 109 | 
            -
                      $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
         | 
| 110 | 
            -
                    SQL
         | 
| 111 | 
            -
                  end
         | 
| 112 | 
            -
                  direction.down do
         | 
| 113 | 
            -
                    execute(<<~SQL)
         | 
| 114 | 
            -
                      CREATE OR REPLACE FUNCTION #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn')} () RETURNS trigger AS $$
         | 
| 115 | 
            -
                      DECLARE
         | 
| 116 | 
            -
                        running_count integer;
         | 
| 117 | 
            -
                        should_lock boolean;
         | 
| 118 | 
            -
                        should_be_precise boolean;
         | 
| 119 | 
            -
                      BEGIN
         | 
| 120 | 
            -
                        IF OLD.strand IS NOT NULL THEN
         | 
| 121 | 
            -
                          should_lock := true;
         | 
| 122 | 
            -
                          should_be_precise := OLD.id % (OLD.max_concurrent * 4) = 0;
         | 
| 123 | 
            -
             | 
| 124 | 
            -
                          IF NOT should_be_precise AND OLD.max_concurrent > 16 THEN
         | 
| 125 | 
            -
                            running_count := (SELECT COUNT(*) FROM (
         | 
| 126 | 
            -
                              SELECT 1 as one FROM delayed_jobs WHERE strand = OLD.strand AND next_in_strand = 't' LIMIT OLD.max_concurrent
         | 
| 127 | 
            -
                            ) subquery_for_count);
         | 
| 128 | 
            -
                            should_lock := running_count < OLD.max_concurrent;
         | 
| 129 | 
            -
                          END IF;
         | 
| 130 | 
            -
             | 
| 131 | 
            -
                          IF should_lock THEN
         | 
| 132 | 
            -
                            PERFORM pg_advisory_xact_lock(half_md5_as_bigint(OLD.strand));
         | 
| 133 | 
            -
                          END IF;
         | 
| 134 | 
            -
             | 
| 135 | 
            -
                          IF should_be_precise THEN
         | 
| 136 | 
            -
                            running_count := (SELECT COUNT(*) FROM (
         | 
| 137 | 
            -
                              SELECT 1 as one FROM delayed_jobs WHERE strand = OLD.strand AND next_in_strand = 't' LIMIT OLD.max_concurrent
         | 
| 138 | 
            -
                            ) subquery_for_count);
         | 
| 139 | 
            -
                            IF running_count < OLD.max_concurrent THEN
         | 
| 140 | 
            -
                              UPDATE delayed_jobs SET next_in_strand = 't' WHERE id IN (
         | 
| 141 | 
            -
                                SELECT id FROM delayed_jobs j2 WHERE next_in_strand = 'f' AND
         | 
| 142 | 
            -
                                j2.strand = OLD.strand ORDER BY j2.strand_order_override ASC, j2.id ASC LIMIT (OLD.max_concurrent - running_count) FOR UPDATE
         | 
| 143 | 
            -
                              );
         | 
| 144 | 
            -
                            END IF;
         | 
| 145 | 
            -
                          ELSE
         | 
| 146 | 
            -
                            -- n-strands don't require precise ordering; we can make this query more performant
         | 
| 147 | 
            -
                            IF OLD.max_concurrent > 1 THEN
         | 
| 148 | 
            -
                              UPDATE delayed_jobs SET next_in_strand = 't' WHERE id =
         | 
| 149 | 
            -
                              (SELECT id FROM delayed_jobs j2 WHERE next_in_strand = 'f' AND
         | 
| 150 | 
            -
                                j2.strand = OLD.strand ORDER BY j2.strand_order_override ASC, j2.id ASC LIMIT 1 FOR UPDATE SKIP LOCKED);
         | 
| 151 | 
            -
                            ELSE
         | 
| 152 | 
            -
                              UPDATE delayed_jobs SET next_in_strand = 't' WHERE id =
         | 
| 153 | 
            -
                                (SELECT id FROM delayed_jobs j2 WHERE next_in_strand = 'f' AND
         | 
| 154 | 
            -
                                  j2.strand = OLD.strand ORDER BY j2.strand_order_override ASC, j2.id ASC LIMIT 1 FOR UPDATE);
         | 
| 155 | 
            -
                            END IF;
         | 
| 156 | 
            -
                          END IF;
         | 
| 157 | 
            -
                        END IF;
         | 
| 158 | 
            -
                        RETURN OLD;
         | 
| 159 | 
            -
                      END;
         | 
| 160 | 
            -
                      $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
         | 
| 161 | 
            -
                    SQL
         | 
| 162 | 
            -
                    execute(<<~SQL)
         | 
| 163 | 
            -
                      CREATE OR REPLACE FUNCTION #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')} () RETURNS trigger AS $$
         | 
| 164 | 
            -
                      BEGIN
         | 
| 165 | 
            -
                        IF NEW.strand IS NOT NULL THEN
         | 
| 166 | 
            -
                          PERFORM pg_advisory_xact_lock(half_md5_as_bigint(NEW.strand));
         | 
| 167 | 
            -
                          IF (SELECT COUNT(*) FROM (
         | 
| 168 | 
            -
                              SELECT 1 AS one FROM delayed_jobs WHERE strand = NEW.strand LIMIT NEW.max_concurrent
         | 
| 169 | 
            -
                            ) subquery_for_count) = NEW.max_concurrent THEN
         | 
| 170 | 
            -
                            NEW.next_in_strand := 'f';
         | 
| 171 | 
            -
                          END IF;
         | 
| 172 | 
            -
                        END IF;
         | 
| 173 | 
            -
                        RETURN NEW;
         | 
| 174 | 
            -
                      END;
         | 
| 175 | 
            -
                      $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
         | 
| 176 | 
            -
                    SQL
         | 
| 177 | 
            -
                  end
         | 
| 178 | 
            -
                end
         | 
| 179 | 
            -
             | 
| 180 | 
            -
                connection.transaction do
         | 
| 181 | 
            -
                  reversible do |direction|
         | 
| 182 | 
            -
                    direction.up do
         | 
| 183 | 
            -
                      drop_triggers
         | 
| 184 | 
            -
                      execute("CREATE TRIGGER delayed_jobs_before_insert_row_tr BEFORE INSERT ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (NEW.strand IS NOT NULL OR NEW.singleton IS NOT NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')}()")
         | 
| 185 | 
            -
                      execute("CREATE TRIGGER delayed_jobs_after_delete_row_tr AFTER DELETE ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN ((OLD.strand IS NOT NULL OR OLD.singleton IS NOT NULL) AND OLD.next_in_strand=true) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn')}()")
         | 
| 186 | 
            -
                    end
         | 
| 187 | 
            -
                    direction.down do
         | 
| 188 | 
            -
                      drop_triggers
         | 
| 189 | 
            -
                      execute("CREATE TRIGGER delayed_jobs_before_insert_row_tr BEFORE INSERT ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (NEW.strand IS NOT NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')}()")
         | 
| 190 | 
            -
                      execute("CREATE TRIGGER delayed_jobs_after_delete_row_tr AFTER DELETE ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (OLD.strand IS NOT NULL AND OLD.next_in_strand = 't') EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_after_delete_row_tr_fn()')}")
         | 
| 191 | 
            -
                    end
         | 
| 192 | 
            -
                  end
         | 
| 193 | 
            -
                end
         | 
| 194 | 
            -
              end
         | 
| 195 | 
            -
             | 
| 196 | 
            -
              def drop_triggers
         | 
| 197 | 
            -
                execute("DROP TRIGGER delayed_jobs_before_insert_row_tr ON #{::Delayed::Job.quoted_table_name}")
         | 
| 198 | 
            -
                execute("DROP TRIGGER delayed_jobs_after_delete_row_tr ON #{::Delayed::Job.quoted_table_name}")
         | 
| 199 | 
            -
              end
         | 
| 200 | 
            -
            end
         | 
| @@ -1,27 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            class AddDeleteConflictingSingletonsBeforeUnlockTrigger < ActiveRecord::Migration[5.2]
         | 
| 4 | 
            -
              def up
         | 
| 5 | 
            -
                execute(<<~SQL)
         | 
| 6 | 
            -
                  CREATE FUNCTION #{connection.quote_table_name('delayed_jobs_before_unlock_delete_conflicting_singletons_row_fn')} () RETURNS trigger AS $$
         | 
| 7 | 
            -
                  BEGIN
         | 
| 8 | 
            -
                    IF EXISTS (SELECT 1 FROM delayed_jobs j2 WHERE j2.singleton=OLD.singleton) THEN
         | 
| 9 | 
            -
                      DELETE FROM delayed_jobs WHERE id<>OLD.id AND singleton=OLD.singleton;
         | 
| 10 | 
            -
                    END IF;
         | 
| 11 | 
            -
                    RETURN NEW;
         | 
| 12 | 
            -
                  END;
         | 
| 13 | 
            -
                  $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
         | 
| 14 | 
            -
                SQL
         | 
| 15 | 
            -
                execute(<<~SQL)
         | 
| 16 | 
            -
                  CREATE TRIGGER delayed_jobs_before_unlock_delete_conflicting_singletons_row_tr BEFORE UPDATE ON #{::Delayed::Job.quoted_table_name} FOR EACH ROW WHEN (
         | 
| 17 | 
            -
                    OLD.singleton IS NOT NULL AND
         | 
| 18 | 
            -
                    OLD.singleton=NEW.singleton AND
         | 
| 19 | 
            -
                    OLD.locked_by IS NOT NULL AND
         | 
| 20 | 
            -
                    NEW.locked_by IS NULL) EXECUTE PROCEDURE #{connection.quote_table_name('delayed_jobs_before_unlock_delete_conflicting_singletons_row_fn')}();
         | 
| 21 | 
            -
                SQL
         | 
| 22 | 
            -
              end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
              def down
         | 
| 25 | 
            -
                execute("DROP FUNCTION #{connection.quote_table_name('delayed_jobs_before_unlock_delete_conflicting_singletons_row_tr_fn')}() CASCADE")
         | 
| 26 | 
            -
              end
         | 
| 27 | 
            -
            end
         | 
| @@ -1,56 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            class FixSingletonConditionInBeforeInsert < ActiveRecord::Migration[5.2]
         | 
| 4 | 
            -
              def change
         | 
| 5 | 
            -
                reversible do |direction|
         | 
| 6 | 
            -
                  direction.up do
         | 
| 7 | 
            -
                    execute(<<~SQL)
         | 
| 8 | 
            -
                      CREATE OR REPLACE FUNCTION #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')} () RETURNS trigger AS $$
         | 
| 9 | 
            -
                      BEGIN
         | 
| 10 | 
            -
                        IF NEW.strand IS NOT NULL THEN
         | 
| 11 | 
            -
                          PERFORM pg_advisory_xact_lock(half_md5_as_bigint(NEW.strand));
         | 
| 12 | 
            -
                          IF (SELECT COUNT(*) FROM (
         | 
| 13 | 
            -
                              SELECT 1 FROM delayed_jobs WHERE strand = NEW.strand AND next_in_strand=true LIMIT NEW.max_concurrent
         | 
| 14 | 
            -
                            ) s) = NEW.max_concurrent THEN
         | 
| 15 | 
            -
                            NEW.next_in_strand := false;
         | 
| 16 | 
            -
                          END IF;
         | 
| 17 | 
            -
                        END IF;
         | 
| 18 | 
            -
                        IF NEW.singleton IS NOT NULL THEN
         | 
| 19 | 
            -
                          -- this condition seems silly, but it forces postgres to use the two partial indexes on singleton,
         | 
| 20 | 
            -
                          -- rather than doing a seq scan
         | 
| 21 | 
            -
                          PERFORM 1 FROM delayed_jobs WHERE singleton = NEW.singleton AND (locked_by IS NULL OR locked_by IS NOT NULL);
         | 
| 22 | 
            -
                          IF FOUND THEN
         | 
| 23 | 
            -
                            NEW.next_in_strand := false;
         | 
| 24 | 
            -
                          END IF;
         | 
| 25 | 
            -
                        END IF;
         | 
| 26 | 
            -
                        RETURN NEW;
         | 
| 27 | 
            -
                      END;
         | 
| 28 | 
            -
                      $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
         | 
| 29 | 
            -
                    SQL
         | 
| 30 | 
            -
                  end
         | 
| 31 | 
            -
                  direction.down do
         | 
| 32 | 
            -
                    execute(<<~SQL)
         | 
| 33 | 
            -
                      CREATE OR REPLACE FUNCTION #{connection.quote_table_name('delayed_jobs_before_insert_row_tr_fn')} () RETURNS trigger AS $$
         | 
| 34 | 
            -
                      BEGIN
         | 
| 35 | 
            -
                        IF NEW.strand IS NOT NULL THEN
         | 
| 36 | 
            -
                          PERFORM pg_advisory_xact_lock(half_md5_as_bigint(NEW.strand));
         | 
| 37 | 
            -
                          IF (SELECT COUNT(*) FROM (
         | 
| 38 | 
            -
                              SELECT 1 FROM delayed_jobs WHERE strand = NEW.strand AND next_in_strand=true LIMIT NEW.max_concurrent
         | 
| 39 | 
            -
                            ) s) = NEW.max_concurrent THEN
         | 
| 40 | 
            -
                            NEW.next_in_strand := false;
         | 
| 41 | 
            -
                          END IF;
         | 
| 42 | 
            -
                        END IF;
         | 
| 43 | 
            -
                        IF NEW.singleton IS NOT NULL THEN
         | 
| 44 | 
            -
                          PERFORM 1 FROM delayed_jobs WHERE singleton = NEW.singleton;
         | 
| 45 | 
            -
                          IF FOUND THEN
         | 
| 46 | 
            -
                            NEW.next_in_strand := false;
         | 
| 47 | 
            -
                          END IF;
         | 
| 48 | 
            -
                        END IF;
         | 
| 49 | 
            -
                        RETURN NEW;
         | 
| 50 | 
            -
                      END;
         | 
| 51 | 
            -
                      $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
         | 
| 52 | 
            -
                    SQL
         | 
| 53 | 
            -
                  end
         | 
| 54 | 
            -
                end
         | 
| 55 | 
            -
              end
         | 
| 56 | 
            -
            end
         | 
| @@ -1,27 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            class UpdateConflictingSingletonFunctionToUseIndex < ActiveRecord::Migration[5.2]
         | 
| 4 | 
            -
              def up
         | 
| 5 | 
            -
                execute(<<~SQL)
         | 
| 6 | 
            -
                  CREATE OR REPLACE FUNCTION #{connection.quote_table_name('delayed_jobs_before_unlock_delete_conflicting_singletons_row_fn')} () RETURNS trigger AS $$
         | 
| 7 | 
            -
                  BEGIN
         | 
| 8 | 
            -
                    DELETE FROM delayed_jobs WHERE id<>OLD.id AND singleton=OLD.singleton AND locked_by IS NULL;
         | 
| 9 | 
            -
                    RETURN NEW;
         | 
| 10 | 
            -
                  END;
         | 
| 11 | 
            -
                  $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
         | 
| 12 | 
            -
                SQL
         | 
| 13 | 
            -
              end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
              def down
         | 
| 16 | 
            -
                execute(<<~SQL)
         | 
| 17 | 
            -
                  CREATE OR REPLACE FUNCTION #{connection.quote_table_name('delayed_jobs_before_unlock_delete_conflicting_singletons_row_fn')} () RETURNS trigger AS $$
         | 
| 18 | 
            -
                  BEGIN
         | 
| 19 | 
            -
                    IF EXISTS (SELECT 1 FROM delayed_jobs j2 WHERE j2.singleton=OLD.singleton) THEN
         | 
| 20 | 
            -
                      DELETE FROM delayed_jobs WHERE id<>OLD.id AND singleton=OLD.singleton;
         | 
| 21 | 
            -
                    END IF;
         | 
| 22 | 
            -
                    RETURN NEW;
         | 
| 23 | 
            -
                  END;
         | 
| 24 | 
            -
                  $$ LANGUAGE plpgsql SET search_path TO #{::Switchman::Shard.current.name};
         | 
| 25 | 
            -
                SQL
         | 
| 26 | 
            -
              end
         | 
| 27 | 
            -
            end
         |