86 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
class AsyncRefresh
 | 
						|
  extend Redisable
 | 
						|
  include Redisable
 | 
						|
 | 
						|
  NEW_REFRESH_EXPIRATION = 1.day
 | 
						|
  FINISHED_REFRESH_EXPIRATION = 1.hour
 | 
						|
 | 
						|
  def self.find(id)
 | 
						|
    redis_key = Rails.application.message_verifier('async_refreshes').verify(id)
 | 
						|
    new(redis_key) if redis.exists?(redis_key)
 | 
						|
  rescue ActiveSupport::MessageVerifier::InvalidSignature
 | 
						|
    nil
 | 
						|
  end
 | 
						|
 | 
						|
  def self.create(redis_key, count_results: false)
 | 
						|
    data = { 'status' => 'running' }
 | 
						|
    data['result_count'] = 0 if count_results
 | 
						|
    redis.hset(redis_key, data)
 | 
						|
    redis.expire(redis_key, NEW_REFRESH_EXPIRATION)
 | 
						|
    new(redis_key)
 | 
						|
  end
 | 
						|
 | 
						|
  def self.exists?(redis_key)
 | 
						|
    redis.exists?(redis_key)
 | 
						|
  end
 | 
						|
 | 
						|
  attr_reader :status, :result_count
 | 
						|
 | 
						|
  def initialize(redis_key)
 | 
						|
    @redis_key = redis_key
 | 
						|
    fetch_data_from_redis
 | 
						|
  end
 | 
						|
 | 
						|
  def id
 | 
						|
    Rails.application.message_verifier('async_refreshes').generate(@redis_key)
 | 
						|
  end
 | 
						|
 | 
						|
  def running?
 | 
						|
    @status == 'running'
 | 
						|
  end
 | 
						|
 | 
						|
  def finished?
 | 
						|
    @status == 'finished'
 | 
						|
  end
 | 
						|
 | 
						|
  def finish!
 | 
						|
    redis.pipelined do |pipeline|
 | 
						|
      pipeline.hset(@redis_key, { 'status' => 'finished' })
 | 
						|
      pipeline.expire(@redis_key, FINISHED_REFRESH_EXPIRATION)
 | 
						|
    end
 | 
						|
    @status = 'finished'
 | 
						|
  end
 | 
						|
 | 
						|
  def increment_result_count(by: 1)
 | 
						|
    redis.hincrby(@redis_key, 'result_count', by)
 | 
						|
    fetch_data_from_redis
 | 
						|
  end
 | 
						|
 | 
						|
  def reload
 | 
						|
    fetch_data_from_redis
 | 
						|
    self
 | 
						|
  end
 | 
						|
 | 
						|
  def to_json(_options)
 | 
						|
    {
 | 
						|
      async_refresh: {
 | 
						|
        id:,
 | 
						|
        status:,
 | 
						|
        result_count:,
 | 
						|
      },
 | 
						|
    }.to_json
 | 
						|
  end
 | 
						|
 | 
						|
  private
 | 
						|
 | 
						|
  def fetch_data_from_redis
 | 
						|
    @status, @result_count = redis.pipelined do |pipeline|
 | 
						|
      pipeline.hget(@redis_key, 'status')
 | 
						|
      pipeline.hget(@redis_key, 'result_count')
 | 
						|
    end
 | 
						|
    @result_count = @result_count.presence&.to_i
 | 
						|
  end
 | 
						|
end
 |