# frozen_string_literal: true module Resolvers class PackagePipelinesResolver < BaseResolver include Gitlab::Graphql::Authorize::AuthorizeResource type Types::Ci::PipelineType.connection_type, null: true extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension authorizes_object! authorize :read_pipeline alias_method :package, :object # this resolver can be called for 100 packages max and we want to limit the # number of build infos returned for _each_ package when using the new finder. MAX_PAGE_SIZE = 20 # This returns a promise for a connection of promises for pipelines: # Lazy[Connection[Lazy[Pipeline]]] structure def resolve(first: nil, last: nil, after: nil, before: nil, lookahead:) default_value = default_value_for(first: first, last: last, after: after, before: before) BatchLoader::GraphQL.for(package.id) .batch(default_value: default_value) do |package_ids, loader| build_infos = ::Packages::BuildInfosFinder.new( package_ids, first: first, last: last, after: decode_cursor(after), before: decode_cursor(before), max_page_size: MAX_PAGE_SIZE, support_next_page: lookahead.selects?(:page_info) ).execute build_infos.each do |build_info| loader.call(build_info.package_id) do |connection| connection.items << lazy_load_pipeline(build_info.pipeline_id) connection end end end end # we manage the pagination manually, so opt out of the connection field extension def self.field_options super.merge( connection: false, extras: [:lookahead] ) end private def lazy_load_pipeline(id) ::Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, id) .find end def default_value_for(first:, last:, after:, before:) Gitlab::Graphql::Pagination::ActiveRecordArrayConnection.new( [], first: first, last: last, after: after, before: before, max_page_size: MAX_PAGE_SIZE ) end def decode_cursor(encoded) return unless encoded decoded = Gitlab::Json.parse(context.schema.cursor_encoder.decode(encoded, nonce: true)) id_from_cursor(decoded) rescue JSON::ParserError raise Gitlab::Graphql::Errors::ArgumentError, "Please provide a valid cursor" end def id_from_cursor(cursor) cursor&.fetch('id') rescue KeyError raise Gitlab::Graphql::Errors::ArgumentError, "Please provide a valid cursor" end end end