gitlab-org--gitlab-foss/app/models/user_interacted_project.rb

46 lines
1.3 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
class UserInteractedProject < ApplicationRecord
belongs_to :user
belongs_to :project
validates :project_id, presence: true
validates :user_id, presence: true
2018-02-23 19:56:43 +00:00
CACHE_EXPIRY_TIME = 1.day
2018-02-26 11:24:02 +00:00
class << self
def track(event)
# For events without a project, we simply don't care.
# An example of this is the creation of a snippet (which
# is not related to any project).
return unless event.project_id
2018-02-26 11:24:02 +00:00
attributes = {
project_id: event.project_id,
user_id: event.author_id
}
cached_exists?(**attributes) do
transaction(requires_new: true) do
2019-03-13 13:42:43 +00:00
where(attributes).select(1).first || create!(attributes)
true # not caching the whole record here for now
rescue ActiveRecord::RecordNotUnique
# Note, above queries are not atomic and prone
# to race conditions (similar like #find_or_create!).
# In the case where we hit this, the record we want
# already exists - shortcut and return.
true
2018-02-26 11:24:02 +00:00
end
2018-02-23 19:56:43 +00:00
end
end
2018-02-26 11:24:02 +00:00
private
2018-02-23 19:56:43 +00:00
2018-02-26 11:24:02 +00:00
def cached_exists?(project_id:, user_id:, &block)
cache_key = "user_interacted_projects:#{project_id}:#{user_id}"
2018-02-26 11:24:02 +00:00
Rails.cache.fetch(cache_key, expires_in: CACHE_EXPIRY_TIME, &block)
end
end
end