Module: Gitlab::GitalyClient::WithFeatureFlagActors

Includes:
Utils::StrongMemoize
Included in:
BlobService, CleanupService, CommitService, ConflictsService, ObjectPoolService, OperationService, PraefectInfoService, RefService, RemoteService, RepositoryService
Defined in:
lib/gitlab/gitaly_client/with_feature_flag_actors.rb

Overview

This module is responsible for collecting feature flag actors in Gitaly Client. Unlike normal feature flags used in Gitlab development, feature flags passed to Gitaly are pre-evaluated at Rails side before being passed to Gitaly. As a result, we need to collect all possible actors for the evaluation before issue any RPC. At this layer, the only parameter we have is raw repository. We need to infer other actors from the repository. Adding extra SQL queries before any RPC are not good for the performance. We applied some quirky optimizations here to avoid issuing SQL queries. However, in some less common code paths, a couple of queries are expected.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#repository_actorObject

Returns the value of attribute repository_actor.



14
15
16
# File 'lib/gitlab/gitaly_client/with_feature_flag_actors.rb', line 14

def repository_actor
  @repository_actor
end

Instance Method Details

#gitaly_client_call(*args, **kargs) ⇒ Object

gitaly_client_call performs Gitaly calls including collected feature flag actors. The actors are retrieved from repository actor and memoized. The service must set ‘self.repository_actor = a_repository` beforehand.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/gitlab/gitaly_client/with_feature_flag_actors.rb', line 18

def gitaly_client_call(*args, **kargs)
  unless repository_actor
    Gitlab::ErrorTracking.track_and_raise_for_dev_exception(
      Feature::InvalidFeatureFlagError.new("gitaly_client_call called without setting repository_actor")
    )
  end

  GitalyClient.with_feature_flag_actors(
    repository: repository_actor,
    user: user_actor,
    project: project_actor,
    group: group_actor
  ) do
    GitalyClient.call(*args, **kargs)
  end
end

#gitaly_feature_flag_actors(repository) ⇒ Object

gitaly_feature_flag_actors returns a hash of actors implied from input repository.



36
37
38
39
40
41
42
43
44
# File 'lib/gitlab/gitaly_client/with_feature_flag_actors.rb', line 36

def gitaly_feature_flag_actors(repository)
  container = find_repository_container(repository)
  {
    repository: repository,
    user: Feature::Gitaly.user_actor,
    project: Feature::Gitaly.project_actor(container),
    group: Feature::Gitaly.group_actor(container)
  }
end

#group_actorObject



62
63
64
65
66
# File 'lib/gitlab/gitaly_client/with_feature_flag_actors.rb', line 62

def group_actor
  strong_memoize(:group_actor) do
    Feature::Gitaly.group_actor(repository_container)
  end
end

#project_actorObject

TODO: replace this project actor by Repo actor



56
57
58
59
60
# File 'lib/gitlab/gitaly_client/with_feature_flag_actors.rb', line 56

def project_actor
  strong_memoize(:project_actor) do
    Feature::Gitaly.project_actor(repository_container)
  end
end

#user_actorObject

Use actor here means the user who originally perform the action. It is collected from ApplicationContext. As this information is widely propagated in all entry points, User actor should be available everywhere, even in background jobs.



49
50
51
52
53
# File 'lib/gitlab/gitaly_client/with_feature_flag_actors.rb', line 49

def user_actor
  strong_memoize(:user_actor) do
    Feature::Gitaly.user_actor
  end
end