100 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
module Gitlab
 | 
						|
  module Import
 | 
						|
    class SourceUserMapper
 | 
						|
      include Gitlab::ExclusiveLeaseHelpers
 | 
						|
 | 
						|
      LRU_CACHE_SIZE = 8000
 | 
						|
      LOCK_TTL = 15.seconds.freeze
 | 
						|
      LOCK_SLEEP = 0.3.seconds.freeze
 | 
						|
      LOCK_RETRIES = 100
 | 
						|
 | 
						|
      def initialize(namespace:, import_type:, source_hostname:)
 | 
						|
        @namespace = namespace.root_ancestor
 | 
						|
        @import_type = import_type
 | 
						|
        @source_hostname = source_hostname
 | 
						|
      end
 | 
						|
 | 
						|
      def find_source_user(source_user_identifier)
 | 
						|
        cache_from_request_store[source_user_identifier] ||= ::Import::SourceUser.find_source_user(
 | 
						|
          source_user_identifier: source_user_identifier,
 | 
						|
          namespace: namespace,
 | 
						|
          source_hostname: source_hostname,
 | 
						|
          import_type: import_type
 | 
						|
        )
 | 
						|
      end
 | 
						|
 | 
						|
      def find_or_create_source_user(source_name:, source_username:, source_user_identifier:)
 | 
						|
        source_user = find_source_user(source_user_identifier)
 | 
						|
 | 
						|
        return source_user if source_user
 | 
						|
 | 
						|
        source_user = create_source_user(
 | 
						|
          source_name: source_name,
 | 
						|
          source_username: source_username,
 | 
						|
          source_user_identifier: source_user_identifier
 | 
						|
        )
 | 
						|
 | 
						|
        cache_from_request_store[source_user_identifier] = source_user
 | 
						|
      end
 | 
						|
 | 
						|
      private
 | 
						|
 | 
						|
      attr_reader :namespace, :import_type, :source_hostname
 | 
						|
 | 
						|
      def cache_from_request_store
 | 
						|
        Gitlab::SafeRequestStore[:source_user_cache] ||= LruRedux::Cache.new(LRU_CACHE_SIZE)
 | 
						|
      end
 | 
						|
 | 
						|
      def create_source_user(source_name:, source_username:, source_user_identifier:)
 | 
						|
        in_lock(
 | 
						|
          lock_key(source_user_identifier), ttl: LOCK_TTL, sleep_sec: LOCK_SLEEP, retries: LOCK_RETRIES
 | 
						|
        ) do |retried|
 | 
						|
          if retried
 | 
						|
            source_user = find_source_user(source_user_identifier)
 | 
						|
            next source_user if source_user
 | 
						|
          end
 | 
						|
 | 
						|
          create_source_user_mapping(source_name, source_username, source_user_identifier)
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      def create_source_user_mapping(source_name, source_username, source_user_identifier)
 | 
						|
        ::Import::SourceUser.transaction do
 | 
						|
          import_source_user = ::Import::SourceUser.new(
 | 
						|
            namespace: namespace,
 | 
						|
            import_type: import_type,
 | 
						|
            source_username: source_username,
 | 
						|
            source_name: source_name,
 | 
						|
            source_user_identifier: source_user_identifier,
 | 
						|
            source_hostname: source_hostname
 | 
						|
          )
 | 
						|
 | 
						|
          import_source_user.placeholder_user = create_placeholder_user(import_source_user)
 | 
						|
          import_source_user.save!
 | 
						|
          import_source_user
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      def create_placeholder_user(import_source_user)
 | 
						|
        return namespace_import_user if placeholder_user_limit_exceeded?
 | 
						|
 | 
						|
        Gitlab::Import::PlaceholderUserCreator.new(import_source_user).execute
 | 
						|
      end
 | 
						|
 | 
						|
      def namespace_import_user
 | 
						|
        Gitlab::Import::ImportUserCreator.new(portable: namespace).execute
 | 
						|
      end
 | 
						|
 | 
						|
      def placeholder_user_limit_exceeded?
 | 
						|
        ::Import::PlaceholderUserLimit.new(namespace: namespace).exceeded?
 | 
						|
      end
 | 
						|
 | 
						|
      def lock_key(source_user_identifier)
 | 
						|
        "import:source_user_mapper:#{namespace.id}:#{import_type}:#{source_hostname}:#{source_user_identifier}"
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |