SysMO-DB/seek

View on GitHub
app/jobs/auth_lookup_update_job.rb

Summary

Maintainability
B
4 hrs
Test Coverage
class AuthLookupUpdateJob

  include CommonSweepers

  @@my_yaml = AuthLookupUpdateJob.new.to_yaml

  BATCHSIZE=3

  mattr_accessor :job_queue_name
  @@job_queue_name = "authlookup"

  def perform
    process_queue

    if AuthLookupUpdateQueue.count>0 && !AuthLookupUpdateJob.exists?
      Delayed::Job.enqueue(AuthLookupUpdateJob.new, :priority=>0, :queue=>AuthLookupUpdateJob.job_queue_name,:run_at=>1.seconds.from_now)
    end
  end

  def process_queue
    #including item_type in the order, encourages assets to be processed before users (since they are much quicker), due to tha happy coincidence
    #that User falls last alphabetically. Its not that important if a new authorized type is added after User in the future.
    todo = AuthLookupUpdateQueue.order("priority,item_type,id").limit(BATCHSIZE).collect do |queued|
      todo = queued.item
      queued.destroy
      todo
    end
    todo.uniq.each do |item|
      begin
        if item.nil?
          update_assets_for_user nil
        elsif item.authorization_supported?
          update_for_each_user item
        elsif item.is_a?(User)
          update_assets_for_user item
        elsif item.is_a?(Person)
          update_assets_for_user item.user unless item.user.nil?
        else
          #should never get here
          Delayed::Job.logger.error("Unexepected type encountered: #{item.class.name}")
        end
      rescue Exception=>e
        AuthLookupUpdateJob.add_items_to_queue(item,15.seconds.from_now,1)
      end
    end
    #required to make sure that cached fragments that contain details related to authorization are regenerated after the job has run
    expire_auth_related_fragments
  end

  def update_for_each_user item
    User.transaction(:requires_new=>:true) do
      item.update_lookup_table(nil)
      User.all.each do |user|
        item.update_lookup_table(user)
      end
    end
    GC.start
  end

  def update_assets_for_user user
    User.transaction(:requires_new=>:true) do
      Seek::Util.authorized_types.each do |type|
        type.all.each do |item|
            item.update_lookup_table(user)
        end
      end
    end
    GC.start
  end

  def self.add_items_to_queue items, t=5.seconds.from_now, priority=0, queuepriority=priority
    if Seek::Config.auth_lookup_enabled

      items = [items] if items.nil?
      items = Array(items)

      disable_authorization_checks do
        items.uniq.each do |item|
          #immediately update for the current user and anonymous user
          if item.respond_to?(:authorization_supported?) && item.authorization_supported?
            item.update_lookup_table(User.current_user)
            item.update_lookup_table(nil) unless User.current_user.nil?
          end
          # Could potentially delete the records for this item (either by asset_id or user_id) to ensure an immediate reflection of the change,
          # but with some slowdown until the changes have been reapplied.
          # for assets its simply - item.remove_from_lookup_table
          # for users some additional simple code is required.
          AuthLookupUpdateQueue.create(:item=>item, :priority=>queuepriority) unless AuthLookupUpdateQueue.exists?(item)
        end
        Delayed::Job.enqueue(AuthLookupUpdateJob.new, :priority=>priority, :queue=>AuthLookupUpdateJob.job_queue_name,:run_at=>t) unless AuthLookupUpdateJob.count>10
      end
    end
  end

  def self.exists?
    count!=0
  end

  def self.count ignore_locked=true
    if ignore_locked
      Delayed::Job.where(['handler = ? AND locked_at IS ? AND failed_at IS ?',@@my_yaml,nil,nil]).count
    else
      Delayed::Job.where(['handler = ? AND failed_at IS ?',@@my_yaml,nil]).count
    end
  end

  
end