Class: Users::RefreshAuthorizedProjectsService
- Inherits:
-
Object
- Object
- Users::RefreshAuthorizedProjectsService
- Defined in:
- app/services/users/refresh_authorized_projects_service.rb
Overview
Service for refreshing the authorized projects of a user.
This particular service class can not be used to update data for the same user concurrently. Doing so could lead to an incorrect state. To ensure this doesn’t happen a caller must synchronize access (e.g. using Gitlab::ExclusiveLease).
Usage:
user = User.find_by(username: 'alice')
service = Users::RefreshAuthorizedProjectsService.new(some_user)
service.execute
Constant Summary collapse
- LEASE_TIMEOUT =
1.minute.to_i
Instance Attribute Summary collapse
-
#source ⇒ Object
readonly
Returns the value of attribute source.
-
#user ⇒ Object
readonly
Returns the value of attribute user.
Instance Method Summary collapse
- #execute ⇒ Object
-
#execute_without_lease ⇒ Object
This method returns the updated User object.
-
#initialize(user, source: nil, incorrect_auth_found_callback: nil, missing_auth_found_callback: nil) ⇒ RefreshAuthorizedProjectsService
constructor
user - The User for which to refresh the authorized projects.
-
#update_authorizations(remove = [], add = []) ⇒ Object
Updates the list of authorizations for the current user.
Constructor Details
#initialize(user, source: nil, incorrect_auth_found_callback: nil, missing_auth_found_callback: nil) ⇒ RefreshAuthorizedProjectsService
user - The User for which to refresh the authorized projects.
22 23 24 25 26 27 28 29 30 |
# File 'app/services/users/refresh_authorized_projects_service.rb', line 22 def initialize(user, source: nil, incorrect_auth_found_callback: nil, missing_auth_found_callback: nil) @user = user @source = source @incorrect_auth_found_callback = incorrect_auth_found_callback @missing_auth_found_callback = missing_auth_found_callback @start_time = current_monotonic_time @duration_statistics = {} end |
Instance Attribute Details
#source ⇒ Object (readonly)
Returns the value of attribute source.
17 18 19 |
# File 'app/services/users/refresh_authorized_projects_service.rb', line 17 def source @source end |
#user ⇒ Object (readonly)
Returns the value of attribute user.
17 18 19 |
# File 'app/services/users/refresh_authorized_projects_service.rb', line 17 def user @user end |
Instance Method Details
#execute ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'app/services/users/refresh_authorized_projects_service.rb', line 32 def execute lease_key = "refresh_authorized_projects:#{user.id}" lease = Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT) until uuid = lease.try_obtain # Keep trying until we obtain the lease. If we don't do so we may end up # not updating the list of authorized projects properly. To prevent # hammering Redis too much we'll wait for a bit between retries. sleep(0.1) end reset_timer_and_store_duration(:obtain_redis_lease) begin # We need an up to date User object that has access to all relations that # may have been created earlier. The only way to ensure this is to reload # the User object. user.reset execute_without_lease ensure Gitlab::ExclusiveLease.cancel(lease_key, uuid) end end |
#execute_without_lease ⇒ Object
This method returns the updated User object.
57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'app/services/users/refresh_authorized_projects_service.rb', line 57 def execute_without_lease remove, add = AuthorizedProjectUpdate::FindRecordsDueForRefreshService.new( user, source: source, incorrect_auth_found_callback: incorrect_auth_found_callback, missing_auth_found_callback: missing_auth_found_callback ).execute reset_timer_and_store_duration(:find_records_due_for_refresh) (remove, add) end |
#update_authorizations(remove = [], add = []) ⇒ Object
Updates the list of authorizations for the current user.
remove - The project IDs of the authorization rows to remove. add - Rows to insert in the form ‘[{ user_id: user_id, project_id: project_id, access_level: access_level}, …]`
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'app/services/users/refresh_authorized_projects_service.rb', line 74 def (remove = [], add = []) ProjectAuthorizations::Changes.new do |changes| changes.add(add) changes.remove_projects_for_user(user, remove) end.apply! user.update!(project_authorizations_recalculated_at: Time.zone.now) if remove.any? || add.any? reset_timer_and_store_duration(:update_authorizations) log_refresh_details(remove, add) # Since we batch insert authorization rows, Rails' associations may get # out of sync. As such we force a reload of the User object. user.reset end |