-
-
Notifications
You must be signed in to change notification settings - Fork 825
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
(REF) Add CRM_Utils_Cache::nack(). Use it for NaiveHasTrait. #13500
Conversation
The `NaiveHasTrait` is a generic implementation of PSR-16 `has()` which builds on the logic of PSR-16 `get()`. This reduces I/O for `has()`. Before ------ * Each call to `has()` triggers two calls to `get()`. After ----- * Each call to `has()` triggers one call to `get()`. Comments -------- The correctness of this stems from the uniqueness of the `$nack` value. To wit: if you always use the same constant (e.g. `NULL` or `0` or `''` or `'no-value'`) to signify a cache-miss, then it's trivial to produce a collision/incorrect-result. (Simply store that constant.) But if the value is a sufficiently unique nonce, then it becomes impractical to produce a collision/incorrect-result.
(Standard links)
|
Note for reviewers: the function TLDR: If |
This makes sense architecturally & has test coverage as described. The has function is overriden in the MemCache implementation but I can't actually find any place that calls this. Seems OK to merge as if lays the groundwork for later things |
This is a follow-up to civicrm#13500. Before ------ * `CRM_Utils_Cache::nack()` returns an array with a value named `nack` * The value returned is somewhat unique -- a random value is generated once per page-view After ----- * `CRM_Utils_Cache::nack()` returns a string * The value returned is more unique -- combining that random value (per page-view) and an offset (per invocation) Comments -------- * The code was originally written with the intent of returning a string. However, there was a slight copy-paste error which caused it to return an array (which contained that string). It functioned correctly anyway, but it feels weird when reading/inspecting. * The more unique the nack-value is, the more correct the nack-checking pattern is. Appending a static-counter is a simple, fast way to provide stronger uniqueness within a page-view. * There may be some obscure edge-cases in which the previous pattern was not sufficiently unique -- e.g. combining tiers-of-tiers or decorators-of-decorators. I haven't verified that, but it seems unimportant given that the static-counter is so straightforward. * In `NaiveHasTrait`, the extra `ht` suffix was an attempt to increase the uniquness. However, the static-counter seems better.
This is a follow-up to civicrm#13500. Before ------ * `CRM_Utils_Cache::nack()` returns an array with a value named `nack`. * The value returned is somewhat unique -- a random value is generated once per page-view. * There is no explicit/direct unit-test. After ----- * `CRM_Utils_Cache::nack()` returns a string. * The value returned is more unique -- combining that random value (per page-view) and an offset (per invocation). * There is an explicit/direct unit-test. Comments -------- * The code was originally written with the intent of returning a string. However, there was a slight copy-paste error which caused it to return an array (which contained that string). Functionally, that worked (because it was serializable and met the same minimum uniqueness constraint), but it's weird to read/inspect, and we should change quickly before something else locks-in the odd structure. * The more unique the nack-value is, the more correct the nack-checking pattern is. Appending a static-counter is a simple, fast way to provide stronger uniqueness within a page-view. * There may be some obscure edge-cases in which the previous pattern was not sufficiently unique -- e.g. combining tiers-of-tiers or decorators-of-decorators. I haven't verified that, but it seems unimportant given that the static-counter is so straightforward. * In `NaiveHasTrait`, the extra `ht` suffix was an attempt to increase the uniquness. However, the static-counter seems better.
if (!isset(Civi::$statics[__CLASS__]['nack'])) { | ||
Civi::$statics[__CLASS__]['nack'] = 'NACK:' . md5(CRM_Utils_Request::id() . CIVICRM_SITE_KEY . CIVICRM_DSN . mt_rand(0, 10000)); | ||
} | ||
return Civi::$statics[__CLASS__]; |
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.
Doh. Line 286 should be like lines 283+284 --specially address the nack
item (rather than the array of statics held for this class). This worked in testing anyway, albeit for the wrong reason. Correction: #13514
Overview
When using PSR-16 to read a cached value, the
$cache->get($key)
will a return a default value on cache-miss, so it's hard to know if you've gotten a genuine value from the cache or just a default. If you need to know that, then it requires a second call to$cache->has($key)
.For some scenarios (esp for upcoming #13496 but also for existing
NaiveHasTrait
), it's important to know if you have a default or a cache-miss, and the code is central enough that we should avoid unnecesary roundtrips.Before
NaiveHasTrait
; that implementation of$cache->has()
requires two round-trips.$cache->has()
and$cache->get()
, then there are typically three round-trips.After
Most cache drivers in Civi mix-in
NaiveHasTrait
; that implementation of$cache->has()
only requires one round-trip.If you want to do a
$cache->has()
and$cache->get()
, it can be handled with one round-trip: