-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
Only use in-memory cache for database settings, set ttl=5 #12166
Conversation
d3f75a4
to
3156c49
Compare
This is blocked on a particularly nasty migration error on initial migration.
|
That recursion error looks like it's been fixed, running more tests now. |
I believe this is still relevant, but needs to be rebased and re-tested on top of #11373 |
Clarifying #12084 |
Make necessary adjustments to monkeypatch as it is very vunerable to recursion Clear cache for each request Clear cache if a setting is changed
Testing is looking good, now I just plan to write a short knowledge base article on general cache knowledge. |
|
||
val = None | ||
if 'migrate' not in sys.argv: | ||
if (isinstance(attr, str)) and (attr in DEFAULTS) and (not attr.startswith('_')): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jbradberry I'm removing the exception for migrations here because it is handled elsewhere now - by not initializing the settings wrapper when this condition is met. The other changes are to be more protective in __getattribute__
code, which is scary.
@@ -26,6 +26,11 @@ | |||
perf_logger = logging.getLogger('awx.analytics.performance') | |||
|
|||
|
|||
class SettingsCacheMiddleware(MiddlewareMixin): | |||
def process_request(self, request): | |||
settings._awx_conf_memoizedcache.clear() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get the reasoning of doing this here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any given automated script could do this:
- make a PATCH to
/api/v2/settings/jobs/
, applying new values - right after that, make a GET to
/api/v2/settings/jobs/
Regardless of what uWSGI worker processes the second (GET) request, it will be under the 5 second ttl
threshold. That means that it would give the values from before the PATCH. The automated script will then conclude that the PATCH it made did not take effect.
Now replace the generalized "automated script" with out integration tests, and you see the immediate reason this was needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the performance improvements here are pretty excellent.
SUMMARY
This is a speculative replacement for #12095, and maybe #5765 for good measure.
EDIT: due to unexpected developments, this does not replace 12095, but it does resolve 5765
Made a writeup on this here:
https://gist.github.com/AlanCoding/3bff66c63db36ae7cb8c326df2c38e29
ISSUE TYPE
COMPONENT NAME
ADDITIONAL INFORMATION
The
__getattr__
method here will be called for any Django setting. The_get_local
is only called for settings registered via our database settings system. For terminology, we call settings which are not registered "file-based settings".It doesn't make any sense to cache file-based settings. They are already static values. This in-memory cache is not only worthless for file-based settings, it actively throws errors. This will even happen when the
ttl
value is 0, so someone probably thought that this was equivalent to turning the caching off, but it's not.I didn't 100% need to introduce a new method here, but doing this avoids including the
validate
keyword argument in the cache key, which is my preference. It might also reduce the test churn from the change.