Skip to content

[Cache] Use namespace versioning for backends that dont support clearing by keys #23969

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

Merged
merged 1 commit into from
Aug 31, 2017

Conversation

nicolas-grekas
Copy link
Member

@nicolas-grekas nicolas-grekas commented Aug 24, 2017

Q A
Branch? 3.3
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #23960
License MIT
Doc PR -

@nicolas-grekas nicolas-grekas added this to the 3.3 milestone Aug 24, 2017
@nicolas-grekas nicolas-grekas changed the title [Cache] Use namespace versioning for backends that dont support clear… [Cache] Use namespace versioning for backends that dont support clearing by keys Aug 24, 2017
@nicolas-grekas nicolas-grekas force-pushed the cache-version branch 3 times, most recently from d33fc54 to c15d72e Compare August 24, 2017 06:55
@@ -189,11 +204,18 @@ private function getId($key)
{
CacheItem::validateKey($key);

if ($this->versioningIsEnabled && '' === $this->namespaceVersion) {
Copy link
Member

Choose a reason for hiding this comment

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

Other classes used the trick isset($string[0]) to check if their is a namespace.

Copy link
Member Author

Choose a reason for hiding this comment

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

not sure it applies here

@nicolas-grekas
Copy link
Member Author

with new false positive from php-cs-fixer...

Copy link

@hcomnetworkers hcomnetworkers left a comment

Choose a reason for hiding this comment

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

Looks good!

Although I'm wondering why you put a colon after the namespace while colons are not allowed in validateKey?
(We used to use colons in our cache keys until we switched to the new classes which don't allow it ;)
Also on a side note: Is there any reason why an integer is not allowed as cache key if it gets namespaced anyway? We have/had that, unfortunately.)

@nicolas-grekas
Copy link
Member Author

nicolas-grekas commented Aug 24, 2017

put a colon after the namespace while colons are not allowed in validateKey

I put a colon because they are not allowed when given from the outside. Here, we're past the interface, so the PSR-6/16 constraints do not apply. Which is very nice for us: using a colon makes it impossible to have any confusion with user input.

why an integer is not allowed as cache key

because PSR-6/16 states that a key must be a string. So 6 is not allowed, but "6" is.

@andrerom
Copy link
Contributor

andrerom commented Aug 26, 2017

I'm a bit torn on this, as it adds extra lookup for every lookup. Would it be possible to rather do this on first usage, and afterwards get it using multi get together with the item lookup? Then if version has changed either refetch the items, or in future when there is stale cache support on get we can still return the items when callee indicated it does not need fresh items, however have the new version set for next caller.

If that won't fly, then at least make sure this is only done once on multi get lookus. in current patch here it will be done for every key before lookup on all is done, which I would consider a bug.

@nicolas-grekas
Copy link
Member Author

As the PR is now, the version retrieval is done only once, on first need. That's how Doctrine does it also afaik. Isn't it good enough?

@andrerom
Copy link
Contributor

andrerom commented Aug 26, 2017

Ah, sorry missed that completely. It's fine with me, but you can bet there will be bug report for this down the line for long running processes :)

@nicolas-grekas
Copy link
Member Author

nicolas-grekas commented Aug 27, 2017

there will be bug report for this down the line for long running processes

so, I added a public method to explicitly reset the memoized version, for the long running process use case. This looks much more reasonable to me than fetching the key on every fetch, as even multi-fetch are not always grouped (eg RedisCluster or RedisArray), thus would pay an extra cost at each fetch.

This requires long running processes to do something like that in their main loop:
$pool->enableVersioning() || $pool->enableVersioning(false);

Yes, this is a "new feature" (because a new public method is). Yet, it is required to compensate for a behavior change (long running process don't have their cache cleared anymore). And the behavior change is also technically a BC break. Yet also I think this is a really edge-case one and the issue is at the design level so that it cannot be solved otherwise.

@jderusse
Copy link
Member

A use case for such each case would be to implement a reverse proxy base on ReactPHP (php-pm for instance). With cache invalidation with the clear method.
(I'm not sur it exists and it'd a good idea.. just a brainstorm idea of what could be wrong)

@andrerom
Copy link
Contributor

andrerom commented Aug 27, 2017

Yes, ReactPHP or similar will hit this. But I agree with @nicolas-grekas that main usage should not pay a penalty because of it. One option would be to clearly document handlers/ connection classes that don't support flushing pool and hence not recommended for use with long running php processes such as ReactPHP/cron/script.

@nicolas-grekas
Copy link
Member Author

to clearly document handlers/ connection classes that don't support flushing

well, with this patch, all handlers do support flushing. But for long running processes, the concern leaks, and I have no better reasonable idea to make it not.

So, we would require ppl to call $pool->enableVersioning() on pools that have versioning enabled.
(or call $pool->enableVersioning() || $pool->enableVersioning(false), which works whether versioning is on or not, without changing the versioning-enabled state.)

@fabpot
Copy link
Member

fabpot commented Aug 31, 2017

Thank you @nicolas-grekas.

@fabpot fabpot merged commit f8a7518 into symfony:3.3 Aug 31, 2017
fabpot added a commit that referenced this pull request Aug 31, 2017
…pport clearing by keys (nicolas-grekas)

This PR was merged into the 3.3 branch.

Discussion
----------

[Cache] Use namespace versioning for backends that dont support clearing by keys

| Q             | A
| ------------- | ---
| Branch?       | 3.3
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #23960
| License       | MIT
| Doc PR        | -

Commits
-------

f8a7518 [Cache] Use namespace versioning for backends that dont support clearing by keys
@nicolas-grekas nicolas-grekas deleted the cache-version branch September 1, 2017 06:57
* When versioning is enabled, clearing the cache is atomic and doesn't require listing existing keys to proceed,
* but old keys may need garbage collection and extra round-trips to the back-end are required.
*
* Calling this method also clears the memoized namespace version and thus forces a resynchonization of it.
Copy link
Contributor

@robfrawley robfrawley Sep 1, 2017

Choose a reason for hiding this comment

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

@nicolas-grekas Spelling errors: "memoized" -> "memorized" and "resynchonization" -> "resynchronization"

Copy link
Member

Choose a reason for hiding this comment

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

I reported the "memoized" typo once ... and I was wrong :( "Memoize" seems to be a valid concept: https://en.wikipedia.org/wiki/Memoization Maybe it's used correctly this time too?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah; seems you are correct! I think the latter one is a spelling error though. ;-)

Copy link
Member Author

Choose a reason for hiding this comment

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

I wrote memoize on purpose :)

nicolas-grekas added a commit that referenced this pull request Sep 3, 2017
…k component (jderusse)

This PR was submitted for the 3.4 branch but it was merged into the 3.3 branch instead (closes #23958).

Discussion
----------

[Lock] Fix race condition in tests between cache and lock component

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

Currently trying to fix
* [x] php 5.5 in testSaveWithDifferentResources "Failed asserting that false is true"
* [x] php 5.5 in testSaveWithDifferentKeysOnSameResources "The store shouldn't save the second key"

Workflow:
* [x] find a reproducer
* [x] fix memcached tests => #23969
* [x] fix redis tests => this PR

Commits
-------

26948cf Fix race condition in tests between cache and lock
@fabpot fabpot mentioned this pull request Sep 11, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants