# frozen_string_literal: true module Users # Service class for caching and retrieving the last push event of a user. class LastPushEventService EXPIRATION = 2.hours def initialize(user) @user = user end # Caches the given push event for the current user in the Rails cache. # # event - An instance of PushEvent to cache. def cache_last_push_event(event) keys = [ project_cache_key(event.project), user_cache_key ] if forked_from = event.project.forked_from_project keys << project_cache_key(forked_from) end keys.each { |key| set_key(key, event.id) } end # Returns the last PushEvent for the current user. # # This method will return nil if no event was found. def last_event_for_user find_cached_event(user_cache_key) end # Returns the last PushEvent for the current user and the given project. # # project - An instance of Project for which to retrieve the PushEvent. # # This method will return nil if no event was found. def last_event_for_project(project) find_cached_event(project_cache_key(project)) end def find_cached_event(cache_key) event_id = get_key(cache_key) return unless event_id unless (event = find_event_in_database(event_id)) # We don't want to keep querying the same data over and over when a # merge request has been created, thus we remove the key if no event # (meaning an MR was created) is returned. Rails.cache.delete(cache_key) end event end private # rubocop: disable CodeReuse/ActiveRecord def find_event_in_database(id) PushEvent .without_existing_merge_requests .find_by(id: id) end # rubocop: enable CodeReuse/ActiveRecord def user_cache_key "last-push-event/#{@user.id}" end def project_cache_key(project) "last-push-event/#{@user.id}/#{project.id}" end def get_key(key) Rails.cache.read(key, raw: true) end def set_key(key, value) # We're using raw values here since this takes up less space and we don't # store complex objects. Rails.cache.write(key, value, raw: true, expires_in: EXPIRATION) end end end