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

Remove cache data from the symfony events #30793

Merged
merged 1 commit into from Mar 27, 2018

Conversation

sharidas
Copy link
Contributor

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

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@sharidas sharidas added this to the development milestone Mar 15, 2018
@sharidas sharidas self-assigned this Mar 15, 2018
@codecov
Copy link

codecov bot commented Mar 15, 2018

Codecov Report

Merging #30793 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@             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
Flag Coverage Δ Complexity Δ
#javascript 52.33% <ø> (ø) 0 <ø> (ø) ⬇️
#phpunit 63.08% <100%> (ø) 18536 <7> (+167) ⬆️
Impacted Files Coverage Δ Complexity Δ
lib/private/AppConfig.php 98.26% <100%> (+0.04%) 29 <7> (+2) ⬆️
lib/private/Config.php 89.9% <100%> (+0.48%) 43 <0> (+1) ⬆️
lib/public/Events/EventEmitterTrait.php 100% <100%> (ø) 8 <0> (+1) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7273799...410d503. Read the comment docs.

'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]
Copy link
Contributor

Choose a reason for hiding this comment

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

why the & sign here ?

Copy link
Contributor Author

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.

Copy link
Contributor

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

Copy link
Contributor Author

@sharidas sharidas Mar 16, 2018

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 &.

Copy link
Contributor

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.

Copy link
Contributor

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 ?

Copy link
Contributor

Choose a reason for hiding this comment

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

@@ -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];
Copy link
Contributor

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 ?

Copy link
Contributor

Choose a reason for hiding this comment

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

other possible approaches:

  1. 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

  1. don't use the emittingCall wrapper and send dispatcher events directly before and after the operation

Copy link
Contributor Author

@sharidas sharidas Mar 19, 2018

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.

Copy link
Contributor Author

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.

@sharidas sharidas force-pushed the remove-cache-from-symfony-event branch 2 times, most recently from a238ba1 to 0b44401 Compare March 19, 2018 08:19
$oldValue = null;

if (isset($this->cache[$app][$key])) {
$oldValue = $this->cache[$app][$key];
Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Contributor

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

Copy link
Contributor Author

@sharidas sharidas Mar 19, 2018

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.

Copy link
Contributor

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) ?

Copy link
Contributor

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 "&&"

Copy link
Contributor

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

Copy link
Contributor

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

Copy link
Contributor Author

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');

Copy link
Contributor Author

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.

@sharidas sharidas force-pushed the remove-cache-from-symfony-event branch 3 times, most recently from 2348475 to 1f3ef66 Compare March 19, 2018 13:46
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>
Copy link
Contributor

@PVince81 PVince81 left a comment

Choose a reason for hiding this comment

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

👍

@PVince81 PVince81 merged commit f9dd178 into master Mar 27, 2018
@PVince81 PVince81 deleted the remove-cache-from-symfony-event branch March 27, 2018 13:34
@PVince81
Copy link
Contributor

@sharidas please backport

@sharidas
Copy link
Contributor Author

Backport PR: #30937

@lock
Copy link

lock bot commented Jul 31, 2019

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.

@lock lock bot locked as resolved and limited conversation to collaborators Jul 31, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants