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
Remove cache data from the symfony events #30793
Conversation
Codecov Report
@@ Coverage Diff @@
## master #30793 +/- ##
============================================
+ Coverage 61.98% 61.98% +<.01%
- Complexity 18369 18536 +167
============================================
Files 1157 1157
Lines 69080 69088 +8
Branches 1242 1242
============================================
+ Hits 42818 42826 +8
Misses 25890 25890
Partials 372 372
Continue to review full report at Codecov.
|
lib/private/AppConfig.php
Outdated
'before' => ['key' => $key, 'value' => $value, 'app' => $app, 'appcache' => isset($this->cache[$app]) ? $this->cache[$app] : null], | ||
'after' => ['key' => $key, 'value' => $value, 'app' => $app, 'appcache' => isset($this->cache[$app]) ? $this->cache[$app] : null] | ||
'before' => ['key' => $key, 'value' => $value, 'app' => $app], | ||
'after' => ['key' => $key, 'value' => $value, 'app' => $app, 'update' => &$update, 'oldvalue' => &$oldValue] |
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.
why the &
sign 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.
Because when the update value is updated https://github.com/owncloud/core/pull/30793/files#diff-cdb763d0bc05b09a392296fde32add1dR209 and &
is not used, then the updated true
is not used. Hence the update value will not be reflected in the variable update
. Same for oldValue
.
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.
the &
sign is ok in the use()
block but why here in the "after" block ? also you didn't set a &
in the other hooks in this location
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.
The problem I felt was https://github.com/owncloud/core/blob/master/lib/public/Events/EventEmitterTrait.php#L46. The arguments
array which has both before
and after
arrays, is passed before any change is made. So if we don't use &
then no update will be reflected. This is one of the reason I find the other hooks I haven't used &
.
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.
as far as I understand how PHP works, if you add a &
on this line (the one my comment points to), it means that the array consumer will be able to modify the values. Ok, now I see that the array consumer is actually the method defined just before that. So it works as expected but feels a bit convoluted and confusing. I don't expect anyone who decides to add a hook to understand when and when not to add &
.
Anyway, since this event emitter pattern has already been reviewed and approved before, let's keep the pattern as is.
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.
Hmmmmm wait, but https://github.com/owncloud/core/blob/master/lib/public/Events/EventEmitterTrait.php#L46 isn't even using $update
directly. It's just passing the array as is to the GenericEvent. The GenericEvent arguments must be modified using setArgument('update', ...)
and not to PHP references.
Have you tried what happens if you remove the &
? Does it stop working ?
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.
follow up here https://github.com/owncloud/core/pull/30793/files#r175119030
lib/private/AppConfig.php
Outdated
@@ -193,12 +200,18 @@ public function setValue($app, $key, $value) { | |||
|
|||
$changedRow = (bool) $sql->execute(); | |||
|
|||
if (isset($this->cache[$app][$key])) { | |||
$oldValue = $this->cache[$app][$key]; |
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.
ohhh, so this line retroactively modifies the value of $oldValue
as referenced in the after
array... yeah, that's very convoluted and confusing.
any chance to read the $oldValue
earlier ? or have some of the code outside of the callback ?
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.
other possible approaches:
- have the callback receive the "before" and "after" arrays as additional function arguments, so it can simply modify the values there when needed. the modification operation will be easier to read and understand than magic updating through reference defined elsewhere
or
- don't use the emittingCall wrapper and send dispatcher events directly before and after the operation
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.
Its better to have approach one. And it worked. Had a basic test with file creation + folder creation, rename, deletion and restore operations. It didn't caused any warning or error in the log file. And the logs were populated. But we may have to update other places where emittingCall is made. So that we can have callback receive 'after' array.
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 chance to read the $oldValue earlier ? or have some of the code outside of the callback ?
yes I updated the PR by moving this logic outside emittingCall
.
a238ba1
to
0b44401
Compare
lib/private/AppConfig.php
Outdated
$oldValue = null; | ||
|
||
if (isset($this->cache[$app][$key])) { | ||
$oldValue = $this->cache[$app][$key]; |
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.
assuming there is a guarantee that the cache is always already populated at this point
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 have updated for and verified cache
has keys $app
and $key
set. If set then update the oldvalue and update var respectively.
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.
it's not about whether to check programmatically
are there any real life scenarios where the cache isn't initialized when we reached this point ? because that could make the event mistakenly think that a key did not exist and have "$update=false" despite the key existing in DB but not being in cache
please verify the logic that populates the cache and see whether it's compatible with the expectation 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.
Got it. There is a method loadConfigValues()
which can help us in such scenarios if configLoaded
is set to false before calling loadConfigValues
. That would at least make sure that the data fetched from DB is consistent with the cache
. But there is a drawback. It would cause performance, I believe. For every setValue call made, it would fetch the data from the DB ( since the configLoaded
is set to false).
Whenever the OC_APP::getAppVersions()
is called the cache is populated. Another way I see the cache update happens is when the apps are getting enabled.
So basically whenever the call
$appConfig = \OC::$server->getAppConfig();
with any of the get or delete method is called in AppConfig the cache
remains updated. Guess chances are bit low that such a scenario would be hit.
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.
ok, let's go the safe route then, how about approach 1 from #30793 (comment) ?
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.
can you elaborate ? all I see is "and" replaced with "&&"
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.
ok I see it now... hmmm
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.
this also means that any time you use "after" you are forced to define it as argument in the callback ?
in the case of other emitters, aren't they also using "after" and not specifying the receiving argument ?
if that works then I'm fine with this change
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.
The receiving argument is not mandatory. That is we can have either
$this->emittingCall(function() use(&$a, &$b) {}, ['before' => [], 'after' => []], 'foo', 'update');
or
$this->emittingCall(function($afterArray) use (&$a, &$b) {}, ['before => [], 'after' => []], 'foo', 'read');
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.
Adding a unit test for the same in for EventEmitterTrait.
2348475
to
1f3ef66
Compare
It was a mistake to include cache data. This change removes the cache data from the symfony event. And hence the listener of the event would avail update and oldvalue from the events. Signed-off-by: Sujith H <sharidasan@owncloud.com>
1f3ef66
to
410d503
Compare
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.
👍
@sharidas please backport |
Backport PR: #30937 |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
It was a mistake to include cache data.
This change removes the cache data from the
symfony event. And hence the listener of
the event would avail update and oldvalue
from the events.
Signed-off-by: Sujith H sharidasan@owncloud.com
Description
Remove cache data from the symfony event dispatcher.
Related Issue
Motivation and Context
Remove cache data from the symfony event dispatcher. Its not ideal to expose too much information.
How Has This Been Tested?
Screenshots (if appropriate):
Types of changes
Checklist: