summaryrefslogtreecommitdiff
path: root/app/workers/project_cache_worker.rb
blob: 4dfa745fb509303562a7bc6f7ddbceef90357b7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Worker for updating any project specific caches.
#
# This worker runs at most once every 15 minutes per project. This is to ensure
# that multiple instances of jobs for this worker don't hammer the underlying
# storage engine as much.
class ProjectCacheWorker
  include Sidekiq::Worker
  include DedicatedSidekiqQueue

  LEASE_TIMEOUT = 15.minutes.to_i

  def self.lease_for(project_id)
    Gitlab::ExclusiveLease.
      new("project_cache_worker:#{project_id}", timeout: LEASE_TIMEOUT)
  end

  # Overwrite Sidekiq's implementation so we only schedule when actually needed.
  def self.perform_async(project_id)
    # If a lease for this project is still being held there's no point in
    # scheduling a new job.
    super unless lease_for(project_id).exists?
  end

  def perform(project_id)
    if try_obtain_lease_for(project_id)
      Rails.logger.
        info("Obtained ProjectCacheWorker lease for project #{project_id}")
    else
      Rails.logger.
        info("Could not obtain ProjectCacheWorker lease for project #{project_id}")

      return
    end

    update_caches(project_id)
  end

  def update_caches(project_id)
    project = Project.find(project_id)

    return unless project.repository.exists?

    project.update_repository_size
    project.update_commit_count

    if project.repository.root_ref
      project.repository.build_cache
    end
  end

  def try_obtain_lease_for(project_id)
    self.class.lease_for(project_id).try_obtain
  end
end