class Kameleoon::Managers::Tracking::LockVisitorTrackingRegistry

def add(visitor_code)

def add(visitor_code)
  @mutex.synchronize { @visitors.add(visitor_code) }
end

def add_all(visitor_codes)

def add_all(visitor_codes)
  @mutex.synchronize do
    @visitors.merge(visitor_codes)
    if @visitors.size > @storage_limit
      erase_nonexistent_visitors
      erase_to_storage_limit
    end
  end
end

def erase_nonexistent_visitors

Not thread-safe
def erase_nonexistent_visitors
  @visitors.delete_if { |vc| @visitor_manager.get_visitor(vc).nil? }
end

def erase_to_storage_limit

Not thread-safe
def erase_to_storage_limit
  visitors_to_remove_count = @visitors.size - (@storage_limit * REMOVAL_FACTOR).to_i
  return if visitors_to_remove_count <= 0
  @visitors.each do |vc|
    break if visitors_to_remove_count.zero?
    visitors_to_remove_count -= 1
    @visitors.delete(vc)
  end
end

def extract

def extract
  should_extract_all_be_used ? extract_all : extract_limited
end

def extract_all

def extract_all
  old_visitors = nil
  new_visitors = Set.new
  @mutex.synchronize do
    old_visitors = @visitors
    @visitors = new_visitors
  end
  old_visitors
end

def extract_limited

def extract_limited
  extracted = nil
  @mutex.synchronize do
    if should_extract_all_be_used
      extracted = extract_all
      next
    end
    i = 0
    extracted = []
    @visitors.each do |vc|
      break if i >= @extraction_limit
      extracted.push(vc)
      i += 1
      @visitors.delete(vc)
    end
  end
  extracted
end

def initialize(visitor_manager, storage_limit = 1_000_000, extraction_limit = 20_000)

def initialize(visitor_manager, storage_limit = 1_000_000, extraction_limit = 20_000)
  @visitor_manager = visitor_manager
  @storage_limit = storage_limit
  @extraction_limit = extraction_limit
  @visitors = Set.new
  @mutex = Mutex.new
end

def should_extract_all_be_used

def should_extract_all_be_used
  @visitors.size < @extraction_limit * LIMITED_EXTRACTION_THRESHOLD_COEFFICIENT
end