Class: Gitlab::GithubImport::UserFinder

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/github_import/user_finder.rb

Overview

Class that can be used for finding a GitLab user ID based on a GitHub user ID or username.

Any found user IDs are cached in Redis to reduce the number of SQL queries executed over time. Valid keys are refreshed upon access so frequently used keys stick around.

Lookups are cached even if no ID was found to remove the need for querying the database when most queries are not going to return results anyway.

Constant Summary collapse

ID_CACHE_KEY =

The base cache key to use for caching user IDs for a given GitHub user ID.

'github-import/user-finder/user-id/%s'
ID_FOR_EMAIL_CACHE_KEY =

The base cache key to use for caching user IDs for a given GitHub email address.

'github-import/user-finder/id-for-email/%s'
EMAIL_FOR_USERNAME_CACHE_KEY =

The base cache key to use for caching the Email addresses of GitHub usernames.

'github-import/user-finder/email-for-username/%s'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project, client) ⇒ UserFinder

project - An instance of `Project` client - An instance of `Gitlab::GithubImport::Client`


33
34
35
36
# File 'lib/gitlab/github_import/user_finder.rb', line 33

def initialize(project, client)
  @project = project
  @client = client
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client


15
16
17
# File 'lib/gitlab/github_import/user_finder.rb', line 15

def client
  @client
end

#projectObject (readonly)

Returns the value of attribute project


15
16
17
# File 'lib/gitlab/github_import/user_finder.rb', line 15

def project
  @project
end

Instance Method Details

#assignee_id_for(issuable) ⇒ Object

Returns the GitLab user ID of an issuable's assignee.


58
59
60
# File 'lib/gitlab/github_import/user_finder.rb', line 58

def assignee_id_for(issuable)
  user_id_for(issuable.assignee) if issuable.assignee
end

#author_id_for(object) ⇒ Object

Returns the GitLab user ID of an object's author.

If the object has no author ID we'll use the ID of the GitLab ghost user.


42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/gitlab/github_import/user_finder.rb', line 42

def author_id_for(object)
  id =
    if object&.author
      user_id_for(object.author)
    else
      GithubImport.ghost_user_id
    end

  if id
    [id, true]
  else
    [project.creator_id, false]
  end
end

#cached_id_for_github_email(email) ⇒ Object


119
120
121
# File 'lib/gitlab/github_import/user_finder.rb', line 119

def cached_id_for_github_email(email)
  read_id_from_cache(ID_FOR_EMAIL_CACHE_KEY % email)
end

#cached_id_for_github_id(id) ⇒ Object


115
116
117
# File 'lib/gitlab/github_import/user_finder.rb', line 115

def cached_id_for_github_id(id)
  read_id_from_cache(ID_CACHE_KEY % id)
end

#email_for_github_username(username) ⇒ Object


103
104
105
106
107
108
109
110
111
112
113
# File 'lib/gitlab/github_import/user_finder.rb', line 103

def email_for_github_username(username)
  cache_key = EMAIL_FOR_USERNAME_CACHE_KEY % username
  email = Gitlab::Cache::Import::Caching.read(cache_key)

  unless email
    user = client.user(username)
    email = Gitlab::Cache::Import::Caching.write(cache_key, user.email) if user
  end

  email
end

#find(id, username) ⇒ Object

Returns the GitLab ID for the given GitHub ID or username.

id - The ID of the GitHub user. username - The username of the GitHub user.


73
74
75
76
77
78
79
80
81
82
83
# File 'lib/gitlab/github_import/user_finder.rb', line 73

def find(id, username)
  email = email_for_github_username(username)
  cached, found_id = find_from_cache(id, email)

  return found_id if found_id

  # We only want to query the database if necessary. If previous lookups
  # didn't yield a user ID we won't query the database again until the
  # keys expire.
  find_id_from_database(id, email) unless cached
end

#find_from_cache(id, email = nil) ⇒ Object

Finds a user ID from the cache for a given GitHub ID or Email.


86
87
88
89
90
91
92
93
94
95
# File 'lib/gitlab/github_import/user_finder.rb', line 86

def find_from_cache(id, email = nil)
  id_exists, id_for_github_id = cached_id_for_github_id(id)

  return [id_exists, id_for_github_id] if id_for_github_id

  # Just in case no Email address could be retrieved (for whatever reason)
  return [false] unless email

  cached_id_for_github_email(email)
end

#find_id_from_database(id, email) ⇒ Object

Finds a GitLab user ID from the database for a given GitHub user ID or Email.


99
100
101
# File 'lib/gitlab/github_import/user_finder.rb', line 99

def find_id_from_database(id, email)
  id_for_github_id(id) || id_for_github_email(email)
end

#id_for_github_email(email) ⇒ Object

Queries and caches the GitLab user ID for a GitHub email, if one was found.


133
134
135
136
137
# File 'lib/gitlab/github_import/user_finder.rb', line 133

def id_for_github_email(email)
  gitlab_id = query_id_for_github_email(email) || nil

  Gitlab::Cache::Import::Caching.write(ID_FOR_EMAIL_CACHE_KEY % email, gitlab_id)
end

#id_for_github_id(id) ⇒ Object

Queries and caches the GitLab user ID for a GitHub user ID, if one was found.


125
126
127
128
129
# File 'lib/gitlab/github_import/user_finder.rb', line 125

def id_for_github_id(id)
  gitlab_id = query_id_for_github_id(id) || nil

  Gitlab::Cache::Import::Caching.write(ID_CACHE_KEY % id, gitlab_id)
end

#query_id_for_github_email(email) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


146
147
148
# File 'lib/gitlab/github_import/user_finder.rb', line 146

def query_id_for_github_email(email)
  User.by_any_email(email).pluck(:id).first
end

#query_id_for_github_id(id) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


140
141
142
# File 'lib/gitlab/github_import/user_finder.rb', line 140

def query_id_for_github_id(id)
  User.for_github_id(id).pluck(:id).first
end

#read_id_from_cache(key) ⇒ Object

Reads an ID from the cache.

The return value is an Array with two values:

  1. A boolean indicating if the key was present or not.

  2. The ID as an Integer, or nil in case no ID could be found.


157
158
159
160
161
162
163
164
165
# File 'lib/gitlab/github_import/user_finder.rb', line 157

def read_id_from_cache(key)
  value = Gitlab::Cache::Import::Caching.read(key)
  exists = !value.nil?
  number = value.to_i

  # The cache key may be empty to indicate a previously looked up user for
  # which we couldn't find an ID.
  [exists, number > 0 ? number : nil]
end

#user_id_for(user) ⇒ Object

Returns the GitLab user ID for a GitHub user.

user - An instance of `Gitlab::GithubImport::Representation::User`.


65
66
67
# File 'lib/gitlab/github_import/user_finder.rb', line 65

def user_id_for(user)
  find(user.id, user.)
end