Cells ADR 014: Protocell ではクラスター全体の同期を行わない

コンテキスト

一部の機能が動作するために、特定のテーブルのデータをすべての Cell に何らかの方法で同期させる必要があります。 たとえば、planssubscription_add_onswork_item_types テーブルはすべての Cell で同一である必要があります。

決定事項

  1. Protocell ではアプリケーション層でのクラスター全体の同期は行いません。
  2. plans のような静的データテーブルは同期を必要とせず、アプリケーションコードにハードコードすることで常に一貫性を保つよう変換します。 良い例として VisibilityLevel があります。
  3. application_settings のような Cell 設定テーブルは独立して設定できます。 Terraform のような外部のシングルソースオブトゥルースが、Cell の各リングに対して目標値を伝播します。 これをサポートするために、各 Cell 設定テーブルに内部 API が必要です。

長所

  1. フォロワー Cell での書き込みを防ぐ作業、同期サービスのセットアップ、各静的データ型テーブルを更新する API の作成が不要になります。
  2. 整合性リスクが軽減されます。何らかの理由で同期が失敗した場合、アプリケーションが不正なデータを生成し始める可能性があります。たとえば、不正な plan_id 値を持つ gitlab_subscriptions が作成される可能性があります。plan_id カラムをグローバルに一意な参照に置き換えることで、整合性リスクを排除できます。
  3. Cell / データベース間でリーダー/フォロワーのトポロジーを作成したり、クラスターをクォーラム状態に保つ必要がなくなります。
  4. 各 Cell は完全に独立しており、互いに依存しません。

短所

  1. Cell 設定については、設定のドリフトが短時間発生することを許容する必要があります。
  2. 静的データテーブルについては、これらのデータに依存するダウンストリームサービスが存在する可能性があります。そのため、ダウンストリームサービスを新しいデータを使用するように更新する前に、すべてのリングにアプリケーションの変更が完全に伝播するのを待つ必要があります。

クラスター全体のテーブルの分析

クラスター全体のテーブルの分析が 2025-01-13 に実施されました。 結果として、4 つの異なるタイプに分類できます。

  1. 静的データテーブル: すべての Cell で一定 / 同一のテーブル。
  2. Cell 設定テーブル: すべての Cell に影響する設定をホストするテーブル。
  3. Organization / Cell テーブル: gitlab_main_cell として分類した方が適切なテーブル。
  4. ユーザーテーブル: ユーザーに関連するテーブル。組織間アクセスが必要な場合に同期できます。

このセクションでは、全テーブルとその各タイプの完全なリストを示します。

Cell 設定テーブル

application_settings

関連 Issue: issue 505685 を参照してください。

要約すると、外部のシングルソースオブトゥルースを使用して各 Cell の Application Settings を設定します。

移行ステップとして、まずレガシー Cell から現在の値を取得し、外部のシングルソースオブトゥルースにコピーします。 外部のシングルソースオブトゥルースはその後、各リングに値を伝播します。

設定を作成する際、開発者はその設定のデフォルト値が任意の Cell で正しく機能することを確認する必要があります。 これは特に、新しい設定が外部のシングルソースオブトゥルースによってまだ設定されていない場合に重要です。

broadcast_messages

application_settings と同様に、ブロードキャストメッセージは外部のシングルソースオブトゥルースによって設定されます。

broadcast_messages.id カラムは user_broadcast_message_dismissals テーブルから参照されており、ユーザーがブロードキャストメッセージを非表示にしたかどうかを記録するために使用されます。 整合性を向上させるため、broadcast_messages.id の値は API 経由で直接設定できます。

静的データテーブル

参照テーブルをアプリケーションコードに変換します。

plans

plans テーブルは idnametitle カラムを持つシンプルなテーブルです。 また、name カラムに一意インデックスがあります。 plan_limitsgitlab_subscriptions という 2 つの参照テーブルがあります。

問題は、すべての Cell で nameid が一致しない不整合データが各 Cell で生成される可能性があることです。

解決策は単純です。 各プランのグローバルに一意な参照が必要です。 以下のような enum を使用できます。

  enum :name_uid,
    default: 1,
    free: 2,
    bronze: 3,
    silver: 4,
    premium: 5,
    gold: 6,
    ultimate: 7,
    ultimate_trial: 8,
    ultimate_trial_paid_customer: 9,
    premium_trial: 10,
    opensource: 11

そして id カラムを削除します。 その後、すべての参照テーブルで新しい name_uid カラムを使用します。

別の代替案として、plans テーブルを完全に削除し、ハードコードされたプランのリストを使用することもできます。

subscription_add_ons

subscription_add_ons テーブルも idnamedescription カラムを持つシンプルなテーブルです。 こちらも name カラムに一意インデックスがあります。

plans と同様に、name_uid カラム戦略を採用するか、テーブルを完全に削除することができます。

work_item_types

work_item_types テーブルは一定の ID セットを持つよう再編成されました。

特に理由がなければ、ワークアイテムタイプのハードコードされたリストを使用するようさらに変換すべきです。

abuse_report_labels

abuse_report_labels テーブルにはいくつかのカラムがあります。

  • id
  • cached_markdown_version
  • title
  • color
  • description
  • description_html

title カラムに一意インデックスがあります。

このテーブルを Cell 間で同期させる概念的な必要性はありません。 abuse report は独立したレコードです。 abuse_report_labels は abuse report に添付されるラベルです。

問題が生じるのは、abuse_report_labels が Cell 間で移動される場合のみで、 title カラムの一意性違反が発生します。 最も簡単な対処は一意性制約を削除し、重複を許可することです。

または、重複を排除するために (Cell 2) をタイトルに追加することもできます。

programming_languages

programming_languages テーブルは idnamecolor カラムを持つテーブルです。 このテーブルは name カラムに一意インデックスがあります。

plans と同様に、name_uid カラム戦略を採用して id カラムを削除できます。 データは Gitaly(linguist)から来るため、安定した方法で name を整数にマッピングする必要があります。 このマッピングは GitLab Ruby モノリスまたは Gitaly に保存できます。

https://gitlab.com/gitlab-org/gitlab/-/blob/816e3ce6770ad96e3d5b0d7dae4925d63efa02fc/vendor/languages.yml には言語の完全なリストがあります。 language_id フィールドを使用できる可能性があります。

すべての参照テーブルは id の代わりに name_uid カラムを参照するよう切り替えます。

security_training_providers

security_training_providers テーブルにはいくつかのカラムがあります。

  • id
  • name
  • description
  • url
  • logo_url

name に一意インデックスがあります。

plans と同様に、name_uid カラム戦略を採用して id カラムを削除できます。 すべての参照テーブルは name_uid カラムを参照するよう切り替えます。

ただし、行数が 3 つのみのため、テーブルを完全に削除してアプリケーションコード内で定義することもできます。

SECUREFLAG_DATA = {
  name_uid: 1,
  name: 'SecureFlag',
  description: "Get remediation advice with example code and recommended hands-on labs in a fully
                interactive virtualised environment.",
  url: "https://knowledge-base-api.secureflag.com/gitlab"
}.freeze

Organization / Cell テーブル

これらのテーブルは gitlab_main_clusterwide として誤って分類されている可能性が高く、 代わりに gitlab_main_cell として分類し直す必要があります。

ユーザーテーブル

これらのテーブルは users テーブルに関連しています。

Protocell ではユーザーは 1 つの Cell にのみ存在できるため、現時点ではユーザー関連データを同期させる必要はありません。

テーブル一覧

以下はすべてのクラスター全体テーブルとそのタイプの一覧です。

テーブル静的データテーブルCell 設定テーブルOrganization/Cell テーブルユーザーテーブル新規 GDK に行あり
ai_feature_settingsYMaybe ?N
ai_settingsYN
appearancesYN
application_settingsYY
cloud_connector_accessYN
plan_limitsYN
service_access_tokensYN
ai_self_hosted_modelsYMaybe ?N
application_setting_termsYN
broadcast_messagesYMaybe ?N
licensesYN
plansYY
subscription_add_onsYY
work_item_hierarchy_restrictionsYY
work_item_related_link_restrictionsYY
work_item_typesYY
work_item_widget_definitionsYY
abuse_eventsYN
abuse_report_assigneesYN
abuse_report_eventsYN
abuse_report_label_linksYY
abuse_report_labelsYY
abuse_report_notesYN
abuse_report_user_mentionsYN
abuse_reportsYY
abuse_trust_scoresYN
ai_testing_terms_acceptancesMaybeN
atlassian_identitiesYN
audit_events_instance_amazon_s3_configurationsMaybeN
audit_events_instance_external_audit_event_destinationsMaybeN
audit_events_instance_external_streaming_destinationsMaybeN
audit_events_instance_google_cloud_logging_configurationsMaybeN
audit_events_instance_streaming_event_type_filtersMaybeN
audit_events_streaming_instance_event_type_filtersMaybeN
authentication_eventsYY
aws_rolesYN
banned_usersYN
deploy_tokensYN
early_access_program_tracking_eventsYN
emailsYY
ghost_user_migrationsYN
gpg_key_subkeysYN
gpg_keysYN
identitiesYN
instance_audit_eventsMaybeN
instance_audit_events_streaming_headersMaybeN
instance_integrationsMaybeN
keysYY
oauth_applicationsMaybeN
programming_languagesYMaybeY
redirect_routesYN
routesYY
saved_repliesYN
security_training_providersYMaybeY
smartcard_identitiesYN
spam_logsYY
term_agreementsYN
user_agent_detailsYN
user_audit_eventsYY
user_broadcast_message_dismissalsYN
user_calloutsYN
user_credit_card_validationsYN
user_custom_attributesYN
user_detailsYY
user_follow_usersYN
user_highest_rolesYN
user_member_rolesYN
user_permission_export_uploadsYN
user_phone_number_validationsYN
user_preferencesYY
user_statusesYN
user_synced_attributes_metadataYN
usersYY
users_statisticsYN
vs_code_settingsYN
webauthn_registrationsYN