Implement caching for issue board lists polling

This is a sub-task of https://gitlab.com/gitlab-org/gitlab-ce/issues/22675 and the goal is to make polling of real-time board changes more performant.

Problem

For every issue board being displayed by user, frontend will poll periodically (every few seconds) for changes in issues being displayed in this board. Because issues will not change most of the time, it wouldn't be very effective to re-load all issues for the given board from DB on each poll request. We would rather want to use ETag caching (https://docs.gitlab.com/ee/development/polling.html) which we already use on other places.

Currently FE loads list of issues for each board list separately by requesting URL (project_or_group_namespace)/boards/:id/lists/:list_id/issues.

We would like to implement ETag caching on the board list level (TODO: consider caching on board level so FE would do one polling request for the whole board). So we would need to invalidate ETag cache when an issues in the given board list changes. This is challenging because:

Possible solution

(based on Sean's idea we discussed on Slack)

We could use list of cache keys for keeping list of board lists on which an issue is displayed:

  • we add 2 helper redis cache keys (both scoped in group namespace): issue_board_lists_keys - for keeping list of all cache keys, and issue_board_lists_$issue_id - for keeping list of board lists on which given issue is displayed
  • user views a board list, that loads some issues
  • each issue creates a cache key: issue_board_lists_$issue_id and adds this key to the issue_board_lists_keys (which keeps list of issue_board_lists_$issue_id)
  • value of issue_board_lists_$issue_id is a set of board list IDs, if the key already exists, it adds the board list ID to that set
  • when an issue is updated, it checks if there is issue_board_lists_$issue_id and if so, it invalidates ETag cache for all board lists listed in the value of this key
  • issue_board_lists_$issue_id cache key would have limited TTL, but higher than TTL of ETag cache key (which is 20 minutes), we would also "renew" TTL on each update of the key
  • issue_board_lists_keys's TTL would be either unlimited or renewed together with update of any of issue_board_lists_$issue_id keys (TODO: double-check invalidation of this - we want to make sure this variable doesn't just keep growing)
  • when a new issue is created, we have to invalidate all board lists being polled on which this issue can be displayed. This is the reason why we keep issue_board_lists_keys - we get all issue_board_lists_$issue_id keys from this cache key (because we can't easily get from redis all keys matching issue_board_lists_$issue_id pattern). And we invalidate ETag cache key for all board lists in all issue_board_lists_$issue_id.

E.g. we display issues with ID 23 on board lists 11 and 12, and issue with ID 24 on board lists 13 and 14. Both issue belongs to group ID 2. We would create following redis cache keys:

'/groups/2/issue_board_lists_keys': ['/groups/2/issue_board_lists_23', '/groups/2/issue_board_lists_24']
'/groups/2/issue_board_lists_23': [11, 12]
'/groups/2/issue_board_lists_24': [13, 14]

We could split this into 2 iterations:

First iteration

Add only issue_board_lists_$issue_id cache keys. In this iteration we wouldn't invalidate cache keys when a new issue is added.

Second iteration

Add issue_board_lists_keys which keeps list of existing issue_board_lists_$issue_id keys and invalidate them when new issue is added.

This page may contain information related to upcoming products, features and functionality. It is important to note that the information presented is for informational purposes only, so please do not rely on the information for purchasing or planning purposes. Just like with all projects, the items mentioned on the page are subject to change or delay, and the development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.

Edited by 🤖 GitLab Bot 🤖