Skip to content

Create the frecent items GraphQL endpoints

What does this MR do and why?

Create the frecent items GraphQL endpoints

Implements the endpoints for fetching frecently visited projects and groups via the GrahphQL API.

Screenshots or screen recordings

No user-facing change.

How to set up and validate locally

  1. Enable the frecent_namespaces_suggestions feature flag.

    Feature.enable(:frecent_namespaces_suggestions)
  2. (optional) You might want to seed some visits if your GDK hasn't yet tracked enough data. Run the following script in the Rails console to create 1000 project and group visits spread over the last 3 months:

    def datetime_rand from = 0.0, to = Time.now
      Time.at(from + rand * (to.to_f - from.to_f)).to_datetime
    end
    
    def seed_project_visit(user)
      offset = rand(Project.count)
      project = Project.offset(offset).first
      visited_at = datetime_rand Time.now - 3.months
      Users::ProjectVisit.create!(user_id: user.id, entity_id: project.id, visited_at: visited_at)
    end
    
    def seed_group_visit(user)
      offset = rand(Group.count)
      group = Group.offset(offset).first
      visited_at = datetime_rand Time.now - 3.months
      Users::GroupVisit.create!(user_id: user.id, entity_id: group.id, visited_at: visited_at)
    end
    
    for i in 1..1000
      user = User.first # This should get the root user. Change if needed.
    
      seed_project_visit(user)
      seed_group_visit(user)
    end
  3. In the GraphQL explorer (http://gdk.test:3000/-/graphql-explorer), run any of the following queries to get the frecent projects or groups:

    query CurrentUserFrecentProjects {
      frecentProjects {
        name
        webUrl
        avatarUrl
        nameWithNamespace
      }
    }
    query CurrentUserFrecentGroups {
      frecentGroups {
        name
        webUrl
        avatarUrl
        fullPath
        fullName
      }
    }

Frecency scores SQL queries

Frecency scores for projects and groups are computed by retrieving a user's project or group visits (effectively limited to the last 3 months due to the tables' retention policy), and adding weighted scores for every namespace. Recent visits score higher.

Both queries output a namespace ID <=> score list from which we extract the highest scoring entities and retrieve the associated projects/groups:

Project.find(ids)
# or
Group.find(ids)

Projects

SELECT
    entity_id,
    SUM(week_count * dense_rank) AS score
FROM (
    SELECT
        "projects_visits"."entity_id",
        COUNT(entity_id) AS week_count,
        DATE_TRUNC('week', visited_at)::date AS week_start,
        DENSE_RANK() OVER (ORDER BY DATE_TRUNC('week', visited_at)::date)
    FROM "projects_visits"
WHERE (visited_at > '2023-08-07 16:15:37.939106')
    AND (visited_at <= '2023-11-07 16:15:37.954841')
AND "projects_visits"."user_id" = 3732265
GROUP BY "week_start",
"projects_visits"."entity_id") AS ranked_entity_visits
GROUP BY
    entity_id
ORDER BY
    score DESC
LIMIT 5

Query analysis: https://console.postgres.ai/gitlab/gitlab-production-tunnel-pg12/sessions/23700/commands/76119

Groups

SELECT
    entity_id,
    SUM(week_count * dense_rank) AS score
FROM (
    SELECT
        "groups_visits"."entity_id",
        COUNT(entity_id) AS week_count,
        DATE_TRUNC('week', visited_at)::date AS week_start,
        DENSE_RANK() OVER (ORDER BY DATE_TRUNC('week', visited_at)::date)
    FROM "groups_visits"
WHERE (visited_at > '2023-08-07 16:19:30.014123')
    AND (visited_at <= '2023-11-07 16:19:30.014382')
AND "groups_visits"."user_id" = 3732265
GROUP BY "week_start",
"groups_visits"."entity_id") AS ranked_entity_visits
GROUP BY
    entity_id
ORDER BY
    score DESC
LIMIT 3

Query analysis: https://console.postgres.ai/gitlab/gitlab-production-tunnel-pg12/sessions/23700/commands/76120

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Related to #431044 (closed)

Edited by Paul Gascou-Vaillancourt

Merge request reports