셀(Cell)에 속성 클레임하기
GitLab v19.5요약
Cells를 활성화해야 클레임이 적용됩니다. 일부 속성은 클러스터 전체에서 전역적으로 고유해야 합니다. 각 셀은 자체 데이터베이스를 갖고 있어서, 서로 다른 데이터베이스에 걸쳐 고유 제약을 강제할 수 없습니다. 이러한 속성에 대해서는 속성이 특정 셀에 속한다고 클레임하기 위해 토폴로지 서비스와 통신합니다.
Cells를 활성화해야 클레임이 적용됩니다.
속성 클레임이 필요한 이유#
일부 속성은 클러스터 전체에서 전역적으로 고유해야 합니다. 예를 들어 라우팅을 위해서는 특정 URL이나 식별자가 최대 하나의 셀에만 속하도록 보장해야 그 셀로 라우팅할 수 있습니다.
각 셀은 자체 데이터베이스를 갖고 있어서, 서로 다른 데이터베이스에 걸쳐 고유 제약을 강제할 수 없습니다. 따라서 이러한 속성이 고유한지 보장하려면 클러스터 전체 데이터베이스가 필요합니다.
이러한 속성에 대해서는 속성이 특정 셀에 속한다고 클레임하기 위해 토폴로지 서비스와 통신합니다. 한 번 클레임되면 다른 셀은 같은 속성을 클레임할 수 없습니다.
클레임할 속성 결정#
속성이 다음에 해당하는지 고려합니다:
- 라우팅에 사용되는지
- URL에 사용되는지
- REST API에 사용되는지
- GraphQL API에 사용되는지
- 로그인에 사용되는지
롤아웃 라이프사이클#
새 속성을 클레임하려면 두 단계가 필요하고, 각 단계는 서로 다른 목적을 수행합니다.
속성별 feature_flag:가 두 단계를 모두 제어합니다. 비활성화된 속성은 라이브
클레임에서 건너뛰고, 검증에서도 건너뜁니다.
1단계: 라이브 요청 클레임#
모델에 Cells::Claimable 컨선(concern)을 추가하고, 선택적으로 새 속성의 롤아웃을 위한
임시 feature_flag:를 추가합니다. 클레임이 활성화되면 Rails의 after_save와
before_destroy 콜백이 모든 생성, 업데이트, 삭제에 대해 토폴로지 서비스에서 속성을
클레임하고 해제합니다.
이 단계는 새로 쓰는 데이터만 처리합니다. 데이터베이스의 기존 레코드는 2단계까지 클레임되지 않습니다.
모델을 구성하는 방법은 속성 클레임 방법을 참고합니다.
Cells::Claimable 컨선은 ActiveRecord 콜백에 의존합니다. delete_all,
insert_all, upsert_all 또는 원시 SQL을 사용하는 코드 경로는 이러한
콜백을 우회합니다. 이러한 코드 경로에서는 데이터베이스 트랜잭션 외부에서
클레임을 처리하도록 Cells::BulkClaimsWorker를 사용합니다. 자세한 내용과
기존 패턴은
ActiveRecord를 우회하는 코드 경로에 대한 벌크 클레임을 참고합니다.
2단계: 백필 및 검증#
모델에 클레임 가능한 속성이 하나라도 활성화되면 검증 서비스가 자동으로 시작됩니다. 첫 실행 시 서비스는 모델의 모든 로컬 레코드를 스캔해 토폴로지 서비스에서 일치하는 클레임을 찾지 못하면 클레임을 생성합니다. 이것이 기존 데이터의 백필 역할을 합니다.
백필이 완료된 후에도 검증 서비스는 크론 스케줄로 계속 실행됩니다. 로컬 레코드를 토폴로지 서비스의 클레임과 조정해 누락된 클레임, 고아 클레임, 변경된 값과 같은 드리프트를 감지하고 수정합니다.
서비스는 현재 활성화된 속성만 조정합니다. 아직 feature_flag: 뒤에 있는
속성은 라이브 클레임과 마찬가지로 백필과 드리프트 수정에서도
건너뜁니다.
검증에 대한 자세한 내용은 검증 및 백필을 참고합니다.
롤아웃 소유권#
두 단계의 롤아웃은 기능을 소유한 팀이 담당합니다. 임시 롤아웃 피처 플래그를 만들고 활성화하는 일, 활성화 후 클레임이 올바르게 동작하는지 모니터링하는 일이 여기에 포함됩니다.
Cells Infrastructure 팀이 도움을 줄 수 있지만, 롤아웃과 정확성 확보의 책임은 기능을 소유한 팀에 있습니다.
클레임 활성화#
cells가 활성화되어 있으면 모델의 속성은 별다른 추가 구성 없이
클레임됩니다. 개별 속성이 롤아웃을 위한 임시 feature_flag:를 아직
갖고 있는 경우만 예외입니다(자세한 내용은
속성 클레임 방법 참고).
모델의 속성 중 하나라도 활성화되면 그 모델의 검증 워커가 자동으로 실행되므로,
워커를 활성화하는 별도의 단계는
없습니다.
검증 워커 활성화를 참고합니다.
# In Rails console
# Check for any temporary per-attribute rollout flags
Feature.all.select { |f| f.name.start_with?('cells_claims') }
속성 클레임 방법#
각 속성에 대해 세 가지를 클레임합니다:
- 속성의 값(필수
type파라미터와 선택적feature_flag파라미터를 갖는cells_claims_attribute로 정의) - 레코드의 주체(
cells_claims_metadata로 정의) - 레코드의 소스(
cells_claims_metadata로 정의)
[!note] 모든
cells_claims_attribute는type(클레임 유형)을 지정해야 합니다. 새 속성의 클레임을 처음 롤아웃할 때 배포 안전성을 위해 선택적으로feature_flag를 추가할 수 있습니다. 이는 롤아웃 라이프사이클의 일부이고 영구적인 요구 사항이 아니므로, 속성이 프로덕션에서 검증되고 안정화되면 제거해야 합니다. 피처 플래그 제거를 참고합니다.
Rails#
User를 예로 들면 다음과 같습니다:
class User < ApplicationRecord
include Cells::Claimable
cells_claims_attribute :id, type: CLAIMS_CLAIM_TYPE::CLAIM_TYPE_USER_ID
cells_claims_attribute :username, type: CLAIMS_CLAIM_TYPE::CLAIM_TYPE_USERNAME
cells_claims_metadata subject_type: CLAIMS_SUBJECT_TYPE::USER, subject_key: :id
end
먼저 모델에 Cells::Claimable을 포함합니다.
여기서는 id와 username 두 속성을 클레임합니다. 각 속성에는
토폴로지 서비스에 정의된 type(클레임 유형)이 필요합니다(아래에서 설명합니다).
여기서는 두 속성 모두 프로덕션에서 검증되어 임시 롤아웃 플래그가 제거되었으므로
feature_flag가 없습니다. feature_flag를 아직 사용하는 예시는
새 클레임 가능한 모델 추가를
참고합니다.
둘째로 cells_claims_metadata로 메타데이터를 정의합니다. 보통은 subject_type과
subject_key만 설정하면 되고, source_type과 소스 값은 추론됩니다. 이들도
토폴로지 서비스에 정의되어 있어야 합니다.
subject_type과 subject_key는 클레임된 속성을 어느 레코드가 소유하는지
식별합니다. 대개 샤딩 키와 일치하지만 항상 그렇지는 않습니다. 샤딩 키가
맞지 않는 경우에는 판단해서 정합니다.
연관 관계의 변경 사항도 저장할 때 같은 트랜잭션에서 자동으로 클레임됩니다.
새 클레임 가능한 모델 추가#
새 모델에 클레임을 추가할 때는 다음을 수행합니다:
-
새 속성의 롤아웃을 위한 임시 피처 플래그를 만듭니다:
# config/feature_flags/beta/cells_claims_<model>s.yml --- name: cells_claims_<model>s feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/XXX introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/XXX rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/tenant-scale/cells-infrastructure/team/-/issues/XXX milestone: 'XX.X' group: group::cells infrastructure type: beta default_enabled: false -
모델에 클레임 구성을 추가합니다:
class YourModel < ApplicationRecord include Cells::Claimable cells_claims_attribute :id, type: CLAIMS_CLAIM_TYPE::CLAIM_TYPE_YOUR_MODEL_ID, feature_flag: :cells_claims_your_model cells_claims_attribute :unique_attr, type: CLAIMS_CLAIM_TYPE::CLAIM_TYPE_YOUR_MODEL_ATTR, feature_flag: :cells_claims_your_model cells_claims_metadata subject_type: CLAIMS_SUBJECT_TYPE::YOUR_MODEL, subject_key: :id end -
토폴로지 서비스에 유형을 추가합니다(토폴로지 서비스 절 참고)
-
ActiveRecord를 우회하는 코드 경로를 점검합니다(ActiveRecord를 우회하는 코드 경로에 대한 벌크 클레임 참고)
-
테스트를 추가합니다(테스트 절 참고)
피처 플래그 제거#
새로 클레임 가능한 속성은 항상 임시 feature_flag: 뒤에서 도입해야 합니다.
그래야 모델의 나머지 부분과 무관하게 롤아웃을 제어하고 되돌릴 수 있습니다.
이는 롤아웃 라이프사이클의 한 단계이고 영구적인 요구 사항이 아닙니다. 플래그는
배포 안전성을 위해 존재하며, 속성이 프로덕션에서 검증되면
제거합니다.
프로덕션에서 플래그를 전역으로 활성화한 후에는 속성 라이프사이클이 처음부터 끝까지 동작하는지 검증합니다:
- 생성: 레코드를 만들면 속성이 클레임됩니다.
- 삭제: 레코드를 파기하면 클레임이 해제됩니다.
- 이름 변경: 속성을 업데이트하면 이전 클레임이 해제되고 새 클레임이 생성됩니다.
프로덕션에서 최소 일주일 동안 문제없이 클레임이 실행되면, 속성별
feature_flag:를 제거하고 그 플래그의 YAML 파일을 삭제합니다. 제거한 후에는
feature_flag가 설정되지 않으면 cells_claims_enabled_for_attribute?가 true를
반환하므로 Gitlab.config.cell.enabled만 클레임을 제어합니다.
Cells::Claimable을 참고합니다.
같은 플래그가 검증도 제어하므로, 플래그를 제거하면 라이브 클레임뿐 아니라 해당 속성의 백필과 드리프트 수정도 시작됩니다. 검증 워커 활성화를 참고합니다.
이 정리 작업의 예시는 머지 리퀘스트 240942를 참고합니다.
이 머지 리퀘스트는 ServiceDeskSetting에서 cells_claims_service_desk_settings 플래그를 제거했습니다.
특정 값에 대한 클레임 건너뛰기#
모든 속성 값을 클레임하지 않아야 하는 모델도 있습니다. 예를 들면 다음과 같습니다:
Route는 하위 경로(gitlab/project)가 아니라 최상위 경로(gitlab)만 클레임해야 합니다.ServiceDeskSetting은custom_email칼럼의nil값을 클레임하지 않아야 합니다.
어떤 값을 클레임할지 제어하려면 cells_claims_attribute의 if: 옵션을 사용합니다.
if: 옵션은 레코드를 받아 불리언을 반환하는 람다를 받습니다.
if:가 false를 반환하면 생성과 파기 시 그 값을 토폴로지 서비스로 보내지 않습니다.
class Route < ApplicationRecord
include Cells::Claimable
cells_claims_attribute :path, type: CLAIMS_CLAIM_TYPE::CLAIM_TYPE_ROUTE,
if: ->(record) { record.path.exclude?('/') }
end
이 예시에서는 경로에 /가 없는 라우트만 클레임됩니다.
if:의 동작#
- 저장(생성):
if:가true를 반환할 때만 새 클레임이 생성됩니다. - 저장(업데이트): 이전 값을 저장할 때
if:가false를 반환했더라도 이전 값은 항상 파기됩니다. 새 값은if:가true를 반환할 때만 생성됩니다. - 레코드 파기: 파기 요청은
if:가 true를 반환할 때만 전송됩니다. - 검증:
cells_claims_metadata는if:가false를 반환하는 항목을 제외하므로, 검증 서비스가 클레임할 수 없는 값에 대해서는 클레임을 만들지 않습니다.
cells_claims_scope를 사용한 범위 필터링#
검증 서비스가 로컬 레코드를 토폴로지 서비스와 조정할 때는 기본적으로
모델의 모든 레코드를 조회합니다. 쿼리 수준에서 행을 제외하려면
cells_claims_scope DSL을 블록과 함께 사용합니다.
class Route < ApplicationRecord
include Cells::Claimable
cells_claims_scope do
where("strpos(path, '/') = 0")
end
cells_claims_attribute :path, type: CLAIMS_CLAIM_TYPE::CLAIM_TYPE_ROUTE,
if: ->(record) { record.path.exclude?('/') }
end
블록은 ActiveRecord::Relation을 반환해야 합니다. 블록을 제공하지 않으면
기본 범위는 all입니다. 데이터베이스 수준에서 검증 대상에서 행을 제외해야
할 때만 블록을 정의합니다.
if:와 cells_claims_scope는 다음과 같이 함께 사용합니다:
if:는 저장 콜백 중에 레코드별 클레임을 제어합니다.cells_claims_scope는 검증 서비스가 어떤 레코드를 스캔할지 제어합니다.
인스턴스 수준에서만 필터링이 필요하다면(예: nil 값 건너뛰기)
cells_claims_scope를 정의하지 않고 if:만 사용합니다:
class ServiceDeskSetting < ApplicationRecord
include Cells::Claimable
cells_claims_attribute :custom_email,
type: CLAIMS_CLAIM_TYPE::CLAIM_TYPE_SERVICE_DESK_CUSTOM_EMAIL,
if: ->(record) { record.custom_email.present? }
end
ActiveRecord를 우회하는 코드 경로에 대한 벌크 클레임#
Cells::Claimable 컨선은 ActiveRecord 콜백에 의존합니다. delete_all,
insert_all, upsert_all 또는 원시 SQL을 사용하는 코드 경로는 이러한 콜백을
우회하므로, 클레임이 자동으로 생성되거나
파기되지 않습니다.
모델에서 이러한 코드 경로를 점검합니다. 존재한다면 Cells::BulkClaimsWorker로
클레임을 처리합니다. 클레임 작업을 데이터베이스 트랜잭션 외부에 두려면
run_after_commit으로 워커를
스케줄링합니다.
워커는 두 개의 페이로드 키를 받습니다:
destroy_metadata: 클레임을 해제할 레코드의 사전 구성된 메타데이터입니다. 메타데이터는 레코드가 아직 존재하는 동안 확보해야 하므로, 레코드를 삭제하기 전에build_destroy_metadata_for_worker로 만듭니다.create_record_ids: 레코드 ID의 배열입니다. 워커가 데이터베이스에서 해당 레코드를 불러와 클레임 메타데이터를 구성합니다.
# Destroying claims for records deleted outside ActiveRecord
destroy_metadata = records.filter_map do |record|
record.build_destroy_metadata_for_worker(:attribute_name)
end
# Creating claims for records inserted outside ActiveRecord
create_record_ids = [record1.id, record2.id]
# Schedule outside the transaction
run_after_commit do
destroy_metadata.each_slice(Cells::Claimable::BULK_CLAIMS_BATCH_SIZE) do |batch|
Cells::BulkClaimsWorker.perform_async(
YourModel.name, 'attribute_name', { 'destroy_metadata' => batch }
)
end
create_record_ids.each_slice(Cells::Claimable::BULK_CLAIMS_BATCH_SIZE) do |batch|
Cells::BulkClaimsWorker.perform_async(
YourModel.name, 'attribute_name', { 'create_record_ids' => batch }
)
end
end
- 데이터베이스 트랜잭션 외부에서 Sidekiq job을 스케줄링하려면
run_after_commit을 사용합니다. - 워커를 스케줄링하기 전에
cells_claims_enabled_for_attribute?를 확인합니다.
전체 구현 예시는 라우트와 이메일에 벌크 클레임을 추가한 MR !230849를 참고합니다.
테스트#
새로운 것을 클레임할 때는 테스트를 추가해야 합니다. 테스트는 두 개를 추가합니다. 하나는 정의가 올바른 값을 만들어 내는지 확인하는 테스트이고, 다른 하나는 정의가 예상대로 동작하는지 확인하는 테스트입니다.
같은 user 예시를 사용해 모델 테스트에 다음을 추가합니다:
it_behaves_like 'cells claimable model',
subject_type: Cells::Claimable::CLAIMS_SUBJECT_TYPE::USER,
subject_key: :id,
source_type: Cells::Claimable::CLAIMS_SOURCE_TYPE::RAILS_TABLE_USERS,
claiming_attributes: [:id, :username]
source_type이 Cells::Claimable::CLAIMS_SOURCE_TYPE::RAILS_TABLE_USERS로 추론되는 것을 볼 수 있습니다.
다음으로 spec/cells/claims/user_spec.rb에 새 테스트 파일을 추가합니다:
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Claim for User', feature_category: :cell do
subject! { build(:user, email: email.email, emails: [email]) }
let(:email) { build(:email) }
shared_context 'with claims records for User' do
def claims_records(only: {})
claims_records_for(subject, only: only) +
claims_records_for(email, only: only)
end
end
it_behaves_like 'creating new claims' do
include_context 'with claims records for User'
end
it_behaves_like 'deleting existing claims' do
include_context 'with claims records for User'
end
it_behaves_like 'updating existing claims' do
let(:transform_attributes) { { username: subject.username.reverse } }
include_context 'with claims records for User'
end
end
까다로운 부분은 user 모델에 email을 정의하지 않았는데도 email을 정의해야 한다는
점입니다. 클레임 속성이 있는 연관 관계도 함께 클레임되기 때문이며, 이메일이
그런 경우입니다.
그래서 claims_records를 재정의합니다. 기본적으로는 주체 자체의 클레임만 만들지만,
여기서는 이메일도 함께 클레임해야 합니다.
공유 예시는 세 가지입니다:
- creating new claims
- deleting existing claims
- updating existing claims
세 가지 모두 claims_records 재정의가 필요합니다. updating existing claims에서는
업데이트할 클레임을 위해 transform_attributes도 정의해야 합니다. 여기서는
username을 뒤집고, 테스트는 이전 클레임이 파기되고 새 클레임이 생성되는지
확인합니다.
이 레코드가 절대 업데이트되지 않는다면 updating existing claims
테스트는 생략할 수 있습니다.
피처 플래그 동작 테스트#
새 속성을 임시 feature_flag: 뒤에서 도입한다면, 클레임이 이를 따르는지
테스트합니다. cells_claims_your_new_attribute를 직접 만든 플래그로
바꿉니다:
RSpec.describe 'Claim for YourModel', feature_category: :cell do
context 'when cells_claims_your_new_attribute feature flag is enabled' do
it_behaves_like 'creating new claims'
it_behaves_like 'deleting existing claims'
end
context 'when cells_claims_your_new_attribute feature flag is disabled' do
before do
stub_feature_flags(cells_claims_your_new_attribute: false)
end
it_behaves_like 'not creating claims'
it_behaves_like 'not deleting claims'
end
end
플래그를 제거하면 비활성화 상태에 대한 이 예시들은 더 이상 적용되지 않습니다.
토폴로지 서비스#
우리가 사용하는 유형은 토폴로지 서비스에 정의되어 있습니다. 클레임 유형은
proto/types/v1/claim.proto에 있고,
주체 유형과 소스 유형은
proto/claims/v1/messages.proto에 있습니다.
새 클레임마다 다음 위치에 새 유형을 추가해야 합니다:
oneof claim- ClaimType
- Subject::Type (이미 존재할 수 있습니다)
- Source::Type
새 유형을 Rails에서 사용할 수 있게 만드는 워크플로는 다음과 같습니다:
- 토폴로지 서비스에 머지 리퀘스트를 만들어
proto/types/v1/claim.proto에 새 클레임 유형을 추가합니다(필요하면proto/claims/v1/messages.proto에 주체 유형이나 소스 유형도 추가합니다) - 잘못된 사용을 막기 위해 validation.go 파일에 새 클레임 유형의 검증 규칙을 추가합니다(검증 문서 참고)
- 검토와 머지가 끝난 후에는 GitLab에 머지 리퀘스트를 만들어
머지 리퀘스트 브랜치에서
scripts/update-topology-service-gem.sh를 실행해 토폴로지 서비스 클라이언트를 업데이트합니다 - 검토와 머지가 끝나면 GitLab 기본 브랜치에서 사용할 수 있습니다
HTTP 라우터#
HTTP 라우터는 같은 클레임 유형을 사용하는 또 다른 소비자입니다. 토폴로지 서비스가 반환한 클레임을 매칭해 요청을 라우팅합니다. Rails가 gem을 사용하는 것과 같은 방식으로 생성된 TypeScript 클라이언트를 사용하므로, 새 클레임 유형은 벤더링된 클라이언트를 다시 동기화한 후에야 라우터에서 사용할 수 있습니다:
- HTTP 라우터에 머지 리퀘스트를 만들어 머지 리퀘스트 브랜치에서
scripts/update-topology-service-client.sh를 실행해 벤더링된 토폴로지 서비스 클라이언트를 업데이트합니다 - 검토와 머지가 끝나면 라우터의 기본 브랜치에서 사용할 수 있습니다
검증 및 백필#
검증 서비스(Cells::Claims::VerificationService)는 로컬 데이터베이스 레코드를
토폴로지 서비스에 저장된 클레임과 조정합니다. 목적은
두 가지입니다:
- 백필: 모델에 처음 활성화될 때 서비스는 토폴로지 서비스에 대응하는 클레임이 없는 모든 로컬 레코드를 스캔해 클레임을 생성합니다.
- 지속적 일관성: 백필 후에도 서비스는 드리프트를 감지하고 수정하기 위해 크론 스케줄로 계속 실행됩니다.
서비스는 cells_claims_enabled_for_attribute?가 true인 속성만 조정합니다.
모델의 모든 속성이 비활성화되어 있으면 서비스는 경고를 기록하고 그 모델을
건너뜁니다. 나중에 비활성화된 속성에 대해 이미 기록된 클레임은 그대로
남습니다. 가져오지도, 파기하지도 않습니다.
검증 작동 방식#
ScheduleClaimsVerificationWorker 크론 job이 클레임 가능한 모델마다
ClaimsVerificationWorker를 10분 간격으로 나눠
스케줄링합니다.
워커는 실행할 때마다 다음을 수행합니다:
- 같은 모델에 대해 동시 실행이 일어나지 않도록 배타적 리스(TTL 5분)를 획득합니다.
- 기본 키 순서로 1,000건 단위 배치로 로컬 레코드를 스캔합니다.
- 각 배치 범위에 대응하는 클레임을 토폴로지 서비스에서 가져옵니다.
- 로컬 레코드를 토폴로지 서비스 클레임과 비교합니다:
- 일치하는 클레임이 없는 로컬 레코드: 클레임을 생성합니다.
- 일치하는 로컬 레코드가 없는 토폴로지 서비스 클레임: 클레임을 파기합니다.
- 클레임 메타데이터가 다른 레코드: 이전 클레임을 파기하고 올바른 클레임을 생성합니다.
- 진행 중인 저장과 충돌하지 않도록 최근 1시간 안에 업데이트된 레코드는 건너뜁니다.
- 배치마다 진행 상황(마지막으로 처리한 ID)을 Redis에 저장합니다. 워커가 시간(4.5분 제한)을 초과하면 멈춘 지점부터 이어서 진행하도록 자신을 다시 스케줄링합니다.
검증 워커 활성화#
검증 워커를 활성화하는 별도의 단계는 없습니다.
Cells::ClaimsVerificationWorker#enabled?가 모델에 대해 검증을 실행할지
결정합니다:
def enabled?(model)
return false unless Cells::Claimable.models_with_claims.include?(model)
model.cells_claims_attributes.any? { |attribute, _| model.cells_claims_enabled_for_attribute?(attribute) }
end
모델이 Cells::Claimable.models_with_claims에 등록되어 있고(cells_claims_attribute를
선언하면 등록됩니다) cells_claims_enabled_for_attribute?가 판단하기에 속성 중
하나 이상이 현재 클레임 가능하면 그 모델에 대해 검증이 실행됩니다. 한 번 실행되는
동안 서비스는 활성화된 속성만 조정하므로, 아직 feature_flag: 뒤에 있는 속성은
모델의 나머지 부분을 붙잡지 않고
건너뜁니다.
속성에 임시 feature_flag:가 없는 모델이라면 Gitlab.config.cell.enabled가
true가 되는 즉시 추가 구성 없이 검증이
실행됩니다.
유효성 검사#
클레임 속성을 정의한 후에는 레코드를 만들거나 업데이트하거나 삭제할 때 Rails가
자동으로 속성을 클레임합니다. 이 클레임은 토폴로지 서비스로 전송되고, 토폴로지
서비스는 이를 자체 데이터베이스에 저장합니다. GDK에서 토폴로지 서비스는 기본적으로
로컬 PostgreSQL 데이터베이스를 사용합니다. gdk psql -d topology_service를 실행해
psql 콘솔에 접속할 수 있습니다. 예를 들어 다음 명령으로 모든 클레임을
나열할 수 있습니다:
gdk psql -d topology_service -c "SELECT * FROM claims;"
웹 UI로 레코드를 몇 개 만들고 업데이트하고 삭제해 보면서, 이 명령을 가끔 실행해 예상대로 동작하는지 확인할 수 있습니다.
문제 해결#
클레임이 생성되지 않음#
-
셀 구성을 확인합니다:
Gitlab.config.cell.enabled -
속성이 클레임 가능한지 확인합니다:
# Replace User and :id with your model and attribute User.cells_claims_enabled_for_attribute?(:id)Gitlab.config.cell.enabled가true가 아니면false를 반환하고, 속성에 임시feature_flag:가 아직 있다면 그 플래그도 활성화되어 있지 않으면false를 반환합니다. -
토폴로지 서비스가 실행 중인지 확인합니다:
gdk status gitlab-topology-service -
토폴로지 서비스 로그를 확인합니다:
gdk tail gitlab-topology-service
백필이 진행되지 않음#
-
모델에 대해 검증이 활성화되어 있는지 확인합니다:
# Replace User with your model User.cells_claims_attributes.each do |attribute, _| puts "#{attribute}: #{User.cells_claims_enabled_for_attribute?(attribute)}" end속성 중 하나 이상이
true를 출력할 때만 검증이 실행됩니다. 임시feature_flag:뒤에 묶인 속성이 하나만 있어도 모델 전체의 검증이 멈춥니다. -
배치 진행 상황을 보려면 검증 워커 로그를 확인합니다.
created와destroyed개수가 있는Cells::Claims::VerificationService batch processed로그 항목을 찾습니다. -
진행 상태를 Redis에서 확인합니다. 워커는 마지막으로 처리한 ID를 저장합니다. 워커가 계속 ID 0부터 다시 시작한다면 Redis 키가 있는지 확인합니다:
Gitlab::Redis::SharedState.with do |redis| redis.get("cells:claims:verification_service:last_processed_id:User") # Replace User with your model name end