canvas_sync 0.17.35 → 0.17.37
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/lib/canvas_sync/engine.rb +6 -0
- data/lib/canvas_sync/job_batches/active_job.rb +108 -0
- data/lib/canvas_sync/job_batches/batch.rb +7 -4
- data/lib/canvas_sync/job_batches/callback.rb +1 -13
- data/lib/canvas_sync/job_batches/jobs/base_job.rb +1 -1
- data/lib/canvas_sync/job_batches/jobs/managed_batch_job.rb +2 -2
- data/lib/canvas_sync/job_batches/pool.rb +2 -2
- data/lib/canvas_sync/job_batches/sidekiq.rb +21 -7
- data/lib/canvas_sync/version.rb +1 -1
- data/spec/dummy/log/test.log +23910 -0
- data/spec/job_batching/active_job_spec.rb +107 -0
- data/spec/job_batching/batch_spec.rb +1 -1
- metadata +5 -5
- data/lib/canvas_sync/job_batches/batch_aware_job.rb +0 -63
- data/spec/job_batching/batch_aware_job_spec.rb +0 -101
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: aa91c7ca59af567024be0ac8cb9d13ffff059fe7c04fb075101609b3fc78fe4f
         | 
| 4 | 
            +
              data.tar.gz: 8f4e9744ed47825c119e4725c506bf8a55a0dca44d045f49c239e272eed3ea7d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 9a6213cb2348019af23683bfa1847e6f0025dd81269fe0950f6a0217acd15565d74096cbcc536bdd42eea8d214f1a5e8a67f8fd6f5188a09aa5442d8f7a26ac7
         | 
| 7 | 
            +
              data.tar.gz: 8a502df328aff5498bf191bc6b3ef73ed91c32b1bcdf2b0f9aa1ec14ce8f0aaf9c908284c8e51da61b2ce51c97df43af0461c297dcb1b0b48252aab8b0240cad
         | 
    
        data/lib/canvas_sync/engine.rb
    CHANGED
    
    | @@ -5,6 +5,12 @@ module CanvasSync | |
| 5 5 | 
             
              class Engine < ::Rails::Engine
         | 
| 6 6 | 
             
                isolate_namespace CanvasSync
         | 
| 7 7 |  | 
| 8 | 
            +
                initializer "canvas_sync.serialze_symbols" do |app|
         | 
| 9 | 
            +
                  app.config.active_record.yaml_column_permitted_classes ||= []
         | 
| 10 | 
            +
                  app.config.active_record.yaml_column_permitted_classes |= [Symbol]
         | 
| 11 | 
            +
                rescue
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 8 14 | 
             
                initializer :append_migrations do |app|
         | 
| 9 15 | 
             
                  config.paths["db/migrate"].expanded.each do |expanded_path|
         | 
| 10 16 | 
             
                    app.config.paths["db/migrate"] << expanded_path
         | 
| @@ -0,0 +1,108 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            module CanvasSync
         | 
| 3 | 
            +
              module JobBatches
         | 
| 4 | 
            +
                module ActiveJob
         | 
| 5 | 
            +
                  module BatchAwareJob
         | 
| 6 | 
            +
                    extend ActiveSupport::Concern
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                    included do
         | 
| 9 | 
            +
                      around_perform do |job, block|
         | 
| 10 | 
            +
                        if (@bid) # This _must_ be @bid - not just bid
         | 
| 11 | 
            +
                          prev_batch = Thread.current[CURRENT_BATCH_THREAD_KEY]
         | 
| 12 | 
            +
                          begin
         | 
| 13 | 
            +
                            Thread.current[CURRENT_BATCH_THREAD_KEY] = Batch.new(@bid)
         | 
| 14 | 
            +
                            block.call
         | 
| 15 | 
            +
                            Thread.current[CURRENT_BATCH_THREAD_KEY].save_context_changes
         | 
| 16 | 
            +
                            Batch.process_successful_job(@bid, job_id)
         | 
| 17 | 
            +
                          rescue
         | 
| 18 | 
            +
                            Batch.process_failed_job(@bid, job_id)
         | 
| 19 | 
            +
                            raise
         | 
| 20 | 
            +
                          ensure
         | 
| 21 | 
            +
                            Thread.current[CURRENT_BATCH_THREAD_KEY] = prev_batch
         | 
| 22 | 
            +
                          end
         | 
| 23 | 
            +
                        else
         | 
| 24 | 
            +
                          block.call
         | 
| 25 | 
            +
                        end
         | 
| 26 | 
            +
                      end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                      around_enqueue do |job, block|
         | 
| 29 | 
            +
                        if (batch = Thread.current[CURRENT_BATCH_THREAD_KEY])
         | 
| 30 | 
            +
                          @bid = batch.bid
         | 
| 31 | 
            +
                          batch.increment_job_queue(job_id) if @bid
         | 
| 32 | 
            +
                        end
         | 
| 33 | 
            +
                        block.call
         | 
| 34 | 
            +
                      end
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    def bid
         | 
| 38 | 
            +
                      @bid || Thread.current[CURRENT_BATCH_THREAD_KEY]&.bid
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    def batch
         | 
| 42 | 
            +
                      Thread.current[CURRENT_BATCH_THREAD_KEY]
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    def batch_context
         | 
| 46 | 
            +
                      batch&.context || {}
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    def valid_within_batch?
         | 
| 50 | 
            +
                      batch.valid?
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    def serialize
         | 
| 54 | 
            +
                      super.tap do |data|
         | 
| 55 | 
            +
                        data['batch_id'] = @bid # This _must_ be @bid - not just bid
         | 
| 56 | 
            +
                        data
         | 
| 57 | 
            +
                      end
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    def deserialize(data)
         | 
| 61 | 
            +
                      super
         | 
| 62 | 
            +
                      @bid = data['batch_id']
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  class ActiveJobCallbackWorker < ::ActiveJob::Base
         | 
| 67 | 
            +
                    include Batch::Callback::CallbackWorkerCommon
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    def self.enqueue_all(args, queue)
         | 
| 70 | 
            +
                      args.each do |arg_set|
         | 
| 71 | 
            +
                        set(queue: queue).perform_later(*arg_set)
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  def self.handle_job_death(job, error = nil)
         | 
| 77 | 
            +
                    if job.is_a?(Array)
         | 
| 78 | 
            +
                      event = ActiveSupport::Notifications::Event.new(*job)
         | 
| 79 | 
            +
                      payload = event.payload
         | 
| 80 | 
            +
                      job = payload[:job].serialize
         | 
| 81 | 
            +
                      error = payload[:error]
         | 
| 82 | 
            +
                    end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    if job["job_id"].present? && job["batch_id"].present?
         | 
| 85 | 
            +
                      CanvasSync::JobBatches::Batch.process_dead_job(job['batch_id'], job['job_id'])
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  def self.configure
         | 
| 90 | 
            +
                    ::ActiveJob::Base.include BatchAwareJob
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                    begin
         | 
| 93 | 
            +
                      ActiveSupport::Notifications.subscribe "discard.active_job" do |*args|
         | 
| 94 | 
            +
                        handle_job_death(args)
         | 
| 95 | 
            +
                      end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                      ActiveSupport::Notifications.subscribe "retry_stopped.active_job" do |*args|
         | 
| 98 | 
            +
                        handle_job_death(args)
         | 
| 99 | 
            +
                      end
         | 
| 100 | 
            +
                    rescue => err
         | 
| 101 | 
            +
                      Rails.logger.warn(err)
         | 
| 102 | 
            +
                    end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                    Batch::Callback.worker_class ||= ActiveJobCallbackWorker
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
            end
         | 
| @@ -6,7 +6,6 @@ end | |
| 6 6 |  | 
| 7 7 | 
             
            require_relative './redis_model'
         | 
| 8 8 | 
             
            require_relative './redis_script'
         | 
| 9 | 
            -
            require_relative './batch_aware_job'
         | 
| 10 9 | 
             
            require_relative "./callback"
         | 
| 11 10 | 
             
            require_relative "./context_hash"
         | 
| 12 11 | 
             
            require_relative "./status"
         | 
| @@ -465,7 +464,7 @@ module CanvasSync | |
| 465 464 | 
             
                        when 'set'
         | 
| 466 465 | 
             
                          r.smembers(key)
         | 
| 467 466 | 
             
                        when 'zset'
         | 
| 468 | 
            -
                          r. | 
| 467 | 
            +
                          r.zrange(key, 0, -1)
         | 
| 469 468 | 
             
                        end
         | 
| 470 469 | 
             
                      end
         | 
| 471 470 | 
             
                    end
         | 
| @@ -481,8 +480,6 @@ module CanvasSync | |
| 481 480 | 
             
                    end
         | 
| 482 481 | 
             
                  end
         | 
| 483 482 | 
             
                end
         | 
| 484 | 
            -
             | 
| 485 | 
            -
                ActiveJob::Base.include BatchAwareJob
         | 
| 486 483 | 
             
              end
         | 
| 487 484 | 
             
            end
         | 
| 488 485 |  | 
| @@ -491,3 +488,9 @@ if defined?(::Sidekiq) | |
| 491 488 | 
             
              require_relative './sidekiq'
         | 
| 492 489 | 
             
              CanvasSync::JobBatches::Sidekiq.configure
         | 
| 493 490 | 
             
            end
         | 
| 491 | 
            +
             | 
| 492 | 
            +
            # Automatically integrate with ActiveJob if it is present.
         | 
| 493 | 
            +
            if defined?(::ActiveJob)
         | 
| 494 | 
            +
              require_relative './active_job'
         | 
| 495 | 
            +
              CanvasSync::JobBatches::ActiveJob.configure
         | 
| 496 | 
            +
            end
         | 
| @@ -38,24 +38,12 @@ module CanvasSync | |
| 38 38 | 
             
                      end
         | 
| 39 39 | 
             
                    end
         | 
| 40 40 |  | 
| 41 | 
            -
                    class ActiveJobCallbackWorker < ActiveJob::Base
         | 
| 42 | 
            -
                      include CallbackWorkerCommon
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                      def self.enqueue_all(args, queue)
         | 
| 45 | 
            -
                        args.each do |arg_set|
         | 
| 46 | 
            -
                          set(queue: queue).perform_later(*arg_set)
         | 
| 47 | 
            -
                        end
         | 
| 48 | 
            -
                      end
         | 
| 49 | 
            -
                    end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                    worker_class = ActiveJobCallbackWorker
         | 
| 52 | 
            -
             | 
| 53 41 | 
             
                    class Finalize
         | 
| 54 42 | 
             
                      def dispatch(status, opts)
         | 
| 55 43 | 
             
                        bid = opts["bid"]
         | 
| 56 44 | 
             
                        event = opts["event"].to_sym
         | 
| 57 45 |  | 
| 58 | 
            -
                        Batch.logger.debug {"Finalize #{event} batch id: #{opts["bid"]} | 
| 46 | 
            +
                        Batch.logger.debug {"Finalize #{event} batch id: #{opts["bid"]}"}
         | 
| 59 47 |  | 
| 60 48 | 
             
                        batch_status = Status.new bid
         | 
| 61 49 | 
             
                        send(event, bid, batch_status, batch_status.parent_bid)
         | 
| @@ -26,7 +26,7 @@ module CanvasSync | |
| 26 26 |  | 
| 27 27 | 
             
                          mapped_sub_jobs = sub_jobs.each_with_index.map do |j, i|
         | 
| 28 28 | 
             
                            j['_mngbid_index_'] = i # This allows duplicate jobs when a Redis Set is used
         | 
| 29 | 
            -
                            j = ActiveJob::Arguments.serialize([j])
         | 
| 29 | 
            +
                            j = ::ActiveJob::Arguments.serialize([j])
         | 
| 30 30 | 
             
                            JSON.unparse(j)
         | 
| 31 31 | 
             
                          end
         | 
| 32 32 | 
             
                          if ordered
         | 
| @@ -104,7 +104,7 @@ module CanvasSync | |
| 104 104 | 
             
                    return unless next_job_json.present?
         | 
| 105 105 |  | 
| 106 106 | 
             
                    next_job = JSON.parse(next_job_json)
         | 
| 107 | 
            -
                    next_job = ActiveJob::Arguments.deserialize(next_job)[0]
         | 
| 107 | 
            +
                    next_job = ::ActiveJob::Arguments.deserialize(next_job)[0]
         | 
| 108 108 |  | 
| 109 109 | 
             
                    Batch.new(root_bid).jobs do
         | 
| 110 110 | 
             
                      Batch.new.tap do |batch|
         | 
| @@ -171,7 +171,7 @@ module CanvasSync | |
| 171 171 | 
             
                    jobs_key = "#{redis_key}-jobs"
         | 
| 172 172 | 
             
                    # This allows duplicate jobs when a Redis Set is used
         | 
| 173 173 | 
             
                    job_desc[:_pool_random_key_] = SecureRandom.urlsafe_base64(10)
         | 
| 174 | 
            -
                    job_json = JSON.unparse(ActiveJob::Arguments.serialize([job_desc]))
         | 
| 174 | 
            +
                    job_json = JSON.unparse(::ActiveJob::Arguments.serialize([job_desc]))
         | 
| 175 175 | 
             
                    order = self.order
         | 
| 176 176 |  | 
| 177 177 | 
             
                    redis.multi do |r|
         | 
| @@ -204,7 +204,7 @@ module CanvasSync | |
| 204 204 |  | 
| 205 205 | 
             
                    return nil unless job_json.present?
         | 
| 206 206 |  | 
| 207 | 
            -
                    ActiveJob::Arguments.deserialize(JSON.parse(job_json))[0]&.symbolize_keys
         | 
| 207 | 
            +
                    ::ActiveJob::Arguments.deserialize(JSON.parse(job_json))[0]&.symbolize_keys
         | 
| 208 208 | 
             
                  end
         | 
| 209 209 |  | 
| 210 210 | 
             
                  def self.redis(&blk)
         | 
| @@ -49,7 +49,7 @@ module CanvasSync | |
| 49 49 | 
             
                    end
         | 
| 50 50 |  | 
| 51 51 | 
             
                    def should_handle_batch?(msg)
         | 
| 52 | 
            -
                      return false if  | 
| 52 | 
            +
                      return false if JobBatches::Sidekiq.is_activejob_job?(msg)
         | 
| 53 53 | 
             
                      true
         | 
| 54 54 | 
             
                    end
         | 
| 55 55 | 
             
                  end
         | 
| @@ -75,6 +75,22 @@ module CanvasSync | |
| 75 75 | 
             
                    end
         | 
| 76 76 | 
             
                  end
         | 
| 77 77 |  | 
| 78 | 
            +
                  def self.is_activejob_job?(msg)
         | 
| 79 | 
            +
                    return false unless defined?(::ActiveJob)
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    msg['class'] == 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper' && (msg['wrapped'].to_s).constantize < JobBatches::ActiveJob::BatchAwareJob
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  def self.switch_tenant(job)
         | 
| 85 | 
            +
                    if defined?(::Apartment)
         | 
| 86 | 
            +
                      ::Apartment::Tenant.switch(job['apartment'] || 'public') do
         | 
| 87 | 
            +
                        yield
         | 
| 88 | 
            +
                      end
         | 
| 89 | 
            +
                    else
         | 
| 90 | 
            +
                      yield
         | 
| 91 | 
            +
                    end
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
             | 
| 78 94 | 
             
                  def self.configure
         | 
| 79 95 | 
             
                    if defined?(::Sidekiq::Batch) && ::Sidekiq::Batch != JobBatches::Batch
         | 
| 80 96 | 
             
                      print "WARNING: Detected Sidekiq Pro or sidekiq-batch. CanvasSync JobBatches may not be fully compatible!"
         | 
| @@ -98,14 +114,12 @@ module CanvasSync | |
| 98 114 | 
             
                      end
         | 
| 99 115 |  | 
| 100 116 | 
             
                      config.death_handlers << ->(job, ex) do
         | 
| 101 | 
            -
                         | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
                           | 
| 117 | 
            +
                        switch_tenant(job) do
         | 
| 118 | 
            +
                          if is_activejob_job?(job)
         | 
| 119 | 
            +
                            JobBatches::ActiveJob.handle_job_death(job["args"][0], ex)
         | 
| 120 | 
            +
                          elsif job['bid'].present?
         | 
| 105 121 | 
             
                            ::Sidekiq::Batch.process_dead_job(job['bid'], job['jid'])
         | 
| 106 122 | 
             
                          end
         | 
| 107 | 
            -
                        else
         | 
| 108 | 
            -
                          ::Sidekiq::Batch.process_dead_job(job['bid'], job['jid'])
         | 
| 109 123 | 
             
                        end
         | 
| 110 124 | 
             
                      end
         | 
| 111 125 | 
             
                    end
         | 
    
        data/lib/canvas_sync/version.rb
    CHANGED