Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FORMS-1677: add user caching #1577

Closed

Conversation

usingtechnology
Copy link
Collaborator

@usingtechnology usingtechnology commented Jan 14, 2025

To reduce the number of hits to the db for user (login user - parsed token + db id) add a caching layer.

Cache the login user (parsed token + db fields). Caching is limited to 5 minutes - same as our token.

A few important things happen before we read from the cache:

  • the token is parsed
  • the token is verified

If we have a valid token, we can then check the cache. If we get a cache hit, we check to see that the cache version matches the token (token may have been refreshed). If that cache hit is stale, then we discard it and do the normal refresh and hydration of the login user and then cache it.

The login user (current user) is called on nearly all endpoints and currently invokes 2 db hits. Short term caching will reduce db load and therefore improve performance. This caching strategy is not aggressive and has safeguards to prevent returning an invalid user.

This relates to #1579 where we remove forms from the current user and use explicit form queries instead of always making those 2 db hits.

Description

Type of Change

feat (a new feature)

perf (change to improve performance)

Checklist

  • I have read the CONTRIBUTING doc
  • I have checked that unit tests pass locally with my changes
  • I have run the npm script lint on the frontend and backend
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)
  • I have approval from the product owner for the contribution in this pull request

Further comments

To reduce the number of hits to the db for user (login user and current user) add a caching layer.

Signed-off-by: Jason Sherman <tools@usingtechnolo.gy>
Copy link
Collaborator

@WalterMoar WalterMoar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that as a team we need to discuss this sort of thing before work starts on it.

@usingtechnology
Copy link
Collaborator Author

I think that as a team we need to discuss this sort of thing before work starts on it.

I have no idea when we are going to have a prioritized list of tasks, so got to work on something. Performance is an issue and has been raised by clients. Some analysis has been done on this (no metrics, but when are we going to get metrics?) so good thing as any to get cracking on. This isn't a "look at the files and approve" PR. At least there is something to kick around and test out.

This comment has been minimized.

usingtechnology and others added 3 commits January 16, 2025 14:43
Signed-off-by: Jason Sherman <tools@usingtechnolo.gy>
Signed-off-by: Jason Sherman <tools@usingtechnolo.gy>

This comment has been minimized.

usingtechnology and others added 2 commits January 20, 2025 09:08
Signed-off-by: Jason Sherman <tools@usingtechnolo.gy>
Copy link
Collaborator

@WalterMoar WalterMoar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that there's a problem with how the frontend makes API calls. However, I don't think that adding complexity (a new caching system) to CHEFS is the approach we want to take. It increases the things that developers need to understand, and it adds dependencies that have to be maintained. Is there a reason that this information can't be stored in Pinia?

@usingtechnology
Copy link
Collaborator Author

I agree that there's a problem with how the frontend makes API calls. However, I don't think that adding complexity (a new caching system) to CHEFS is the approach we want to take. It increases the things that developers need to understand, and it adds dependencies that have to be maintained. Is there a reason that this information can't be stored in Pinia?

It can't be stored in Pinia because it is the backend that makes the db calls on each API. It's the backend that needs to hydrate the token with the db information so it can reliably do role/permissions checks. The backend doesn't care what the frontend stores or passes in for user information; the backend only trusts the token. That hasn't changed, the procedure for parsing and verifying the token still happens each call. The only thing that changes is the removing the db calls to fetch/set the user data for a period of time.

This PR isn't proposing that we start caching everything, it is one thing and it is the one thing that is called on nearly all API calls. The token & user information is very consistent but we pair them and ensure the db matches on every single call. All we do now is see if the incoming token matches a stored token and use that if it matches. The cache self expires (lives no longer than a token) so it doesn't get stale and if the token has changed before it expires then we follow normal procedure.

Every PR has something new that a developer should understand. Understanding caching isn't some obsure or esoteric function. I don't think this is complex at all.

I do understand bringing in more libraries does introduce potential maintenance time. Are we going to make that a criteria for better performance/user experience? The 3 libraries introduced have minimial dependencies... 3 libs with 4 additional libs in total. That's not insignificant but smaller than others. jsonwebtoken has 10 direct dependencies with an additional 6, what's the cutoff for functionality vs maintenance?

As far as PRs go, this one has far less risk than many others. It introduces no new data to be saved, it doesn't alter any persisted data, it introduces no new APIs, the unit test has 100% coverage of the service, the code is extremely isolated and reversal of introduced code is simple - boils down to like 6 lines in one method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants