# アーキテクチャ設計書

## 概要

本ドキュメントは、GitLab Community Edition (CE) / Enterprise Edition (EE) のアーキテクチャ設計書である。GitLabは、DevOpsプラットフォームとしてソースコード管理、CI/CD、イシュー追跡、セキュリティ分析等の機能を統合的に提供するWebアプリケーションである。

本システムは Ruby on Rails を基盤とし、モノリシックアーキテクチャを採用しつつ、ドメイン駆動設計（DDD）の概念を取り入れた境界づけられたコンテキスト（Bounded Contexts）によるモジュール分割を実現している。

## システム全体構成

### アーキテクチャ概要図

[アーキテクチャ構成図.md](./アーキテクチャ構成図.md) を参照

### システム境界と外部連携

| 外部システム | 連携方式 | 用途 |
| --- | --- | --- |
| PostgreSQL | ActiveRecord / pg gem | プライマリデータストア（main, ci, geo, embedding） |
| Redis | redis gem / Redis Cluster | キャッシュ、セッション、キュー、Feature Flag |
| ClickHouse | click_house-client gem | 分析データストア |
| Elasticsearch | elasticsearch-model gem | 全文検索 |
| Gitaly | gRPC | Git リポジトリ操作 |
| GitLab Workhorse | HTTP Reverse Proxy | 静的ファイル配信、Git HTTP/SSH プロキシ |
| GitLab Shell | SSH | Git SSH アクセス |
| GitLab Pages | HTTP | 静的サイトホスティング |
| GitLab Runner | HTTP API | CI/CD ジョブ実行 |
| Sidekiq | Redis | バックグラウンドジョブ処理 |
| Object Storage (S3/GCS/Azure) | fog-* gems | ファイルストレージ |
| LDAP/SAML/OAuth | omniauth-* gems | 外部認証 |
| Jira/Slack/Microsoft Teams | 各種 SDK | 外部サービス連携 |
| Kubernetes | kubeclient gem | クラスタ管理 |
| Prometheus | prometheus-client-mmap gem | メトリクス収集 |
| Sentry | sentry-* gems | エラートラッキング |
| OpenTelemetry | opentelemetry-* gems | 分散トレーシング |

## レイヤー構成

### アーキテクチャスタイル

GitLabは **レイヤードアーキテクチャ** と **ドメイン駆動設計（DDD）** を組み合わせた設計を採用している。

- **レイヤードアーキテクチャ**: Rails の MVC パターンを基盤とし、Service層、Policy層を追加
- **DDD**: Bounded Contexts による明確なドメイン境界の定義（`config/bounded_contexts.yml`）
- **モノリス + 分散**: 単一アプリケーションとして動作しつつ、Workhorse/Gitaly/Shell等の補助サービスと連携

### レイヤー定義

| レイヤー | 責務 | 主なコンポーネント |
| --- | --- | --- |
| Presentation | ユーザーインターフェース、API エンドポイント | Controllers, Views, GraphQL, REST API (Grape) |
| Application | ユースケースの実装、ワークフロー調整 | Services, Workers, Finders, Presenters |
| Domain | ビジネスルール、ドメインモデル | Models, Policies, Validators |
| Infrastructure | 外部サービス連携、永続化 | Uploaders, lib/gitlab/*, Mailers |

### レイヤー間の依存関係ルール

```
Presentation → Application → Domain → Infrastructure
     ↓              ↓            ↓
   Views        Services      Models
 Controllers    Workers     Policies
  GraphQL       Finders    Validators
  REST API    Presenters
```

- **許可される参照**:
  - 上位レイヤーから下位レイヤーへの参照
  - 同一レイヤー内の参照
- **禁止される参照**:
  - 下位レイヤーから上位レイヤーへの参照
  - Controllers から直接 Models を更新（Services を経由）

## モジュール構成

### ドメイン分割

GitLab は `config/bounded_contexts.yml` で定義された境界づけられたコンテキストにより構成される。

| ドメイン | 責務 | 関連モジュール |
| --- | --- | --- |
| Ci | CI/CD パイプライン | `app/models/ci/`, `app/services/ci/`, `app/workers/ci/` |
| Ai | AI機能（Duo Chat, Code Suggestions） | `app/models/ai/`, `lib/gitlab/llm/` |
| Analytics | 分析・レポート | `app/models/analytics/`, `lib/gitlab/analytics/` |
| AntiAbuse | スパム・不正検出 | `app/models/anti_abuse/`, `lib/spam/` |
| Authn | 認証 | `app/models/authn/`, `lib/gitlab/auth/` |
| Authz | 認可 | `app/policies/`, `lib/authz/` |
| AuditEvents | 監査ログ | `app/models/audit_events/`, `lib/audit_events/` |
| ContainerRegistry | コンテナレジストリ | `lib/container_registry/` |
| Clusters | Kubernetes クラスタ | `app/models/clusters/`, `lib/gitlab/kubernetes/` |
| Environments | デプロイ環境管理 | `app/models/environment.rb`, `app/services/environments/` |
| Geo | Geo レプリケーション | EE: `ee/app/models/geo/` |
| Groups | グループ管理 | `app/models/group.rb`, `app/services/groups/` |
| Issues | イシュー管理 | `app/models/issue.rb`, `app/services/issues/` |
| MergeRequests | マージリクエスト | `app/models/merge_request.rb`, `app/services/merge_requests/` |
| Packages | パッケージレジストリ | `app/models/packages/`, `lib/packages/` |
| Projects | プロジェクト管理 | `app/models/project.rb`, `app/services/projects/` |
| Users | ユーザー管理 | `app/models/user.rb`, `app/services/users/` |

### パッケージ構造

```
gitlabhq/
├── app/
│   ├── assets/           # フロントエンドアセット
│   ├── channels/         # ActionCable チャネル
│   ├── components/       # ViewComponent
│   ├── controllers/      # Rails コントローラー
│   │   ├── admin/
│   │   ├── concerns/
│   │   ├── groups/
│   │   └── projects/
│   ├── finders/          # クエリオブジェクト
│   ├── graphql/          # GraphQL スキーマ
│   │   ├── mutations/
│   │   ├── resolvers/
│   │   └── types/
│   ├── helpers/          # View ヘルパー
│   ├── mailers/          # メール送信
│   ├── models/           # ActiveRecord モデル
│   │   ├── ci/
│   │   ├── concerns/
│   │   └── {domain}/
│   ├── policies/         # 認可ポリシー (DeclarativePolicy)
│   ├── presenters/       # Presenter パターン
│   ├── serializers/      # JSON シリアライゼーション
│   ├── services/         # ビジネスロジック
│   │   ├── ci/
│   │   └── {domain}/
│   ├── uploaders/        # ファイルアップロード (CarrierWave)
│   ├── validators/       # カスタムバリデーション
│   ├── views/            # ERB/HAML テンプレート
│   └── workers/          # Sidekiq ワーカー
│       ├── ci/
│       └── {domain}/
├── config/
│   ├── initializers/     # Rails 初期化
│   ├── routes/           # ルーティング定義
│   └── bounded_contexts.yml  # DDD ドメイン定義
├── db/
│   ├── migrate/          # マイグレーション
│   ├── post_migrate/     # デプロイ後マイグレーション
│   └── structure.sql     # スキーマ定義
├── ee/                   # Enterprise Edition 拡張
│   ├── app/
│   └── lib/
├── lib/
│   ├── api/              # Grape REST API
│   └── gitlab/           # GitLab コアライブラリ
├── gems/                 # 内部 gem
└── workhorse/            # Go 製リバースプロキシ
```

### コンポーネント依存関係

```
Controllers/GraphQL → Services → Models → Database
        ↓                ↓         ↓
     Finders          Workers   Policies
        ↓                ↓
    Presenters      Mailers
```

## ミドルウェア構成

### データベース

| 種類 | ミドルウェア | バージョン | 用途 |
| --- | --- | --- | --- |
| RDB | PostgreSQL | 14+ | プライマリデータストア |
| RDB (分離) | PostgreSQL | 14+ | CI データ (ci)、Geo データ (geo)、埋め込みデータ (embedding) |
| OLAP | ClickHouse | - | 分析・集計クエリ |

**データベース構成の特徴**:
- **Decomposed Database**: main, ci, geo, embedding の4つの論理データベースに分離
- **Load Balancing**: 読み取りレプリカへの自動分散
- **Loose Foreign Keys**: 遅延外部キー制約 (`config/gitlab_loose_foreign_keys.yml`)

### キャッシュ

| ミドルウェア | バージョン | 用途 | TTL |
| --- | --- | --- | --- |
| Redis | 6+ | アプリケーションキャッシュ | 可変 |
| Redis | 6+ | Repository Cache | 可変 |
| Redis | 6+ | Session Store | セッション有効期限 |

### メッセージキュー

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| Redis + Sidekiq | Redis 6+, Sidekiq 7 | 非同期ジョブ処理 |
| Redis Pub/Sub | Redis 6+ | ActionCable リアルタイム通信 |

**Sidekiq キュー構成** (`config/sidekiq_queues.yml`):
- 重み付けキュー（1: 低優先度 〜 5: 最高優先度）
- 機能別キュー（ci_*, analytics_*, audit_events_* など）

### 検索エンジン

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| Elasticsearch | 7.x | 全文検索（コード、イシュー、MR） |
| Zoekt | - | 高速コード検索 |

### その他ミドルウェア

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| Puma | 7.x | Web アプリケーションサーバー |
| GitLab Workhorse | Go | リバースプロキシ、ファイル処理 |
| Gitaly | Go/gRPC | Git リポジトリ操作 |
| GitLab Shell | Go | Git SSH アクセス |
| GitLab Pages | Go | 静的サイトホスティング |
| Mattermost | - | チャット連携（オプション） |

## データフロー

### リクエスト処理の流れ

**Web リクエスト（同期）**:

1. クライアントが HTTPS リクエストを送信
2. ロードバランサー/Nginx が GitLab Workhorse にルーティング
3. Workhorse が静的ファイルを直接処理、動的リクエストを Puma に転送
4. Puma が Rails アプリケーションを実行
5. Rack ミドルウェアスタック処理:
   - `Gitlab::Middleware::BasicHealthCheck`
   - `Gitlab::Middleware::ReadOnly`
   - `Gitlab::Middleware::CompressedJson`
   - `Gitlab::Middleware::PathTraversalCheck`
   - `Rack::Attack` (レート制限)
6. Rails Router がルーティング
7. Controller がリクエストを処理
8. Service が ビジネスロジックを実行
9. Model が データベース操作を実行
10. View/Serializer がレスポンスを生成
11. レスポンスをクライアントに返却

**API リクエスト**:

1. `/api/v4/*` へのリクエスト
2. Grape API エンドポイントがルーティング
3. APIGuard による認証・認可
4. Service 層でビジネスロジック実行
5. Entity/Serializer で JSON レスポンス生成

### 非同期処理の流れ

**Sidekiq ジョブ**:

1. Service/Controller がジョブをエンキュー
2. Redis キューにジョブ情報を格納
3. Sidekiq プロセスがキューからジョブを取得
4. Worker クラスの `perform` メソッドを実行
5. 必要に応じて Service 層を呼び出し
6. 完了後、ジョブ結果を記録

**ActionCable (WebSocket)**:

1. クライアントが WebSocket 接続を確立
2. `ApplicationCable::Connection` で認証
3. チャネルをサブスクライブ
4. サーバーからリアルタイムイベントをブロードキャスト
5. クライアントがイベントを受信

### データ永続化の流れ

**Create/Update 操作**:

1. Controller がパラメータを受信
2. Service が `params` を検証
3. Model で ActiveRecord バリデーション実行
4. トランザクション内でデータベースに保存
5. 関連する非同期ジョブをエンキュー（インデックス更新、キャッシュ削除など）
6. Webhook/Integration 通知を送信

**ファイルアップロード**:

1. Workhorse がファイルを一時ディレクトリに受信
2. Controller がアップロードを処理
3. CarrierWave Uploader がファイルを処理
4. Object Storage (S3/GCS) または ローカルストレージに保存
5. データベースにメタデータを記録

## 横断的関心事

### 認証・認可

| 方式 | 実装箇所 | 対象 |
| --- | --- | --- |
| Session 認証 | Devise gem | Web UI |
| Personal Access Token | APIGuard | API |
| OAuth 2.0 | Doorkeeper gem | 外部アプリケーション |
| SAML/LDAP/OmniAuth | omniauth-* gems | SSO |
| JWT | jwt gem | サービス間認証 |
| Kerberos | gssapi gem | エンタープライズ SSO |
| 2FA (TOTP/WebAuthn) | devise-two-factor, webauthn gems | 追加認証 |

**認可システム (DeclarativePolicy)**:
- `app/policies/` に Policy クラスを定義
- `BasePolicy` を継承し、条件と権限を宣言的に記述
- `Ability.allowed?(user, :action, subject)` で権限チェック

### ロギング・監査

| 種類 | 実装方式 | 保存先 |
| --- | --- | --- |
| アプリケーションログ | Rails Logger, Lograge | `log/*.log`, JSON 形式 |
| 監査ログ | AuditEventService | PostgreSQL (`audit_events` テーブル) |
| アクセスログ | Nginx/Workhorse | ファイル/Syslog |
| API ログ | Grape Logging | `log/api_json.log` |
| Git 操作ログ | Gitaly | ファイル |

### エラーハンドリング

| エラー種別 | ハンドリング方式 | レスポンス |
| --- | --- | --- |
| バリデーションエラー | ActiveRecord::RecordInvalid | 422 Unprocessable Entity |
| 認証エラー | Gitlab::Auth::AuthenticationError | 401 Unauthorized |
| 認可エラー | Gitlab::Access::AccessDeniedError | 403 Forbidden |
| リソース未発見 | ActiveRecord::RecordNotFound | 404 Not Found |
| レート制限 | Rack::Attack | 429 Too Many Requests |
| 内部エラー | StandardError | 500 Internal Server Error |
| タイムアウト | Rack::Timeout | 503 Service Unavailable |

**例外追跡**: Sentry (`sentry-ruby`, `sentry-rails`, `sentry-sidekiq`)

### トランザクション管理

| 範囲 | 管理方式 | 分離レベル |
| --- | --- | --- |
| 単一 DB 操作 | ActiveRecord::Base.transaction | READ COMMITTED (PostgreSQL デフォルト) |
| 複数モデル操作 | Service 層でのトランザクション管理 | READ COMMITTED |
| バックグラウンドジョブ | 各ジョブ内でトランザクション管理 | READ COMMITTED |

**クロスデータベーストランザクション**:
- `CrossDatabaseModification` concern で制御
- `ApplicationRecord.transaction` でラップ

## 設計原則・コーディング規約

### 適用している設計原則

| 原則 | 適用箇所 | 実装例 |
| --- | --- | --- |
| Single Responsibility | Service クラス | `Issues::CreateService`, `MergeRequests::MergeService` |
| Open/Closed | Concerns, Module prepend | `Noteable` concern, `prepend_mod_with` |
| Dependency Injection | Service 初期化 | `BaseService.new(project, user, params)` |
| Repository Pattern | Finder クラス | `IssuesFinder`, `MergeRequestsFinder` |
| Service Object Pattern | Services | `app/services/` |
| Policy Object Pattern | Policies | `app/policies/` (DeclarativePolicy) |
| Presenter Pattern | Presenters | `app/presenters/` |
| Decorator Pattern | SimpleDelegator | 各種 Decorator クラス |

### コーディング規約

**Ruby/Rails**:
- RuboCop による静的解析 (`.rubocop.yml`)
- Rails 7.2 スタイルガイドに準拠
- Feature Category によるコード分類

**JavaScript/Vue**:
- ESLint による静的解析 (`eslint.config.mjs`)
- Vue 3 移行中
- Vite によるフロントエンドビルド

**データベース**:
- マイグレーションは `db/migrate/` と `db/post_migrate/` に分離
- Large Table への変更は Background Migration を使用
- Foreign Key は Loose Foreign Key で管理

## 備考

- **EE (Enterprise Edition)**: `ee/` ディレクトリに拡張機能を配置。`prepend_mod_with` でモジュールを動的にロード
- **JH (JiHu Edition)**: 中国向けエディション。`jh/` ディレクトリに配置
- **Feature Flags**: `lib/feature/` および `config/feature_flags/` で管理
- **Bounded Contexts**: `config/bounded_contexts.yml` で定義。新規ドメインはここに登録
- **OpenTelemetry**: 分散トレーシング対応（Rails, Sidekiq, Redis, PostgreSQL 等を計装）
