notes cache are not invalidated correctly
We store pre-rendered HTML code with our notes, which help us minimize N+1 queries to render references. The problem is that whenever a cached data changes, like an issue title or merge request title, there is no easy way to invalidate them.
There are two possible alternatives to solve this:
- keep a reverse graph of places that refers to the target item, in order to trigger cache invalidations
- don't cache mutable data (like titles, descriptions etc) into pre-rendered HTML code and try to reduce requests by smart caching on client-side
For the reverse graph, as we now have to support only Postgres, we can use either jsonb or array in our favor. An alternative using array would be to add (to Issues,MRs and Epics):
mentioned_in_issuesmentioned_in_merge_requestsmentioned_in_epics
And keep unique ids of places that mention that entity, so whenever title/description/status is changed, we know what to invalidate cache for.
For the JSONB approach, we would create a mention field on the notes, and we can store either only ids, which we can use to search for later on and flag things that need to be refreshed, or store the mutable data, which we can update as well, in a single transaction.
For the smart cache idea on client-side, we can do something on this line:
- Keep each mentionable item stored on users browser IndexedDB, with all required data and a cache key.
- Whenever a user loads an issue/MR/epic, we look for the items we already have on local IndexedDB and use them right away for a faster UI response
- We do re-validate items on background by batching up a query to a GraphQL endpoint listing each primary_key for each type, along with the cache key. Ex:
{issues: [{id: 25: cache_key: '...'}]}, the response would be either something likecache_fresh: truefor each item/primary key, or content to update to. - After the cache is refreshed we feed that back to the Vue app and let it handles re/rendering stuff
We can even go further and keep a TTL as well to prevent refreshing it every page hit. Also another thing we can do is, whenever you update an issue/MR/epic, your browser session should invalidate that local cache you have, so if you go to another window that is still open, when you hover over a mention, as that would be missing on the local indexedDB, it will fetch for the freshest version on the API.