Skip to content

Introduce UserRefreshFromReplicaWorker that runs as a "safety-net" for correcting any wrong project authorization records

Currently, we run UserRefreshWithLowUrgencyWorker as a safety net for correcting any wrong project authorization records.

However, our plan going forward is to make these safety-net jobs read from the replica first, and only if the replica says that the user needs a refresh, will another job be enqueued.

The problem with the existing class, ie, UserRefreshWithLowUrgencyWorker is that its name does not suggest that the data will be read from replica.

Moreover, there is a specific requirement to use the UserRefreshWithLowUrgencyWorker over here that would read from primary. So it is best to keep UserRefreshWithLowUrgencyWorker as it is, as it has uses elsewhere.

So the plan is,

  • Keep UserRefreshWithLowUrgencyWorker as it is and make no changes in this class.
  • Introduce UserRefreshFromReplicaWorker which will behave exactly like the current UserRefreshWithLowUrgencyWorker to start with. (so that it would read from primary)
  • In first iteration, replace calls to UserRefreshWithLowUrgencyWorker with calls to UserRefreshFromReplicaWorker where ever it is required.
  • In second iteration, start reading data in UserRefreshFromReplicaWorker from the replica and make code changes like so, (this is being tracked as a separate issue at #333219 (closed))
module AuthorizedProjectUpdate
  class UserRefreshFromReplicaWorker
    include ApplicationWorker

    feature_category :authentication_and_authorization
    urgency :low
    queue_namespace :authorized_project_update
    deduplicate :until_executing, including_scheduled: true
    data_consistency :delayed

    idempotent!

    def perform(user_id)
      user = User.find_by(id: user_id)
      return unless user

      enqueue_project_authorizations_refresh(user) if project_authorizations_needs_refresh?(user)
    end

    private

    def project_authorizations_needs_refresh?(user)
      AuthorizedProjectUpdate::FindRecordsDueForRefreshService.new(user).needs_refresh?
    end

    def enqueue_project_authorizations_refresh(user)
      with_context(user: user) do
        AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker.perform_async(user.id)
      end
    end
  end
end
Edited by Manoj M J [OOO]