gitlab-org/gitlab
Gitaly client
Every Git read/write goes through Gitaly. This page covers the client side that lives in this repo; for Gitaly's internals see gitlab-org/gitaly.
Purpose
Gitaly is a gRPC service that owns Git repository storage. The Rails monolith does not touch .git directories directly; instead it makes typed gRPC calls.
Source
| Concern | Location |
|---|---|
| Top-level facade | lib/gitaly_client.rb (~32K LoC) |
| Per-RPC service classes | lib/gitaly_client/ |
| Repository wrapper | lib/gitlab/git/repository.rb |
| Wiki wrapper | lib/gitlab/git/wiki.rb |
| Generated proto bindings | lib/gitaly/ (and via gitaly gem) |
| Workhorse-side client | workhorse/internal/gitaly/ |
Patterns
The Rails code rarely calls Gitaly directly; it calls Gitlab::Git::*:
project.repository.commit('main') # uses Gitaly
project.repository.commits('main', limit: 20)
project.repository.tree('main')
project.repository.find_by_path('main', 'README.md')Gitlab::Git::Repository wraps Gitlab::GitalyClient::*Service classes. Each RPC method has a Ruby helper.
Token and routing
Every Gitaly call requires:
storage_name— which Gitaly node ("default", "secondary", etc.).relative_path— the on-disk path inside that storage.gl_repository— encoded identifier ("project-123", "wiki-123", "personal_snippet-7").gl_project_path— for logging.auth_token— a JWT signed with the shared secret inconfig/gitlab.yml.
Gitlab::GitalyClient builds the metadata header and reuses gRPC connections per storage.
Connection management
- A single gRPC client per storage process-wide.
- Connections are reused across requests; each request gets its own RPC.
lib/gitlab/gitaly_client/with_feature_flag_actors.rbpropagates feature-flag context to Gitaly.
Concurrency and timeouts
Gitlab::GitalyClient enforces per-call deadlines:
- Fast (~3 s) — metadata, single-commit lookups.
- Medium — commit list, blame.
- Slow — clone, push, archive (no deadline).
SafeRequestStore tracks per-request Gitaly call counts; the perf bar surfaces them, and the N+1 detector flags excessive calls.
Common services used by the Rails app
| Service class | RPCs |
|---|---|
CommitService |
commit lookup, commit message, parents |
RefService |
branches, tags, default branch |
BlobService |
file content |
RepositoryService |
clone, push, archive |
OperationService |
merge, cherry-pick, revert |
RemoteService |
mirror push/fetch |
DiffService |
structured diffs |
ConflictsService |
merge conflict resolution |
WikiService |
wiki repo operations |
ObjectPoolService |
shared object pools (forks) |
Workhorse and Gitaly
Workhorse also talks to Gitaly directly for git-over-HTTP transfers:
sequenceDiagram
Browser->>Workhorse: git fetch
Workhorse->>Rails: /authorize
Rails-->>Workhorse: gitaly addr + token + repo
Workhorse->>Gitaly: SmartHTTP service
Gitaly-->>Workhorse: streamed packfile
Workhorse-->>Browser: streamed packfileThis avoids streaming the entire packfile through Puma.
Tests
- Most code paths use real Gitaly running under GDK.
- Spec helpers in
spec/support/helpers/gitaly_helpers.rb. - For unit tests,
stub_gitaly_client_calland friends provide cheap stubs.
Failure modes
| Symptom | Cause |
|---|---|
Gitlab::Git::CommandError |
Underlying git command failed (often legitimate user error) |
GRPC::Unavailable |
Gitaly process down or network glitch |
GRPC::DeadlineExceeded |
Operation slower than the per-call deadline |
Gitlab::Git::ResourceExhausted |
Gitaly's concurrency limit hit |
Gitlab::GitalyClient::TooManyInvocationsError |
N+1 detector fired |
Related
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.