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

Multi Get support for Second Level Cache #954

Closed
wants to merge 9 commits into from

Conversation

goetas
Copy link
Member

@goetas goetas commented Feb 14, 2014

Hi!
As discussed here i have implemented some kind of multi-get for second level cache implementation.

I have also created a PR to doctrine/cache component (see doctrine/cache#29) that enables this feature at driver cache level.

@doctrinebot
Copy link

Hello,

thank you for creating this pull request. I have automatically opened an issue
on our Jira Bug Tracker for you. See the issue link:

http://www.doctrine-project.org/jira/browse/DDC-2982

We use Jira to track the state of pull requests and the versions they got
included in.

@goetas
Copy link
Member Author

goetas commented Feb 14, 2014

I have not added tests yet because i think that it has to be discussed...

@FabioBatSilva
Copy link
Member

I'd like to suggest Doctrine\ORM\Cache\Region\DefaultMultiGetRegion and Doctrine\ORM\Cache\MultiGetCollectionHydrator

That will remove the instanceof logic from DefaultCollectionHydrator and keep DefaultGetRegion simple..

@goetas
Copy link
Member Author

goetas commented Feb 14, 2014

@FabioBatSilva ok, but then have i to edit DefaultCacheFactory::getRegion() wrapping a default impl?

@goetas
Copy link
Member Author

goetas commented Feb 14, 2014

@FabioBatSilva
Question: i have seen that you have used everywhere Doctrine\Common\Cache\CacheProvider as dependency from docrine/cache...
Why not use just Doctrine\Common\Cache\Cache? It is an interface... (deps on interfaces are better...)

@goetas
Copy link
Member Author

goetas commented Feb 14, 2014

@FabioBatSilva i do not understand how to implement DefaultCollectionHydrator... i have to check aniway if $targetRegion is instanceof MultiGetRegion...

@FabioBatSilva
Copy link
Member

It depends on CacheProvider because cache regions use flushAll which is not part of Cache
But in reality only concrete implementations know about Common\Cache, you could have a different implementations that uses wherever cache provider you want..

For the MultiGetCollectionHydrator I think u need to wrap DefaultCacheFactory#buildCollectionHydrator and check the region to decide which implementation will be used..

@goetas
Copy link
Member Author

goetas commented Feb 17, 2014

I'm not sure to use inheritance over composition inside DefaultMultiGetRegion...

@skydiablo
Copy link

some proceedings ?

@goetas
Copy link
Member Author

goetas commented Jun 14, 2014

at the moment i'm very busy... :-(

@Ocramius
Copy link
Member

@goetas since doctrine/cache#29 is fixed, could you eventually complete this PR next week, so that we can throw it in the final 2.5 release? (probably doing it while at PHPBNL15)

@Ocramius Ocramius self-assigned this Jan 15, 2015
@goetas
Copy link
Member Author

goetas commented Jan 16, 2015

@Ocramius i can to look at this this evening or on tomorrow....!

if ($mapping['cache']) {
$targetPersister = $em->getUnitOfWork()->getEntityPersister($mapping['targetEntity']);

if ($targetPersister instanceof CachedPersister) {
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 really hate this nested if... but I do not know why $em->getUnitOfWork()->getEntityPersister($mapping['targetEntity']); somtimes seems to be instance of BasicEntityPersister.... and not a cache persister as expected...

Copy link
Member

Choose a reason for hiding this comment

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

Ping @guilhermeblanco about this

Copy link
Member Author

Choose a reason for hiding this comment

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

found that one!
I don not know why but Doctrine\Tests\Models\CMS\CmsUser::$articles is marked as cacheable (but CmsArticle is not!)... and this is the only failing test case

@goetas
Copy link
Member Author

goetas commented Jan 16, 2015

@Ocramius rebased and tested (a bit)

@Ocramius
Copy link
Member

Thanks @goetas. I'm stuck on another PR and the current build failure, but I'll get to this one tonight, hopefully.

* @since 2.5
* @author Asmir Mustafic
*/
interface MultiGetRegion extends Region
Copy link
Member

Choose a reason for hiding this comment

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

Don't extend from larger interfaces unless strictly needed

Copy link
Member Author

Choose a reason for hiding this comment

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

Does it make sense? A MultiGetRegion region is always a region. Of course, the new interface is much simpler, but can it be used alone? I can not imagine a use case.

@Ocramius
Copy link
Member

This PR should introduce a dependency to "doctrine/cache": "~1.4"

$targetRegion = $targetPersister->getCacheRegion();

if ($targetRegion instanceof MultiGetRegion) {
return new MultiGetCollectionHydrator($em);
Copy link
Member

Choose a reason for hiding this comment

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

The multi-get region is not being passed to the MultiGetCollectionHydrator? You are doing a lot of checks but discarding a lot of dependencies then: is it intended to be like that?

Copy link
Member Author

Choose a reason for hiding this comment

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

With the first version I was re-building the multi-get region on each loadCacheEntry :-( , while now I pass it as a constructor argument.

Your suggestion makes it simpler and faster, thanks! :-)

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 have "fixed" this problem with goetas@e5ee538 but i think that is not the right solution...

Copy link
Member Author

Choose a reason for hiding this comment

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

@Ocramius what about this?

@@ -202,7 +218,11 @@ public function getRegion(array $cache)

$cacheAdapter->setNamespace($cache['region']);

$region = new DefaultRegion($cache['region'], $cacheAdapter, $this->regionsConfig->getLifetime($cache['region']));
if ($cacheAdapter instanceof MultiGetCache) {
Copy link
Member

Choose a reason for hiding this comment

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

$region = ($cacheAdapter instanceof MultiGetCache)
    ? new DefaultMultiGetRegion($cache['region'], $cacheAdapter, $this->regionsConfig->getLifetime($cache['region']))
    : new DefaultRegion($cache['region'], $cacheAdapter, $this->regionsConfig->getLifetime($cache['region']));

@goetas
Copy link
Member Author

goetas commented Jan 17, 2015

@guilhermeblanco I've tried to implement buildCacheEntry in the way as suggested by you

@goetas
Copy link
Member Author

goetas commented Jan 17, 2015

@guilhermeblanco solved the [bug](goetas@0b57935#diff-408359faa7db56dc64cf1f0b2006625dL8%5D! :-)

Versioned classes can't be cacheable as associations....

/cc @Ocramius

Ocramius added a commit that referenced this pull request Jan 17, 2015
…eed to segregate the interface here)
Ocramius added a commit that referenced this pull request Jan 17, 2015
Ocramius added a commit that referenced this pull request Jan 17, 2015
Ocramius added a commit that referenced this pull request Jan 17, 2015
Ocramius added a commit that referenced this pull request Jan 17, 2015
Ocramius added a commit that referenced this pull request Jan 17, 2015
Ocramius added a commit that referenced this pull request Jan 17, 2015
@Ocramius Ocramius closed this in 4cde35d Jan 17, 2015
@Ocramius
Copy link
Member

Merged after applying following changes:

  • DefaultRegionFactory now accepts generic Doctrine\Common\Cache\Cache
  • DefaultRegionFactory builds a MultiGetRegion when the given cache adapter is a MultiGetCache
  • DefaultRegion now operates just with a Doctrine\Common\Cache\Cache, evictAll will throw an exception if the cache instance is not a FlushableCache
  • DefaultRegionFactory sets the cache namespace only if a CacheProvider is given
  • Region now extends MultiGetRegion (breaking change, but we didn't yet release SLC, so it's fine)

The SRP violation of Region being a child of MultiGetRegion is negligible, IMO, as it is trivial to provide a generic polyfill for the getMultiple implementation

master: 4cde35d

@Ocramius
Copy link
Member

Thanks @goetas!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants