This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned on this page are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.
Status Authors Coach DRIs Owning Stage Created
proposed @vshumilo @vitallium @tgolubeva @jameslopez devops fulfillment 2024-02-07

CustomersDot Plan 관리 자동화

요약

GitLab Customers Portal은 GitLab 제품과 별도로 독립적으로 설계된 애플리케이션으로, GitLab 고객이 계정, 구독 및 추가 좌석 구매 및 갱신과 같은 작업을 관리할 수 있도록 지원합니다. Customers Portal에 대한 자세한 정보는 GitLab 문서에서 확인할 수 있습니다. 내부적으로는 CustomersDot(또는 CDot이라고도 함)이라고 불립니다.

GitLab은 모든 제품 관련 정보의 Single Source of Truth(SSoT)로 Zuora 플랫폼을 사용합니다. Zuora 제품 카탈로그는 판매 가능한 수익 창출 제품 및 서비스의 전체 목록을 나타내며, 이는 CustomersDot의 의사 결정에 필수적인 핵심 지식입니다. CustomersDot은 현재 IronBank gem과 LocalRecord 확장 기능을 통해 Zuora 제품 카탈로그의 로컬 캐시를 보유하고 있습니다.

CustomersDot은 Plan을 사용하여 제품 카탈로그의 모든 세부 정보에 쉽게 액세스합니다. 제품 이름, 가격, 최소 수량 등과 같은 Plan의 세부 정보는 Zuora::ProductRatePlan, Zuora::ProductRatePlanCharge, Zuora::ProductRatePlanChargeTier 객체에 분산되어 있으므로, 이러한 세부 정보에 대한 전통적인 액세스는 번거로울 수 있습니다. 이 클래스는 모든 이러한 세부 정보를 조회할 필요 없이 이러한 세부 정보를 저장하기 때문에 매우 유용합니다. 또한 이 클래스는 Zuora::ProductRatePlan을 등급, 배포 유형 및 응용 프로그램 전체에서 사용할 기준 등에 따라 분류하는 데 도움을 줍니다.

CustomersDot의 캐시된 제품 카탈로그는 현재 수동으로 동기화되며, Plan 클래스의 제한으로 인해 완전히 새로 고침하려면 CustomersDot을 다시 시작해야 합니다. 새 제품, 제품 요금제 또는 제품 요금제 계층이 Zuora 제품 카탈로그에 업데이트되거나 추가될 때마다 Plan 클래스에 추가 수동 노력이 필요합니다.

이 설계 문서의 주요 목표는 CustomersDot 내의 Plan 모델의 아키텍처와 유지 관리성을 개선하는 데 있습니다. Zuora에서 제품 카탈로그가 업데이트되면, 앱 재시작, 코드 변경 또는 수동 개입 없이 CustomersDot에 자동으로 반영될 수 있도록 하는 것입니다.

동기

현재 Zuora 제품 카탈로그 업데이트가 CustomersDot에 자동으로 반영되지 않는 두 가지 이유가 있습니다:

  • CustomersDot의 캐시된 제품 카탈로그 동기화는 Rails 콘솔을 통해 수동 개입이 필요하며, PlanZuora::ProductRatePlan 분류에 상수 및 클래스 변수를 강하게 의존하므로 완전한 새로 고침을 위해 서버 재시작이 필요합니다.
  • 새 제품/SKU가 Zuora 제품 카탈로그에 추가되는 경우, 앞서 설명한 캐시가 새로 고쳐지더라도 CustomersDot에서 이를 사용할 수 있게 하려면 코드 변경이 필요합니다. 이는 Plan 클래스가 Zuora::ProductRatePlan id를 상수에 할당하고 이후 수동으로 다양한 범주(예: Ultimate 티어의 모든 요금제 또는 GitLab.com의 자체 구매용 추가 기능)를 나타내기 위해 id 그룹을 형성하도록 하는 현재 전략 때문입니다. 코드베이스와 제품 수가 늘어날수록 이러한 수동 개입은 더 비용이 많이 듭니다.

목표

주요 목표는 다음과 같습니다:

  • CustomersDot 캐시된 제품 카탈로그가 언제든 Zuora와 동기화되도록 보장합니다.
  • CustomersDot에서 기본적인 제품 카탈로그 업데이트에 대해 수동 개입이 필요 없도록 CustomersDot Plan 관리를 자동화합니다. 즉, 새 제품/SKU 추가, RatePlanCharge 업데이트 또는 제품 중단이 포함됩니다. 이를 위해 CustomersDot의 현재 방식을 벗어나고 LocalRecords에서 요구에 따라 이러한 세트를 동적으로 해결할 수 있도록 ProductCatalog에 CustomersDot 메타데이터를 추가하여 분류 지식을 전달합니다.

제안

현재 CustomersDot은 IronBank gem과 LocalRecord 확장 기능를 통해 Zuora의 제품 카탈로그의 로컬 캐시를 보유하고 있습니다.

현재 우리는 Zuora에서 CustomersDot에 관심 있는 새로운 변경 사항이 있음을 통보받으면 이 캐시를 수동으로 새로 고침합니다:

sequenceDiagram participant CustomersDot participant Zuora Note left of CustomersDot: Rails 콘솔을 통해 제품 카탈로그 새로 고침이 트리거됨 CustomersDot->>Zuora: 제품 카탈로그 GET Zuora->>CustomersDot: 제품 카탈로그 응답 CustomersDot->>CustomersDot: LocalRecord 데이터베이스에 제품 카탈로그의 복사본 캐시 Note left of CustomersDot: 미래 제품 카탈로그 조회에 LocalRecords 사용 CustomersDot->>CustomersDot: Zuora::Product GET CustomersDot->>CustomersDot: Zuora::ProductRatePlan GET Note right of Zuora: 제품 정보가 업데이트됨 CustomersDot->>CustomersDot: Zuora::ProductRatePlanCharge GET CustomersDot->>CustomersDot: Zuora::ProductRatePlanChargeTier GET Note left of CustomersDot: 다음 배포까지 Zuora 변경 내용이<br/>CustomersDot에서 알려지지 않음 ### Iteration 1 Zuora와 Product Catalog를 언제든지 동기화 상태로 유지합니다: ```mermaid sequenceDiagram participant CustomersDot participant Zuora Note right of Zuora: 제품 정보가 업데이트되었습니다 Zuora->>CustomersDot: 제품 업데이트에 대한 알림 CustomersDot->>Zuora: 제품 카달로그 가져오기(GET Product Catalog) Zuora->>CustomersDot: 제품 카달로그로 응답 CustomersDot->>CustomersDot: 제품 카달로그 캐시(LocalRecord database) 새로고침 Note left of CustomersDot: CustomersDot 제품 카달로그<br/>캐시가 Zuora와 동기화 상태입니다

Iteration 2

CustomersDot의 분류 지식을 Zuora 제품 카달로그에 추가하여 (고객 분류 지식을 사용하여) 요구에 따라 LocalRecord에서 ProductRatePlan을 직접 해결할 수 있도록합니다.

우리는 제품 카달로그에 다음과 같은 사용자 지정 필드를 추가하기를 제안합니다:

--- title: Zuora 제품 카달로그 제안 사항 추가 --- erDiagram "Product" ||--|{ "ProductRatePlan" : "has many" "ProductRatePlan" ||--|{ "ProductRatePlanCharge" : "has many" "ProductRatePlanCharge" ||--|{ "ProductRatePlanChargeTier" : "has many" "Product" { enum Tier__c enum DeploymentType__c } "ProductRatePlan" { boolean WebDirect__c }

Iteration 3

(반복 2에서 소개된) 사용자 정의 메타데이터를 사용하여 Zuora Product Catalog로부터 ProductRatePlan을 직접 해결하고 전체 캐시 새로고침을 방해하는 Plan 상수를 제거합니다.

디자인 및 구현 세부 정보

Iteration 1

(Iteration 1) 제품 카달로그는 Zuora와 동기화 상태입니다

  • 첫 번째 반복에서 매일 제품 카달로그를 새로 고치는 Cron 작업을 추가하고 즉시 가치를 더합니다.
  • 다음을 요청하는 Finance Systems 이슈를 생성합니다:
    • Zuora 제품 카달로그에서 레코드용 사용자 지정 필드를 업데이트할 때의 새로운 사용자 지정 이벤트 | 기본 오브젝트 | 사용자 지정 이벤트 이름 | | ————————- | ————————————– | | Product | CatalogProductUpdate | | ProductRatePlan | CatalogProductRatePlanUpdate | | ProductRatePlanCharge | CatalogProductRatePlanChargeUpdate | | ProductRatePlanChargeTier | CatalogProductRatePlanChargeTierUpdate |
    • Zuora 제품 카달로그에서 레코드가 추가, 삭제 또는 업데이트될 때의 Billing 컴포넌트에 대한 새로운 콜아웃
  • 중복 미들웨어, 콜백, 추가적인 Rails 작업을 포함시키지 않고 가능한 빠르게하기 위해 ActionController::Metal을 기반으로 CustomersDot에 새 컨트롤러를 작성합니다.

    module Zuora
      class WebHooksController < ActionController::Metal
        feature_category :platform
    
        def create
          # 단계 1. 수신 웹훅 페이로드를 유효성 검사하고 데이터베이스에 저장
          # 단계 2. SyncProductCatalogJob을 시작합니다
          head :ok
        end
      end
    end
    

    단계가 지나치게 많은 제품 카달로그 업데이트 알림을 받을 경우 SyncProductCatalogJob의 디바운싱 전략을 보장합니다. 초기에는 실행을 5분 동안 지연시키고 큐에 이미 작업이 들어가있으면 새로운 작업을 추가하지 않도록합니다.

(Iteration 2) CustomersDot의 분류 지식을 Zuora 제품 카달로그로 이전

모든 변경 사항은 Finance Systems 이슈를 필요로 합니다.

  • 기존 필드 Zuora::Product#category를 검토하여 모든 제품에 대해 올바르게 설정되어 있는지 확인합니다. 가능한 값: [null, "Base Products", "Add On Services", "Miscellaneous Products"].
  • 새로운 사용자 지정 필드 Zuora::ProductRatePlan#web_direct를 추가하여 boolean이 될 수 있도록합니다.
    • true: 해당 플랜은 셀프 서비스를 위해 이용 가능
    • false: 해당 플랜은 셀프 서비스를 위해 이용 불가능
  • Product#tier에 새로운 사용자 지정 필드 enum를 추가합니다 (다중 선택). 가능한 값: [premium, ultimate, starter, bronze, silver, gold, free, null]
  • Product#deployment_type에 새로운 사용자 지정 필드 enum를 추가합니다 (다중 선택). 가능한 값: [self_managed, dedicated, gitlab_dot_com]

추가된 각 필드에 대해: Zuora의 값은 Zuora::ProductRatePlan ID의 현재 그룹화에 의한 CustomersDot 분류와 일치해야합니다.

참고: 현재 노력을 통해 이러한 필드 중 일부를 Zuora에 추가 중이므로 재사용할 수 있을 것으로 예상됩니다. 재사용하는 경우 Zuora의 값과 CustomersDot 분류가 각각의 항목에 대해 일치하는지 두 번 확인해야합니다.

(Iteration 3) 이 Zuora 사용자 지정 메타데이터를 사용하여 Zuora 제품 카달로그로부터 ProductRatePlan을 직접 해결하기

  • 반복 2에서 소개된 메타데이터를 기반으로 Zuora::ProductZuora::ProductRatePlan을 가져오기 위한 스코프를 생성합니다. 가능한 스코프:
    • self_managed
    • dedicated
    • gitlab_dot_com
    • base_products
    • add_ons
    • web_direct
    • sales_assisted
    • ultimate
    • premium
    • active (유효 시작/종료 날짜 기준)
  • 주어진 분류를 충족하는 레코드의 모음을 나타내는 Plan 상수의 사용을 제거하고 구현된 스코프를 사용하여 LocalRecords에서 동일한 컬렉션을로드하는 방법으로 대체합니다. 예: ALL_ULTIMATE_SM_PLANSZuora::Product.self_managed.ultimate.flat_map(&:product_rate_plans).map(&:id)로 대체할 수 있습니다. 각 반복이 얼마나 복잡한지에 따라 기능 플래그가 필요한지 여부를 결정할 수 있습니다.