Improve performance and interaction with starred objects.

Review Request #14825 — Created Feb. 18, 2026 and updated

Information

Review Board
release-7.1.x

Reviewers

Review requests and groups can be starred, and the star status can be
shown in the datagrids and the review request page.

The star status of an individual object would be looked up via a
database call, wrapped in a method on Profile. An optimization was in
place to avoid this lookup if memcached state told us that the user
didn't have any starred objects. If we wanted to look up the same object
more than once, we'd have more than one database query.

The dashboard worked differently, and in a somewhat invasive way. The
column would pre-fetch the IDs of any displayed rows that were starred,
and then bolt those onto the review request or group as an attribute to
aid caching of the state and rendering of the star indicator.

The dashboard's caching attempt wasn't applicable to general lookup and
rendering, and in practice this meant that we tended to look up the
star status more than once on the review request page.

We now go about this differently.

Profile now maintains a local star_cache attribute, which keys
(model_type, pk) to a boolean indicating if an object is cached. When
we star, unstar, or look up the star state for an object via Profile,
we update this cache, speeding up subsequent lookups. This cuts down on
lookups on the review request page.

The star columns on datagrids are now much more simple and less hacky.
They populate star_cache during the queryset augmentation phase, and
then rendering just renders as normal.

The render_star utility just now needs to call the Profile methods
for checking if the object is starred, and render it appropriately. All
the bolted-on cache attribute checks are gone, and it benefits from
Profile-stored caches.

With Profile managing all lookups, this opens the door for optimizing
things further down the line, if needed. Only Profile needs to
interface with the database, and it owns the cache. There are no
immediate plans for optimizing further, but if we need to, we'll have
one place to do that.

Unit tests pass.

Tested starring and unstarring on the dashboard and group datagrids.
Verified that the state was recorded and loaded correctly on page
load and on the other pages.

Summary ID
Improve performance and interaction with starred objects.
Review requests and groups can be starred, and the star status can be shown in the datagrids and the review request page. The star status of an individual object would be looked up via a database call, wrapped in a method on `Profile`. An optimization was in place to avoid this lookup if memcached state told us that the user didn't have any starred objects. If we wanted to look up the same object more than once, we'd have more than one database query. The dashboard worked differently, and in a somewhat invasive way. The column would pre-fetch the IDs of any displayed rows that were starred, and then bolt those onto the review request or group as an attribute to aid caching of the state and rendering of the star indicator. The dashboard's caching attempt wasn't applicable to general lookup and rendering, and in practice this meant that we tended to look up the star status more than once on the review request page. We now go about this differently. `Profile` now maintains a local `star_cache` attribute, which keys `(model_type, pk)` to a boolean indicating if an object is cached. When we star, unstar, or look up the star state for an object via `Profile`, we update this cache, speeding up subsequent lookups. This cuts down on lookups on the review request page. The star columns on datagrids are now much more simple and less hacky. They populate `star_cache` during the queryset augmentation phase, and then rendering just renders as normal. The `render_star` utility just now needs to call the `Profile` methods for checking if the object is starred, and render it appropriately. All the bolted-on cache attribute checks are gone, and it benefits from `Profile`-stored caches. With `Profile` managing all lookups, this opens the door for optimizing things further down the line, if needed. Only `Profile` needs to interface with the database, and it owns the cache. There are no immediate plans for optimizing further, but if we need to, we'll have one place to do that.
b62e16cc19cec8190caa2ed1eccacd4657718c56
Description From Last Updated

Looks like this was copy/pasted. This docstring should be made generic.

daviddavid

undefined name 'SafeString' Column: 10 Error code: F821

reviewbotreviewbot

Something got messed up here.

daviddavid
Checks run (1 failed, 1 succeeded)
flake8 failed.
JSHint passed.

flake8

david
  1. 
      
  2. reviewboard/accounts/models.py (Diff revision 1)
     
     
     
     
     
    Show all issues

    Looks like this was copy/pasted. This docstring should be made generic.

  3. reviewboard/datagrids/columns.py (Diff revision 1)
     
     
     
     
    Show all issues

    Something got messed up here.

  4.