집계 엔진 GraphQL 통합
이 문서는 Gitlab::Database::Aggregation::Graphql::Mounter 모듈을 사용하여 집계 엔진을 GraphQL과 통합하는 방법을 설명합니다. GraphQL 통합은 다음을 자동으로 생성합니다:
이 문서는 Gitlab::Database::Aggregation::Graphql::Mounter 모듈을 사용하여 집계 엔진을 GraphQL과 통합하는 방법을 설명합니다.
개요#
GraphQL 통합은 다음을 자동으로 생성합니다:
- 마운트된 엔진을 위한 쿼리 필드
- 엔진 필터 정의를 기반으로 하는 필터 인수
- 엔진 차원 및 메트릭 정의를 기반으로 하는 정렬 인수. 스네이크 케이스 차원 및 메트릭 식별자를 정렬 식별자로 사용 가능
- 차원과 메트릭을 필드로 포함하는 응답 유형
- 매개변수가 있는 차원과 메트릭을 위한 매개변수화된 필드
- 페이지네이션: 집계 결과는 OFFSET 페이지네이션을 사용하여 자동으로 페이지네이션됩니다
엔진 마운트#
GraphQL 유형에서 mount_aggregation_engine 메서드를 사용하여 집계 엔진을 노출합니다:
module Types
class ProjectType < BaseObject
extend Gitlab::Database::Aggregation::Graphql::Mounter
mount_aggregation_engine(
IssueAggregationEngine,
field_name: 'issue_analytics',
description: 'Issue analytics aggregation'
) do
# 기본 집계 스코프를 정의합니다. 자체 스코프를 구성하거나 부모 객체에서 상속합니다.
def aggregation_scope
object.issues
end
end
end
end
- GraphQL 필드에 대한 권한 부여 및 적절한 기본 스코프를 반드시 처리하거나 GraphQL 필드에 대한 상승된 권한 요구 사항을 정의해야 합니다.
- 참고: 모든 필터, 메트릭 및 차원은 자동으로 노출됩니다.
Mounter 옵션#
| 옵션 | 타입 | 설명 |
|---|---|---|
field_name |
String/Symbol | GraphQL 필드 이름. 기본값: :aggregation |
types_prefix |
String/Symbol | *AggregationResponse 및 *AggregationDimensions와 같은 모든 자식 유형의 접두사. 기본값: field_name |
description |
String | GraphQL 필드에 대한 설명 |
생성된 GraphQL 서브트리에 대한 GraphQL 쿼리 예시#
생성된 GraphQL 서브트리는 두 단계 구조를 사용합니다:
-
외부 필드(
issueAnalytics)는 차원 및 비메트릭 필터 인수를 허용합니다. -
내부
aggregated필드는 메트릭 필터, 정렬, 페이지네이션 인수를 허용하며 페이지네이션된 연결을 반환합니다.
query IssueAnalytics($projectId: ID!) {
project(fullPath: $projectId) {
issueAnalytics(
state: ["opened", "closed"]
createdAtFrom: "2024-01-01"
createdAtTo: "2024-12-31"
) {
aggregated(
totalCountFrom: 5
orderBy: [{ identifier: "totalCount", direction: DESC }]
first: 10
) {
nodes {
dimensions {
createdAt(granularity: "monthly")
}
totalCount
meanWeight
highQuantile: durationQuantile(0.9)
medianQuantile: durationQuantile(0.5)
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
필터 배치#
필터 인수는 필터가 적용되는 시점에 따라 두 단계에 분산됩니다:
-
비메트릭 필터(
exact_match또는range로 정의된 필터)는 외부 필드(예:issueAnalytics)에 나타납니다. -
메트릭 필터(
metric_exact_match또는metric_range로 정의된 필터)는 내부aggregated필드에 나타납니다.
커스텀 요청 유효성 검사#
GraphQL 스키마를 유지하면서 특정 집계 요청을 거부하는 커스텀 유효성 검사 로직을 추가할 수 있습니다. 이는 특정 요청에 커스텀 런타임 제약을 적용해야 할 때 유용합니다.
커스텀 오류 메시지와 함께 요청을 거부하려면 GraphQL::ExecutionError를 발생시킵니다.
커스텀 유효성 검사를 추가하려면 마운팅 블록에서 validate_request! 메서드를 재정의합니다:
module Types
class ProjectType < BaseObject
extend Gitlab::Database::Aggregation::Graphql::Mounter
mount_aggregation_engine(IssueAggregationEngine) do
# 기타 구성 옵션...
# 커스텀 유효성 검사 로직
def validate_request!(engine_request)
if engine_request.dimensions.empty?
raise GraphQL::ExecutionError, 'At least one dimension must be specified'
end
end
end
end
end
validate_request! 메서드는 dimensions, metrics, filters 및 order 사양이 포함된
Gitlab::Database::Aggregation::Request 객체를 받습니다.
ActiveRecord 연관 관계를 위한 차원#
차원은 association: true 옵션을 사용하여 연관 관계로 표시할 수 있습니다. 이렇게 하면 차원이
GraphQL에서 노출되는 방식이 변경되어 ID만 노출하는 대신 연관된 모델이 자동으로 해석됩니다.
연관 관계 차원 정의#
집계 엔진에서 association: true로 차원을 선언합니다:
class AgentPlatformSessions < Gitlab::Database::Aggregation::ClickHouse::Engine
dimensions do
column :flow_type, :string, description: 'Type of session'
column :user_id, :integer, description: 'Session owner', association: true
end
end
GraphQL 스키마 영향#
차원이 연관 관계로 표시되면 원시 *_id 필드 대신 객체가 노출됩니다. 위의 차원은 GraphQL에서
ID별 배치 로딩이 적용된 field :user, Types::UserType, ...으로 변환됩니다.
_id 접미사 없이 연관 관계 이름을 사용하여 연관 관계 ID로 정렬할 수 있습니다
(예: orderBy: [{ identifier: "user", direction: DESC }]).
연관 관계 GraphQL 유형에 대한 적절한 권한 부여 확인을 반드시 확인해야 합니다
(예: authorize :read_user).
커스텀 연관 관계 구성#
기본적으로 연관 관계 모델과 GraphQL 유형은 차원 이름에서 추론됩니다:
- 모델:
user_id→User - GraphQL 유형:
User→Types::UserType
association 옵션에 해시를 전달하여 이 동작을 커스터마이즈할 수 있습니다:
dimensions do
column :author_id, :integer,
description: 'Issue author',
association: { model: User }
# 또는 모델과 GraphQL 유형
# association: { model: User, graphql_type: Types::CurrentUserType }
end
GraphQL 쿼리 예시#
연관 관계 없음
query {
project(fullPath: "gitlab-org/gitlab") {
aiUsage {
agentPlatformSessions {
nodes {
dimensions {
userId # 반환: 123 (정수)
}
}
}
}
}
}
연관 관계 있음
query {
project(fullPath: "gitlab-org/gitlab") {
aiUsage {
agentPlatformSessions(
userId: [1, 2] # 필터는 여전히 원래 차원 식별자를 사용
orderBy: [{ identifier: "user", direction: DESC }] # 정렬은 연관 관계 이름 사용
) {
nodes {
dimensions {
user { # 반환: 전체 User 객체
id
username
name
}
}
}
}
}
}
}
