-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
SettingManagementStore not refreshing cache within the same UnitOfWork #4040
Comments
ISettingManager
not refreshing cache within the same UnitOfWork
What if we are using a distributed redis cache, you invalidate the cache but then your UOW failed on transaction commit? In this case, you've updated a shared cache, but actually not changed the data on the database. Actually, vice verse is also a problem (save OUW but can't update the cache). Your solution seems fine to me. Can you send a PR? |
A solution would be overriding a cached value via a temporary dictionary stored in the current request/httpcontext.items or somewhere. Let me think about that. |
You can maybe add a new local event handler which gets called upon exceptions when saving changes or committing the UOW transaction, and just keep track of what "keys" changed during that Uow (and invalidate them all on UOW completion failure). I wouldn't tie that to the http request in any way... that'd prevent you from using it on BackgroundWorkers, or BackgroundJobs or any other kind of hosted service outside http requests. You know, there are two things hard on programming: naming things and cache invalidation ;-) |
I've committed the pull request because I think this is a better scenario than it was before... however, there are still some problems with this approach: mainly, if we do a: I believe the "right" approach would be tracking the cache changesduring a UnitOfWork and rolling them back or invalidating them in case the UnitOfWork fails committing/saving changes: this however would also pose problems on a "microservices" scenario, since the caching for uncommitted changes would spread to other services (in case of a distributed cache, like redis) while it's still uncommited. The current scenario (with or without my pull request, which just solves a simple one), has many possible consistency problems... the biggest one of them being:
So in my oppinion, the cache during a unit of work should not be distributed and be kept local to the process (or to the actual unit of work): maybe update the distributed cache upon correctly committing the transaction at the end of the UOW. This is again problematic because ABP is mostly designed to have a UOW during for all requests, so this basically invalidates an "initial distributed cache" (since the first I see a way of solving this:
But maybe this needs more brainstorming Also, I'd have optional setting stores without a cache at all: depending on the usage, hitting the database every time a setting is requested may be the best scenario (rather than having a distributed cache, and taking most of the queries for settings are extremely simple and don't take a lot of information). Of course, since this is scenario-based, this should be an option (have the current If I can be of any help, just let me know |
I made this test for SettingManagementStore, which fails (on its test file):
Test result:
That's because the cache is invalidated only when the
UnitOfWork
finished (it uses anILocalEventHandler
on SettingCacheItemInvalidator)The scenario above is pretty common: if you have an API endpoint which updates a setting, it's VERY NORMAL wanting to use the new value from other service (the one using the setting), potentially in the same request, called from the same app service (with the same UnitOfWork).
The solution (which we apply on our projects) would be invalidating the cache (or updating it, although that might become inconsistent in case the UnitOfWork transaction failed to commit) on the
Update
path on theSettingManagementStore
(this wouldn't work if fiddling directly on the database, but that should be not recommended on the documentation -when it's done-), so basically this on here:This makes the test above pass flawlessly.
If you find this solution acceptable I can provide a PR for it (including the test if you want it)
The text was updated successfully, but these errors were encountered: