Class: Gitlab::Search::RecentItems

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/search/recent_items.rb

Overview

This is an abstract class used for storing/searching recently viewed items. The #type and #finder methods are the only ones needed to be implemented by classes inheriting from this.

Direct Known Subclasses

RecentIssues, RecentMergeRequests

Constant Summary collapse

ITEMS_LIMIT =

How much history to remember from the user

100
SEARCH_LIMIT =

How many matching items to return from search

5
EXPIRES_AFTER =
7.days

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user:, items_limit: ITEMS_LIMIT, expires_after: EXPIRES_AFTER) ⇒ RecentItems

Returns a new instance of RecentItems.



15
16
17
18
19
# File 'lib/gitlab/search/recent_items.rb', line 15

def initialize(user:, items_limit: ITEMS_LIMIT, expires_after: EXPIRES_AFTER)
  @user = user
  @items_limit = items_limit
  @expires_after = expires_after
end

Instance Attribute Details

#userObject (readonly)

Returns the value of attribute user.



13
14
15
# File 'lib/gitlab/search/recent_items.rb', line 13

def user
  @user
end

Instance Method Details

#latest_with_timestampsHash<ActiveRecord::Base, Time>

Returns the most recently viewed items with their view timestamps

objects and values are the timestamp of the last visit

Returns:

  • Hash where keys are recently viewed ActiveRecord



48
49
50
51
52
53
54
# File 'lib/gitlab/search/recent_items.rb', line 48

def latest_with_timestamps
  timestamps = latest_ids_with_timestamps
  ids = timestamps.keys.map(&:to_i)
  items = query_items_by_ids(nil, ids)

  items.index_with { |item| Time.zone.at(timestamps[item.id.to_s]) }
end

#log_view(item) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/gitlab/search/recent_items.rb', line 21

def log_view(item)
  with_redis do |redis|
    redis.zadd(key, Time.now.to_f, item.id)
    redis.expire(key, @expires_after)

    # There is a race condition here where we could end up removing an
    # item from 2 places concurrently but this is fine since worst case
    # scenario we remove an extra item from the end of the list.
    if redis.zcard(key) > @items_limit
      redis.zremrangebyrank(key, 0, 0) # Remove least recent
    end
  end
end

#search(term) ⇒ Array<ActiveRecord::Base>

Searches for recently viewed items matching the given term

Parameters:

  • Search term to filter items by title, or nil for no filtering

Returns:

  • Array of matching items ordered by recency



39
40
41
42
# File 'lib/gitlab/search/recent_items.rb', line 39

def search(term)
  ids = latest_ids
  query_items_by_ids(term, ids)
end