Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
cache system
Priority:
Major
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Anonymous (not verified)
Created:
30 Aug 2012 at 23:58 UTC
Updated:
21 Sep 2021 at 20:46 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
sunThanks! :)
Comment #2
Crell commentedTo address a point catch made in the prior issue, yes, passing in a DB object or calling Database::getConnection() once in the constructor means that you will be unaffected by db_set_active(). However, unlike catch I do not see that as a problem. Rather, I see it as one of the main reasons we SHOULD switch to injected connection objects, so that the database you're writing to in a cache object or CMI object does not change out from under you unexpectedly. That is, it's not a bug, but a feature, and all the more reason we should be making this switch.
Comment #3
chx commentedFor a taste of things to come: http://privatepaste.com/3c917bb5ea. That patch has a small problem: simpletest when batching messes up the parent site :P otherwise, tests pass.
Comment #4
Anonymous (not verified) commentedyeah, i agree with Crell in #2 on this. and nothing about making the cache system use DI will stop implementations that want a 'smart' db connection that can point at different targets, or an implementation that takes two (one master, one slave) db connections, etc.
in both of those cases it would be explicit, not magic like it is now.
Comment #5
Anonymous (not verified) commentedsorry, didn't mean to unassign, cross post.
Comment #6
gddReassinging
Comment #7
chx commentedBurn bot, burn! katbailey pointed out (thanks!) that it'd be (much) nicer to use tagged services instead of this weird string magick I am doing for cache_backends(). Next version. I am sure there will be a next version.
Comment #9
Anonymous (not verified) commentedjust wanted to point out #1766186: Move test prefix $databases munging earlier in the bootstrap, which touches on when we munge $databases, and #1597696: Consider whether HttpCache offers any significant benefit over the existing page cache.
not counterposing any of this, just making sure the right people see the issues.
Comment #10
chx commentedThis patches the installer too. Most of the hocus-pocus in the installer cache backend is just gone. When we have a database we switch to the database backend. That's easy because cache() no longer static caches anything. Why would it? drupal_container() does. In drupal_container() we trust.
Comment #12
sunAny chance to introduce a proper CacheFactory here?
(coming from #1702080-37: Introduce canonical FileStorage + (regular) cache)
Comment #13
pounard@sun What do you mean by CacheFactory?
Comment #14
catchCross-linking #1759152: Add a database service to the DIC - once that's done there's no reason to worry about having a db connection class property any longer.
Comment #15
catchmsonnabaum brought up a good point in another issue that if something like the database backend only exists to call the database, then we don't have to inject the database connection, so we could presumably use the
Databasefactory directly with no functional change and it's not ever going to affect unit testing in practice (if we unit test the database backend, we won't want to mock the Database class). That seems reasonable to me and might make this simpler.Comment #16
Crell commentedAs the database maintainer I 100% oppose putting the db_() functions or Database:: static class directly into injectable objects. They were written as utility wrappers only for a reason. They rely on the "active connection" concept, which we are already talking about removing as it doesn't make sense in an injected world. I'd like to see the static Database class go away entirely, in fact, and become a DB manager object in the DIC.
It saves a few function calls, too. And avoids "is the function available yet?" questions entirely. And doesn't make people who do follow a properly injected design laugh at Drupal. And we can make the table name injectable very easily.
See the new routing code for an example. The PathMatcher doesn't work on anything but the database, yet it's an injected object, as it should be.
Comment #17
berdirMoving the database service down to bootstrap.inc means that I can also solve the problems I'm having in #1547008-32: Replace Update's cache system with the (expirable) key value store and #512026: Move $form_state storage from cache to new state/key-value system. Yay!
So this means that provide a different cache implementation, you have to do smething like this in settings.php?
Adding an example for that to default.settings.php might not be a bad idea? or do we leave that to document to the modules providing cache backends as we currently do?
Will try to re-roll this one, might get too late today, though.
Comment #18
berdirRe-rolled against latest HEAD.
There is now a CacheFactory but we can't really use it. The problem is that we can't put the dynamic $container->has() code inside CacheFactory because that results in an endless loop, obviously.
So what I did right now is define a hardcoded cache.config service and am ignoring CacheFactory for the moment. The problem is that you would need to explicitly override that cache backend, it's not enough to just register('cache').
We could directly register the cache factory in the DIC only and call it like this: drupal_container()->get('cache')->bin($bin). cache() would wrap that and we could also pass it as a reference. A service that needs cache then would just need to know that he receives a factory and not an actual cache. That essentially does mean that we're back at the use of $conf['cache_classes'] and can't do the fancy $container->has('cache.$bin') anymore, though.
Wondering where we're at with the tests and if I messed this up.
Comment #20
berdirRemoved the duplicated Reference use statement.
Comment #22
fabianx commented#20: update-dic-1764474-20.patch queued for re-testing.
Comment #24
chx commentedComment #25
Crell commentedBerdir: What is wrong with just having cache.$bin service IDs, and injecting that from the DIC? For something as simple as cache that should be fine.
Comment #26
berdir@Crell: i don't know the DIC that well, but wouldn't that mean that we explicitly have to specificy all bins? Right now, we have a fallback mechanism that checks if cache.bootstrap is defined explicitly if you request cache('bootstrap') and if not, falls back to cache.
If we can't do that, then somone who wants to use memcache by default would have to specify every single cache bin, and there are a lot. (13 currently, and entitycache in 7.x uses a bin per entity type).
Is there a way to bake that fallback logic directly into the DIC? Because it only works when you call cache(), you can't use a new Reference() with the current code.
Comment #27
berdirOk, let's see if this fixes the installer.
I found an interesting installer bug, when the installer is able to create the settings.php then he doesn't explicitly check for readability but then displays an error if it's not TRUE. So on the first request, we always get a requirement error and it works after a refresh.
Doesn't have to do with this issue as far as I can see, so will open a separate issue for that, if there isn't one already.
Comment #29
chx commentedA) It should be possible to extend ContainerBuilder to support wildcard service registrations. Whether this is a good idea I have no idea. As an idea, here's Container::get extended to wildcards http://privatepaste.com/4abdc2c8ec . Who knows, it might actually work as an extension of ContainerBuilder too.
B). I am surprised #1167144: Make cache backends responsible for their own storage is not linked. That seems relevant / necessary if we dont want A).
Comment #30
berdirDiscussed with chx in IRC, one possible solution might be a CacheFactory that works with a cache bin -> service map, which should be relatively easy to extend and doesn't need to know what it needs to invoke a certain backend. The main requirement there is to ensure that backends can switch the bin at runtime, without getting confused about tags and stuff.
Anyway, first step is getting the tests working. Let's see what the current patch does. Fixed some things I messed up when merging and also updated some conversions. Had to add a try/catch to delete() because that was invoked during install time within a test where maintance mode isn't defined.
I can no*w* run tests locally both with run-tests.php and in the UI.
Edit: I can now run test, not I can not run tests...
Comment #32
berdirFixed the tests and broken the installer. This time it's probably the other way round :p
Comment #34
berdirHad to restore the original InstallBackend, I'm not sure if it's actually required but there is a test that does explicitly test how it's supposed to work. Can probably be simplified a bit, by e.g. testing if $this->dbConnection is set but I didn't wanted to change too much.
Also completely messed up cache validation, copy pasted into the wrong function, that's why the other tests failed.
Comment #36
berdirAnd... fixing the installer!
Comment #38
berdirMore installer fixing. This seems to work manually, not sure why it's necessary.
Comment #39
cosmicdreams commentedThis is as far as I could get before having to switch away from this task. These are mostly code readibility notes. shouldn't change status of issue.
part 1: is this change for readibility? this combined with part 2 completes an unnecessary change as it doesn't make much of an impact.
Are you trying to make the DRUPAL_BOOTSTRAP_DATABASE condition earlier because it is selected from the switch more often than DRUPAL_BOOTSTRAP_PAGE_CACHE?
part 2
I realize this is a continuation of the syntax that was there before, but to me this reads as there is more than one default database. Just wanted to point out that's difficult to follow unless you know the anatomy of the settings.php file pretty well.
Perhaps this a personal preference but I think it would be more readible if these were unchained.
$container->get($service) seems to return on an object that has a "bin" method or property. But someone who doesn't know drupal_container intimately may assume that "bin" is a method or property of drupal_container instead.
breaking up the chain of these object calls may go a long way to help folks get ramped up on these functions.
Comment #40
pounardbin() should be exploded into setBin() and getBin() for readability and consistency. Aside of that the patch sounds going into the right direction, I especially like the database connection injected into the database backend. I'm still a bit concern about easyness of overiding backend implementations if they are injected into the DIC.
EDIT: Typo fixes only.
Comment #41
berdirOk, here is a new patch. Let's see if this will pass the tests. For the record, our installer is a very fragile thing, did cost me some nerves...
Changes:
- Now registers cache.factory and cache.default in the DIC
- This makes it possible to inject the database service into the database backend, without having to do that in the cache factory
- The Cache Factory uses a bin => service mapping that allows to use different services for different backends.
- Renamed bin() to setBin(), not chained anymore
- Removed caching for the moment. It's not much more than a call to the DIC and there are ~25-30 of them on a front page with some content. Feels strange to have caching there when there are hundreds of calls through language() without.
Note: The same service is currently re-used for multiple backends, and is switched on run time. This is nice but I'm not sure if it's possible. Consider this code:
So we probably can't do this, not sure how to solve it yet.We could re-introduce caching and clone them or something like that.
@cosmicdreams: I'm not sure why that code was moved, was part of the original patches from chx, maybe to have it consistent with the order in which it is called? Likely not relevant to this issue but this is still in stage "figuring out what's possible" and not "getting it ready for being commited", so not worrying about stuff like that too much atm :)
Comment #42
berdirComment #44
Crell commentedIf I'm reading the patch correctly, I think Berdir's sample code at the end of #41 is exactly why it won't work. :-) Having an object you get back from the DIC randomly change out from under you is a show-stopper, especially when you consider that we want to not be using cache() all the time but injecting the cache object as a dependency to other objects.
I really don't see an issue with having a separate instantiated object for each bin, though, so I don't understand why it should be an issue. The number of bins never gets all that large, or if it does you're doing something wrong. Why exactly are you allowing the bin of a cache object to change after it's been instantiated? That is the part that strikes me as "eeek, run away!!"
Comment #45
berdirYes, yes, that is mostly why the patch failed :) cache.config is now used like that and falls apart.
The problem is, it's not that easy, there are at least three reasons that make "Let's just register every cache bin as a service in the DIC" problematic:
- There are quite a few cache bins, in fact. Core alone has 13 (cache_update and cache_locale don't really con't and will be replaced by KV, so 11). A 7.x site that I'm working on has 25.
- Configurability. If we register every single bin, does that mean that memcache has to override each of them explicitly?
- Even if we wanted to register all of them, we can't. We don't *know* which cache bins exist. Yes, there is an issue that will register them in a hook, but hooks aren't available when we want register them?
One approach that I'm currently trying is using the service as a "template object", clone it for each bin when requested and store these in the factory. We could also store them in the container using set() but I don't know if that will work after it's been compiled to the disk?
Comment #46
Crell commented25 cache bins sounds to me like "you're doing something wrong". Really, that's a red flag to me.
I'd presume that a module that says "I need a foo cache bin" would register a cache.foo service, and then it knows that service is there and will start calling it. Other modules that don't know about that module would not know about cache.foo, nor should they even care. If they care, that's a bug.
If you're swapping out a given bin for memcache, then you know the bin exists so you know to replace it.
I really don't think cache bins are or should be as fluid as we are trying to make them. :-)
Comment #47
berdir25 cache bins is the obvious result of the current situation, we only have per-module cache bins, with some exceptions. So each contrib module that needs to store more than a few entries currently defines it's own bin because there is no existing one that it could use. #1194136: Re-organise core cache bins tries to change that by introducing more
The thing is that we have a lot of interdependencies between these issues. To get the number of cache bins down, we for example need to move cache_update to KV, but that needs the database changes contained in this issue and so on. So in case we get somehow blocked here, we could consider moving that into a separate issue and get it in, to solve the deadlock :)
I'm really unsure about the configurability of cache bins. Right now, it's easy to specifiy that Memcache should be used by default by setting two variables in settings.php. If we make it explicit, you would need to check after each installed module if there's a new bin provided by it and update the configuration. Also, I'm not sure about the order, given that mymodule would register cache.mymodule in MymoduleBundle. Maybe there could be a default service configuration and some helper code?
Will continue later with this, have some code that I'm still working on.
Comment #48
pounardHum I have to agree with both Crell and Berdir, in one side I'd prefer to do a direct registration of all bins into the DIC and keep out the factory, but in another I'd like to keep the factory because it could help building some workaround like returning null implementations when database is not active.
Comment #49
catchYes it's currently possible to register a backend as the default for all cache bins site-wide, because the cache backend configuration is static, whereas the cache bins themselves are dynamic.
There's no way to get a list of all cache bins without invoking hook_flush_caches(). #1167144: Make cache backends responsible for their own storage would encapsulate that hook a bit but doesn't fix any of the problems here.
If we go in any direction I'd prefer to see the cache bins be less dynamic and the cache configuration stay static, not the other way 'round (because that'd mean writing to cache configuration on module enable/disable automatically which just feels fragile).
Does registering the cache bins separately mean that we'd have to instantiate a real connection with the backends each time? Something like cache_mymodule might not ever be used during a request and if I have a memcache bin set up separately for it for some reason I'd not want that overhead if it's not going to be used during the request.
Comment #50
Crell commentedcatch: If we go all the way to a factory-less cache.page, cache.filter, etc. registration straight on the DIC, no. If cache.filter is backed by memcache, and memcache is a service in the DIC, then the first time you request cache.filter the DIC will notice that it depends on the "memcache" service ID and instantiate that, then pass that to the constructor of the class wired into cache.filter. If you never request cache.filter, then it never causes the "memcache" service to initialize. (Unless some other service asks for it, of course.)
Comment #51
berdirOk. Here is a patch that explicitly registers every bin that we could possibly use. Currently doing this in a loop in bootstrap.inc, non-system.module bins would need to be moved to $moduleBundle.
What's totally not clear to me is how to override this to use Memcache for all bins.
For the ones directly registered in drupal_container(), we could use drupal_container()->register('cache', '...'). But I totally don't get yet how that would work for those defined in moduleBundle because that is invoked after settings.php?
Any pointers are welcome.
Comment #53
berdirFixed the InstallBackend and the upgrade tests. update.php really calls cache('update') ? Weird, it shouldn't do that IMHO, could lead to more of the ugly fetch task queue duplicates...
Comment #54
pounardIt's even weirder to replace it by a direct table truncate, it should remain a cache() call instead. A lot of other cache() calls will happen during various installation tasks.
Comment #55
berdirNo, cache_update is not a cache. Among other things, it contains fetch_task entries which are used to prevent duplicate queue items. Deleting them means we create duplicate fetch records. So the truncate is just as wrong, that is correct. I think we might be able to remove it completely, because update.module has a special implementation of hook_cache_flush() that deletes stuff on update.php runs. Not sure why this is duplicated.
I've explicitly not registered cache.update as a cache backend service, that's why it failed, not because it's called on update.php.
I'm converting cache_update to the key value storage in another issue but that issue needs this one to be able to use the database in early bootstrap.
Comment #56
pounardOh right, forgot that one, it's not a cache... Yes so you're right here sorry for the noise.
Comment #57
chx commentedExplicit registration++
I suggest, however, in CoreBundle:
Adding another $bin:
The $container->has() would allow, eventually, for overrides.
Comment #58
pounardWhat the real benefit of cloning the entry VS. explicitely registering it with the database reference? It makes it less readable, especially with the replaceArgument and all.
Comment #59
berdirWe can probably explicitly register as well. We also discussed about using tags (definitions can have tags) to identify cache bins instead of looking through the ids), so the default definition might get a bit bigger, but we could wrap this thing in a helper function and then it doesn't really matter if it's a clone or not for those using it.
Comment #60
pounardYep that was a minor detail, tags is a good idea indeed, we could get rid of cache backends reference in the factory and use it for retrieval for cache clear all or tags clearing operations.
Comment #61
Crell commentedI like the sound of #57, but then we'd likely want to reverse the parameter order so the bin is the first constructor argument, always. That way if you have a cache implementation that needs 2 or more additional parameters, the position of the bin name argument doesn't change. That's an easy fix.
Tagging cache services sounds sensible, too, and in fact may serve as a replacement for #1167144: Make cache backends responsible for their own storage
I'm liking this.
Comment #62
pounardAgree with #61, we could imagine something like this:
* Register the default cache backend like any other component in the DIC
* Tag it in the kernel
* chx's idea is not that bad even if I'd prefer people to set their own definition: in anyway document that all registered cache bins must be tagged
* Generalize use of the tag for fetching backend list instead of the #1167144: Make cache backends responsible for their own storage
* Document how to override the class used for a specific bin
* Expose onto the factory various methods such as flush, flush tags, and potentially a list helper
* Remove from the factory any other code
Pros:
* Get rid of a yet another hook
* Every feature we need here DIC is already capable of doing it
* Untangle the factory from procedural code (removes the varialbe_get() of #1772682: Remove the variable_get inline in CacheFactory::getBackends
* Everything gets compiled
* Hardcoded list of bins easily retrive-able for various operations (flush, tags flush and UI listings)
* Fix all the procedural wrappers to use that
Cons:
* Less easy to understand maybe, but people generally know how to read documentation
* Uneasy to set a "default" class
* If people don't know how to read documentation, we'd have to find a way to move this out of hardcoded bundle registration and set those into a config file for override (sounds like a "Pros" in the end) used before compile if found
* Not a Drupalism :) (I should have put this in the "Pros" category)
Comment #63
berdirOk, here is a new patch.
- Changes: Uses an adapted version of chx's code to define the non-bootstrap bins in CoreBundle. Currently all definitions are still created in CoreBundle, we can move them to per-module bundles once we agreed on the exact syntax. Also note that I'm working on generalizing the cache bin names so that we can get rid of module-specific bins in Core (except cache_test :p), so they will in fact go back to CoreBundle, see #1194136: Re-organise core cache bins.
- Using the first argument for the bin, as Crell suggested. To enforce this, we would have to make a separate set method in the interface for this as we don't want to explicitly define the
- Using tags to identify cache services.
- Using the correct query copied from update.authorize.inc to flush update.module caches in update.php. I think this is actually a separate bug and this change should be backported to 7.x as well.
- No helper function to use the clone trick to define the cache backend, Crell almost beheaded me as he heard me adding a function :)
Notes:
- It's not exactly nice, but it's actually possible with this code to properly override cache bins in settings.php. The following example has been tested and works as expected:
- While testing the above configuration, I found an interesting bug. The database is now solely configured through the DIC. If the first request does not go through DatabaseBackend but e.g. db_query() then the Database never receives the necessary connection information and the site explodes. Discussed with Crell and we agreed this can be solved in a separate issue as the Database class should be refactored a bit anyway to make it easier to embed it into the DIC.
- While we could throw out the default/clone stuff and rely on explicit overwrites only if people don't like that, we at least need to keep the !$container->has() check IMHO or it is impossible to overwrite cache bins from settings.php. Having to add a module with a bundle class, making sure that it has a high weight and so on is IMHO the wrong approach, considering that this is environment-specific configuration.
Comment #65
pounardHere is PoC I was working on during the time you wrote yours:
* Took your previous patch as base.
* Added the tags, and added a CacheManager object for iterating over.
* Followed http://symfony.com/doc/2.0/components/dependency_injection/tags.html and added a compiler pass for registering bins in a container parameter.
Comment #66
pounardIf you interdiff both you'll see I didn't edit any of your code, just added tags, the compiler pass, the cachemanager object, and their respective registration.
Comment #67
katbailey commentedI think tagged services and a compiler pass are definitely the way to go here, and I have a feeling there are several other places this pattern could be made use of. The problem is we can't use compiler passes until #1706064: Compile the Injection Container to disk gets in - I will try to at least get that patch green again tomorrow.
Comment #68
berdirForgot to switch the arguments in install.core.inc. This should do better.
@pounard: That code looks interesting, but currently dies with "Fatal error: Class 'Symfony\Component\Config\Resource\FileResource' not found", probably because of what katbailey said in #67. I merged it with my latest code and have it in a separate local branch, so I can re-add it once it can work.
Comment #70
pounard@Berdir, I just didn't tested the code, because since a recent commit no D8 will install on my box (even unpatched) and I can't figure out why. It seems it's because of early registration of CMI stuff...
You shouldn't experience this error, I think this is due to a missing use statement, maybe, but written correctly it should work!
@katbailey Compiler passes are supposed to work even if not compiled I thought? I mean, it's slower but behavior shouldn't change with or without compilation since we already are using all the compilation ready tooling, or I am wrong here?
EDIT: Re @Berdir I saw a lot of install stuff being patched, I think we can make it less invasive regarding the DIC by building a DIC with scopes ("config-ready", "database-ready", "system-ready" and "request"): each scope defines components, until the database is not ready cache are null implementations, and after database ready the DIC overrides itself by entering the "database-ready" scope which overrides the previous definitions and makes normal cache available. This allows to have one single big bundle for Core, and may help removing the drupal_container() custom container which sounds heretic IMO.
Comment #71
berdir@pounard The DependencyInjection container relies partially on Symfony's Config component, which we don't use/have. Looks like this compiler pass stuff is one of the things that do rely on it. In a quite hardcoded way (new FileResource()) Looks like the Dependency injection container does not follow the dependency injection rules :p
Still working on this. The cache.field error is because run-tests.sh is not booting a Kernel and then tries to invoke hooks, which rely on stuff that is registered in CoreBundle, then it breaks. That can be easy fixed but after that, I'm getting a very weird behavior in module.inc, config('system.module')->get('enabled') returns NULL instead of the enabled modules. Haven't figured this out yet, any pointers would be appreciated.
Comment #72
berdirOh, didn't mean to change the status.
Comment #73
pounard@Berdir Ok, I understand, this is bad for we'll have to use the Config component or write a compatible null implementation. Drupal 9 will be SF2 full stack I guess ^^
Comment #74
pounard@Berdir the config('system.module')->get('enabled') must happen either because:
* Site is not fully installed yet, and this shouldn't be called OR
* #1608842: Replace list of bootstrap modules, enabled modules, enabled themes, and default theme with config introduced bugs
You should ask sun for this.
Comment #75
berdirThe failure only happens after the test execution, after the (static) caches have been emptied and the function is called again. Something seem to go sideways there, not sure yet if there's something wrong with this patch or this patch just exposes it.
Comment #76
katbailey commented@pounard yes, compilation means two things - running compiler passes and compiling to php. We had the former working without the Config component but it was deemed not performant enough until we get the latter in. #1706064: Compile the Injection Container to disk deals with both of these aspects of "compilation".
Comment #77
pounard@katbailey My question was more: even if not compiled to disk, the behavior should not change and the compiler pass should run, right? As soon as we are building a ContainerBuilder the pass should be runtoo? If not, I don't know how SF developers can debug their own apps since the compilation passes oftenly add business related stuff which are mandatory for the app to run.
Comment #78
katbailey commented@pounard see this line here: http://drupalcode.org/project/drupal.git/blob/refs/heads/8.x:/core/lib/D...
No compiler passes are being run - which is why all the event subscribers are being instantiated and added to the dispatcher instead of being added as tagged services and using a compiler pass:
http://drupalcode.org/project/drupal.git/blob/refs/heads/8.x:/core/lib/D...
Comment #79
berdirFigured it out, I have to move the container above the module_list_reset() call in TestBase::tearDown(). A bit confused by the duplicate reset calls in TestBase and WebTestBase but that's not relevant here.
Let's see if this gets us back on track.
Comment #81
berdirOk, had to move the page bin to drupal_container() and pretty much all bins that we have to update.php to get the upgrade tests working. On the other side, was able to remove the test bin because that is just used a direct argument to DatabaseBackend()/InstallBackend().
Let's see if any test fails remain.
Comment #83
berdirAdding more bandaids to get the upgrade tests working. UpgradePathTestBase is ugly...
Comment #85
Crell commentedStrictly speaking, if we're changing the order of these phases their numbers should change, too.
Can we put this somewhere other than a function? If the CacheFactory class still exists that might be a good place. Or, it's a one liner, just don't bother with it. Really, I would just not bother with it. :-) cache_invalidate() has to call drupal_container() anyway for now.
I'm unclear why the InstallBackend is doing this, but then I've never really understood why the InstallBackend extends DatabaseBackend rather than just being a null implementation. Why do we need two static calls in what should be a noop implementation?
$database_info should have a description. You can probably steal some existing docs from somewhere. Or just reference settings.php.
I should note this is not the final state we want to have for the DB, but I'm OK with this approach for now. We can/should refactor later.
There's no need to call drupal_container() multiple times. Just call it once, save the $container variable, and call it a few times.
I'm in nitpicking mode now, I think. The overall approach is IMO solid. Berdir++
Comment #86
berdirThanks for the review.
- Fixed the remaining exceptions, had to move the container restore above the static reset call. That one seriously results in a system_list() call, through __destruct() functions of the cache array class.
- Changed value of those constants.
- merged cache_backends() into cache_invalidate().
- Not sure what to do with InstallBackend. AFAIK, we can *not* replace it with NullBackend, because it needs to do those cache clears if it can. We could possibly inject the database there conditionally as well, to keep the logic of that outside of the class and avoid functions calls. Will do that when this patch is green again.
- Changed the duplicate calls to drupal_container(). Not happy with the messy situation in the upgrade tests.
Comment #87
fubhy commentedThe problem with the NullBackend is for a different issue. For me, the NullBackend is an EXTREMELY ugly workaround. It should definitely use NullBackend at some point but due to the current behavior of the installer that's not yet possible. What the installer backend basically does AFAIK is: It clears the database cache entries that were produced as a result of AJAX callbacks that are already using the normal DatabaseBackend during the batch process. If that's not fucked up then I don't know... :P
Comment #89
berdirYeah, the renumbering actually broke stuff. Reverted that and also the changed order within the switch, that does not have any effects anyway.
Comment #90
pounard@Berdir The
findTaggedServiceIds()method is not available on the ContainerInterface, it is only available on the ContainerBuilder specific implementation: this is why the compilation pass is mandatory for this to work. If you use it outside of a compiler pass you are violating the interface contract and making the code fragile.Comment #91
podarokIs there any reason to make this array hardcoded?
Possibly we should make it configurable via yml ?
Or may be I`d missing something here ;(
Comment #92
fubhy commentedCMI has a dependency on the cache API. So we can't use CMI anywhere there.
Comment #93
berdirThis is the hardcoded list of cache bins that are required in early bootstrap. Modules can define their own bins in a bundle class.
You can see that the other ones are defined in CoreBundle currently #1194136: Re-organise core cache bins will reduce the amount of bins we have in Core and, instead of specific per-module bins, introduces generic bins that can be re-used by othe rmodules, which should eliminate the need for custom bins in most cases.
Comment #94
podarokwith this can we replace it via settings.php ?
Comment #95
podarokwoops
Comment #96
pounardI'm not sure this would make sense: bins are registered by modules that will explicitely use it (hardcoded bin names) and I'm not sure we have any use of having a "dynamic user bin registration" feature: if the site admin adds bins in there, they probably will remain unused forever or conflict with already registered module bins.
Comment #97
chx commentedThere's nothing user facing in this patch nor is it advocated. What is advocated is that overriding the default cache changes everything and for that reason I would to see the bootstrap container to use the getDefinition pattern as well.
Comment #98
pounardI was speaking about settings.php.
Comment #99
sunThe question on settings.php is valid. It's not about registration of cache bins, but about specifying which backend to use for which cache bin.
This patch seems to hard-code the database backend for all cache bins, unless I'm missing something big (unlikely, but possible). So the overly simple question is:
What do I put in my settings.php to make Drupal use APC for all cache bins?
Right now, all I need to do is this:
(Test yourself with #1807662: Built-in APCu support in core (PHP 5.5 only) ;))
Comment #100
pounardI definitely agree we need a configuration entry for setting those backends, but the psuedo code written upper doesn't relate this need.
Comment #101
berdir@chx: Using getDefinition() does not help there. getDefinition() only helps if settings.php has a chance to replace the default cache bin definition before those bins are added. That's not the case for those defined in drupal_container().
#63 has an example how this can be configured. Yes, it is more complicated than what we currently have. We might be able to simplify it a bit by looping over the backends but as @pounard said, it's not save to use findTaggedServices() outside of a compiler pass thingy, so as soon as we do the compilation, it won't work anymore.
Comment #102
pounardYep, the SF2 documentation gives a very good example with tag handling, we should tie to this method.
Comment #103
berdirOk, here is an update.
- Passing the database to InstallBackend if available, so moving that logic outside of the class. Note that there is an important difference in any patch in this issue (not just this one) for the InstallBackend. It does not act if the database becomes available during request, only if available initially. Not sure if that is a problem, might be?
- Updated the documentation in CacheBackendInterface. Quite outdated stuff in there, e.g. non PSR-0 example class names.
- Added all cache bins to UpgradePathTestBase, removing one-off registrations from subclasses. This is the same behavior as we have in update.php too, so I think this makes sense. Also standardized all cases to use clone getDefinition().
- Some general cleanup and improvements.
Let's see if I introduced any bugs with this.
Comment #105
podarok#103: cache-dic-1764474-103.patch queued for re-testing.
Comment #107
podarok#103: cache-dic-1764474-103.patch queued for re-testing.
Comment #109
podaroksomething wrong with a bot?
Comment #110
berdirNo, the patch is.
The installer is crazy, the actual error is usually hidden below two meaningless errors, because trying to display the error results in a dependency injection exception and then trying to handle that exception results in yet another one.
Comment #112
berdirForgot to add the use statement. Also removed some debug code that I left in there accidently.
Comment #113
podarokdespite of these hardcoded arrays
all other looks good for me
Comment #114
pounardThe first three are core cache bins, installed by the system module and used for early bootstrap, so there is no other choice. And in the end, modules defining bins will have to hardcode their registration into their respective bundles, so those hardcoded names sounds legit.
Comment #115
podarokcan we move those arrays into settings.php ?
Comment #116
fubhy commented@podarok: Once the patch is more or less done they will be moved to the bundle of the module that they belong. So the second loop in bootstrap.inc will go away. Not sure if the first one can or should be moved to CoreBundle. Moving them to settings.php doesn't make sense imo.
Comment #117
podarok#116 Thanks, i got it
Looks like we need update documentation here with @todo for feature follow-ups
Comment #118
berdirNo, the second loop in bootstrap.inc will *not* go way. Those are bootstrap caches that are required before the bundles are loaded. No module can be called there, so there is little chance that something could use a different bin than these. And if it would actually be necessary to overwrite anything in there, then that could be done in settings.php, which is about the only case that could execute something at that point. I think.
The loop in CoreBundle is the one that should be distributed to per-module bundles, but the thing is that #1194136: Re-organise core cache bins will move them back because there will only be a fixed set of bins *in core* (modules still have the possibility to define their own, but the ones in core are then actually designed to be generic instead of added to the module that needs them).
The only ones that are a problem IMHO are those in update.php and UpgradePathTestBase. Because other modules might not have the chance to register their bin. This might get solved if update.php is converted to use a Kernel.
The problem there is that the cache bins are flushed according to hook_cache_flush(). As a follow-up of this issue, we might actually want to kill that hook (or rename it and keep it for special flush stuff like the thing in update.module) and flush all caches that are registered in the service.
Comment #119
berdirDidn't mean to remove the tag.
Comment #120
pounard@#118 Having two containers is heretic, "there's an issue for that" (TM) somewhere to reduce the pre bootstrap stuff to the maximum and move them into the core bundle where they belong. EDIT: The only blocker is the module list, it's the bare minimum to be able to build the full container using module bundles. The problem is that since now the module list uses both config and k/v, which themselves use cache and database, it forces us to continue this pre-bootstrap standalone non compiled container, which is very bad...
Comment #121
fubhy commentedSorry. I didn't look at the patch again and so I thought that the second loop listed in @podaroks comment was in bootstrap.inc too. So I was refering to the same loop that you were talking about @berdir. I just was wrong with the file that it is in :). So.. Yes, I meant the loop on the modules -> That one should be removed in favor of per-module bundles.
Comment #122
podarok#118 updated summary with hook_cache_flush() feature pointed to Your comment for pointing this in @todo`s
Comment #123
Crell commentedNot marking RTBC yet in case someone else has comments, but I think I've run out of things to object to in #112.
Comment #124
chx commentedFor sure settings.php can set up cache as it wishes so I have wrapped that in a has() much like the rest of the patch does and added plenty of comments. It's a minute change and for the rest everyone agree so I mark this RTBC.
Comment #125
berdirI really don't understand the need for these has() calls there. By calling drupal_container() in settings.php, which you need to do first, this code is run and those services are registered. The container class is created with new ContainerBuilder() right above, there is exactly zero chance someone could have added a cache service between new DrupalContainer() and register('cache')?
And if settings.php would actually create a completely new Container and pass it into drupal_container(), then the whole code block would never be executed.
Given that, exactly how could the cache service already exist at that point? Those 4 services/bins need to be overwritten using the example code that I've added to the documentation of CacheBackendInterface.
Comment #126
webchickThat sounds like a needs review.
Comment #127
chx commentedOoops... totally right, of course. #112 is the RTBC one then, reuploading here to avoid confusion.
Comment #128
webchickThis looks like it has catch written all over it. :)
Comment #131
sunIt still does not seem to be possible to define the cache storage to use (for all cache bins) in settings.php? This is a critical regression from D7, and I'm afraid, we don't have any critical follow-up issue slots available. :-/
Let's add a @todo + @see here for the issue that replaces this with a persistent non-cache storage.
Why does this suddenly become an issue? Such changes generally indicate that something else must be wrong.
TestBase and WebTestBase contain various @todos on the fact that the installer does not actually use the connection info in Database. By removing global $databases from the installer, those need to be resolved with this change.
This looks like a pretty bad hack - the getConnection() method is cleanly separated from connection info management methods currently. I do not think we want to hi-jack that clean design and separation. This change effectively means a ::setInfo() in a ::getConnection() method.
Same as above, but much worse.
These changes should be done in the dedicated issue instead:
#1810990: Teared down test environment leaks into parent site/test runner
TestBase sets up a new container already, so why is this needed?
Comment #132
berdirIt is possible, as described above. Not in a single line, but not *that* many. It is documented in the patch and relies on the fact that later cache bins will clone the definition of the default cache bin, so if that was changed in settings.php to APC, they will use APC as well.
Yes, it's not as nice as what we can currently do. On the other side, this likely makes the suggested hook_cache_bin_info() unecessary and should also be able to eliminate hook_cache_flush() in the way it exists now. We know which bins are around, so we can just loop over them and delete them. @pounard has posted a nice cache manager object above, but that can't happen until we compile the DIC, so let's open a follow-up: #1811724: Introduce cache manager to invalidate tags and flush all bins. We could also use this to provide an easy method for adding new cache bins using that method I guess.
#512026: Move $form_state storage from cache to new state/key-value system. There is a already a patch, just waiting for this and #1547008: Replace Update's cache system with the (expirable) key value store to happen so that we can use the expirable keyvalue storage in maintenance/install mode. *However*, that will not make the cache.form bin unecessary, it only moves the parts out that are *not* a cache. #1194136: Re-organise core cache bins is also waiting for all these issues to happen to get the number of our bins down to a handful generic ones.
Not sure, will check if it's still necessary. It certainly was at some point.
Yeah, it is. The correct way to fix this is to refactor the static Database class into one that lives within DIC and receives the necessary information in the constructor. Quoting Crell from #85: "I should note this is not the final state we want to have for the DB, but I'm OK with this approach for now. We can/should refactor later.". Follow-up created here: #1811730: Refactor Database to rely on the DIC solely. This issue is blocking a number of improvements and cleanup's for the cache system and I really hope we can get it in asap.
Comment #133
berdirOk, here we go.
- I did not add a @todo about cache.form because we don't want to replace it, we want to make it a normal cache. And there's already a major issue which is about doing that, with a patch, blocked by this issue :)
- I was able to remove the change in install_run_task(), seems to work fine now, must have been related to another issue.
- I was also enable to remove the drupal_container() call in WebTestBase::setUp(), tests seem to work.
- Added a @todo to Database::getConnection(). I actually realized that by moving the database correctly into the DIC, this will make the setUp()/tearDown() much much nicer. setUp() just needs to create a new container and set the database.info parameter. Done. tearDown() will just need to restore the original container. Done. Awesome :)
- Found and removed an now unecesary code snippet that restored global $databases, this is now restored as part of the container restore.
- Also, the drupal_container() move in tearDown() might be wrong, but is 100% in line with the current code. Here's why: Right above that, we restore the database to the default, then call those resets. So we are already executing them against the default database right now. The difference is that the cache backends now have an instantiated connection object instead of calling the current global connection. Moving it above means that the behavior is not changed. I think I know how to solve this properly, will comment in #1810990: Teared down test environment leaks into parent site/test runner. IMHO, the change in this patch makes sense given the current behavior.
- The remaining @todo: in TestBase about $databases is I think still true, so I left it there:
It is not a global anymore, but we still have to set it in two different ways. As mentioned above, once the Database is in the DIC, this will in fact be the only thing that we will have to do.
Thanks for the review, made a few nice cleanup's possible as one can see in the interdiff. Let's see if the testbot is happy.
EDIT: I'm actually not sure if we will replace the form cache bin completely or not, not sure what's correct, I'm going by catch's comment in the form_state issue, but looking at the code, I'm not sure if it makes sense to keep it. There is a major issue, so IMHO, not really necessary to add a todo that might or might not be true.
Comment #134
berdirComment #136
berdirStrange. Something in drupal_container(NULL, TRUE) must depend on something in drupal_static(). It works when drupal_container() is below drupal_static_reset() but not otherwise. And it's even strange that only those two tests break.
Comment #137
katbailey commentedI am deeply troubled by one aspect of this patch - if I am understanding it correctly, it is completely at odds with the effort to get rid of the "bootstrap container". See #1784312: Stop doing so much pre-kernel bootstrapping for background.
The bulk of the work for solving that problem is in #1331486: Move module_invoke_*() and friends to an Extensions class and that, combined with #1706064: Compile the Injection Container to disk, will result in the following set-up: on a normal page request, there is no container at all until the kernel creates one, and what it creates is a Container, not a ContainerBuilder. This means that nothing can affect the contents of the container without going via the kernel.
Obviously the ability to allow settings.php to affect how services are built is important, but I feel like this patch is going way off in one direction to solve that problem, and the work in the above two patches is going in the opposite direction (granted, not with that particular goal in mind, but with equally important ones IMO).
I know we have to solve one problem at a time and I don't want to hold this one up, but if it goes in like this I'm afraid it will be a huge setback for the above two patches.
Comment #138
Crell commentedI think sun is the one who first mentioned having a "SiteBundle" of some sort, where a site can register new services, or override services. I think that's the better approach to take. Then we simply add that bundle (if defined?) to the list of bundles to process when rebuilding the container.
Comment #139
sunSee also: How to Set External Parameters in the Service Container
Comment #140
katbailey commentedOK, based on #138 and #139 I am less deeply troubled about this ;-)
I still think it will be a ton of work to get both the DIC compilation and ExtensionHandler patches back on track after this patch, but at least it's fairly clear what needs to be done and, more importantly, that it can be done.
Comment #141
Crell commentedKat: So what patch order would result in the least rewriting between these three? Let's coordinate that since we want all three to get in soon. :-)
Comment #142
katbailey commentedHeh, that is a difficult question for me to answer objectively ;-)
I *think* that the order involving the least amount of rewriting would be:
... because I don't think either of those first two patches has side-effects that are at odds with the goal of this patch, whereas the converse is not true in either case. But of course it's easy for me to say that, seeing as I've worked on the other two and not on this one...
@chx has worked on all three, so maybe he's the best placed to give an objective opinion about this.
Comment #143
berdirOk, let's focus on the other ones then first. That will hopefully also make the performance decrease of this issue
Wha I'm going to do is extract the database changes form this issue and continue with that in #1811730: Refactor Database to rely on the DIC solely. Because it's only the database changes which are required to unblock my keyvalue issues, which would in turn help to simplify this patch.
Comment #144
berdirOk, re-starting this. See proof of concept patch.
This is the same approach as the one we're using for KeyValue. Database changes are no longer required, as the key value factory went the easy way to expose it for now. Applying the patch seems to work fine in an existing site, install will obviously not work yet.
Comment #145
robloachComment #146
sunThis looks great, @Berdir.
I assume that the following steps should get us to green here:
- adding a factory for cache.memory, cache.null, and cache.install
- registering the cache.install service in
install_begin_request()- registering the cache.memory service in
DrupalUnitTestBase::setUp()Comment #147
berdir@sun: Almost. The thing you forgot is CacheFactory::getBackends(). I'm not sure how to implement that, because I'm not sure what it's actually supposed to return.
Right now, it returns all backends that are explicitly registered. Let's say you use memcache by default, memory for A, database for B and apc for C then it returns 4 backends. Each is returned once. But if you use memcache by default and database for A and B, it will return three backends, 1x memcache and 2x database.
The implementation of the cache tag invalidation is currently based on the first case. It then invokes a method on each backend which it assumes is bin-agnostic ( I haven't found this being documented anywhere). There are already some issues about this and how it could be solved. The easiest would be to make tag invalidation a per-bin operation, but I'm not sure if that's actually possible.
If not, then the question is if that method should return bins or (distinct) backends. If backends, then the problem is that we currently have no official way to execute bin-agnostic methods. We could invoke it with CACHE_BIN_ALL or something like that, but that's a bit ... weird too.
Comment #148
berdirOk, I restored the current getBackends for the moment, that should allow to ignore it for the moment and get the other things working.
Added an install backend factory and made install work. Due to some crazy __destruct() stuff I had the problem that some cases still tried to access the install.backend service when it was no longer available. Fixed that by adding a fallback for now.
Comment #150
sunShortly after this location, we're setting up a specialized container for the installer, and I think this should be moved in there.
I also think that we no longer need an install backend. Instead, the memory backend should be sufficient and suitable for the installer container, and once system tables have been installed, that container is replaced with the regular container, which can use the database backend as usual.
Simplification++ :)
Comment #151
berdir@sun: I'm not sure, I think the tricky part are those ajax requests that might lead to cache sets but still need to be deleted when requested to do so. Other than that, InstallBackend is essentially a NullBackend. Agree that it might be possible to improve this, but it's not really relevant for the complexity of this issue We still need to overwrite the default with *something* on install.
Not sure what you mean with the specialized container part, there is one, but that is only used conditionally when there is no settings.php yet. That one was missing a definition for the cache factory, which I added now, this should make the installer work, I was testing with an existing settings.php. The cache.install definition is also needed when we use the default bootstrap container.
Comment #153
catchInstaller backend is #1792536: Remove the install backend and stop catching exceptions in the default database cache backend let's discuss that issue there but yes it can't just be removed as it is without a regression still afaik.
@Berdir, we could loop over hook_cache_bin_info() and invalidate tags for each bin that way, then it's up to something like the database backend to avoid writing the tags over and over again itself. That would be cleaner than the assumption we have now probably. This would mean that tag invalidation would eventually depend on the extension manager but that's not too bad.
This would mean bringing in just the hook_cache_flush()/hook_cache_bin_info() change from #1167144: Make cache backends responsible for their own storage into here though. That issue now depends on this one (because it needs update module to not be hard-coding database queries to its cache table).
Comment #154
berdirAdded memcache factory and using that in DrupalUnitTestBase.
Somehow, running tests within a test is currently broken, looks like the tables don't exist. Haven't figured that out yet.
Comment #156
berdirOk, re-rolled this works fine through the installer for me. Testbot, be nice?
Comment #158
berdirOk, the cache decorator tests are easy to fix, but I'm really strugglying with the other two, both have the same problem, they fail to run tests within a test.
The reason seems to be that the state query in drupal_get_installed_schema_version() connects to the parent simpletest site, where those modules are already enabled. Obviously. So it doesn't install the schema of user.module and then breaks. But it only happens within a test, not for normal test and I can't figure out what's different.
Someone has an idea what this could be? :(
Comment #159
chx commented#156: cache-dic-re-revival-1764474-155.patch queued for re-testing.
Comment #161
berdirOk, here is a re-roll. Those weird schema issues might have been fixed in the meantime in other issues, let's see what happens!
Comment #163
dawehnerJust a small point, shouldn't all classes which depends on the container implement the ContainerAwareInterface?
You talked about getting rid of that earlier in the issue, but couldn't pull that information from the container using tags on the individual cache factories?
The InstallBackendFactory seems to require to inject the database connection?
Wouldn't it help a bit if the service would be called cache.factory, so the name explains what is behind? On the other hand $container->get('cache')
is simplier to read.
So additional to the event_dispatcher we register a dispatcher, which is not container aware, so we can't rely on container tags. I'm wondering whether this is really cleaner the rely on the container.
Shouldn't this be cache_bin?
Is there a reason why not to use the database connection from the container?
Comment #164
berdirThanks for the review!
Re-rolled, updated service definitions and hopefully fixed the installer, also added the ContainerAware part and fixed the cache.bin unset. install backend is gone, so we don't have to worry about that anymore :)
To-Do:
- Consider to rename the services to cache.factory(.*)
- Change to use settings in the factory, possibly injected. Will need to change that a bit I think, we'll see.
Comment #166
Anonymous (not verified) commented#164: cache-dic-1764474-164.patch queued for re-testing.
Comment #168
berdirRe-roll after the lock patch went in. Could not have worked on two other issues that were overlapping that much ;)
Comment #170
dawehner#168: cache-dic-1764474-168.patch queued for re-testing.
Comment #172
chx commentedThis patch has been written from ground up. I have seen Drupal install and ClearTest pass with it.
Comment #174
chx commentedOh. I tried minimal. Here's one that installs with standard :)
Comment #176
chx commentedOh DUTB.
Comment #178
dawehnerGreat work so far, here are just small comments.
I'm wondering whether it would make sense to have these methods on the global Cache backend factory.
I guess we could typehint the connection object here?
Just to note: This contains code by another class :)
Why not split up after the first dot instead? This could be easier to read.
Does it make sense to use this class instead of using the full path here?
Just in general: I prefer the variant by local module: "Registers locale module's services to the container."
because it's simply more correct.
Comment #179
chx commentedThanks for the review, these have been addressed. The helper methods does not belong to CacheFactory -- but I already wanted a helper class for bin registration so Cache was added. I hopefully addressed most (all?) test failures as well.
Comment #181
chx commentedComment #183
chx commentedComment #185
chx commentedComment #186
dawehnerDo we have an issue to remove this backport compatibility layer?
Even if it's commented code, shouldn't we better use array_walk, as we don't map a function, and apply the value but rather iterate over the values. If we use array_walk, we can also exclude the bins in that already.
Idea for a follow up: We could put these bins in a constant, so it's documented why we exactly have these kind of bins.
Could we actually test settings() with that?
Nitpick: Missing "\", I will not comment further nitpicks.
If we add a new file we should also document what this class allows us to do.
I guess these functions should be marked as public?
Seems to be a good candidate for array_walk?
Should we better use Drupal::service() now, as drupal_container() is deprecated?
It's odd to have a test for that in there, isn't that test cout clearing the cache, not getting the bins?
Don't we have the container available at that time? There is at least a $this->container there.
Another array_walk
Nice catch, that we forgot the views_results in there.
Comment #187
berdirRelated to "$bin = str_replace('cache_', '', $bin);", I think my earlier patches already removed that as I couldn't find any remaining usage of that.
I'm working on throwing out 50% of the current cache bins in #1194136: Re-organise core cache bins (In short, group cache bins by type/usage instead of module that uses it), so let's not spend too much on documenting/defining them as constants for now :)
Comment #188
chx commentedComment #189
Crell commentedThis class is not needed. See below.
I don't see how this is needed. It's one call in a bundle method.
This should be a method on the CacheFactory object itself.
This should be a method on the CacheFactory object itself.
This should be a method on the CacheFactory object itself.
We've been moving larger blocks like this into utility methods within CoreBundle for readability. I think this qualifies.
Wait, why are we using the container in a test?
Comment #190
chx commented> I don't see how this is needed. It's one call in a bundle method.
We are not going to copypaste 5 lines of code 7 times. Not to mention it's not quite copypaste, it has an argument. Do we really need to argue on why functions are a good idea...?
> This should be a method on the CacheFactory object itself.
That's a followup. It involves refactoring _menu_clear_page_cache to use the new terminate event and so on. The issue is about the cache interface and the backends using the DIC, not converting every single helper to full injection. It's already 50kb and complicated.
> We've been moving larger blocks like this into utility methods within CoreBundle for readability. I think this qualifies.
Sure. I added comments too.
Comment #191
chx commentedUnfollowing. Have fun!
Comment #192
msonnabaum commentedRemoved Drupal::parameter. The name is way too generic for what it does, and doesn't really provide a useful abstraction in this patch.
Changed the array_walk's to foreach. The type hinted callback was less readable and didn't buy us anything.
Also moved registerBins to CacheFactory. It's unfortunate that registering bins is already tied to the the container, but let's not make Cache dependent on it.
Comment #193
dawehnerThanks for continuing this issue!
We could fix this small comment in a follow up.
Comment #195
alexpottDue to...
Comment #196
alexpottShould have fixed that comment at the same time...
Comment #198
alexpottOkay-dokey... the issue was this...
Comment #199
dawehnerIn one of the other patches array_map/array_walk got changed to foreach, so using array_walk seems to be a small inconsistency, but I don't consider this as a problem which blocks the RTBC.
Comment #201
alexpottOkay had to make
GenericCacheBackendUnitTestBaseuseDrupalUnitTestBaseasDrupal\system\Tests\Cache\DatabaseBackendUnitTestwas using the database and this shouldn't really happen in aUnitTestBasetest.Also incorporated feedback from #199 to make
system_cron()consistent.Hopefully green...
Comment #202
berdirLooks awesome, some comment nitpicking but should be ready after that.
I think Crell said at some point that this isn't really necessary. Also, I don't seem to find any usage of it, so not sure why it was introduced?
In case this needs a re-roll, should be Contains \Drupal\...
Ah, I guess it was used here.
Same here, should have a \ in front of the class name.
I am wondering if we can use the same pattern here that we are nowing using for controllers and might be using for plugins as well. That is, a static create() method on the implementation that can get the stuff it needs from the container. Not as clean as this but also doesn't require this class.
Certainly something to discuss in a follow-up, we're just applying a pattern here that's already beeing used for queue and key/value.
Hm. A simple docblock with @param and @return wouldn't hurt. That was already in my previous patches I think...
Left-over docblock from copy & paste.
Contains \... :)
It's arguable if this should use the container service or not. We often do that but it doesn't really matter, if we don't use that then we still need the database connection, so I think this is fine.
Hah, I was going point to the same issue as being related but then noticed that you already did pick that one ;)
Another one of those.
Another \ ;)
Comment #203
alexpott@berdir thanks for the review! hopefully the attached patch has got them all...
Comment #204
berdirInterdiff looks great.
Comment #205
catchhook_cache_flush() should be completely removed. While some modules implement it for garbage collection etc., they all appear to be unaware that it runs on hook_cron() anyway, and the phpdoc says it's only for declaring cache bins anyway.
Are any modules implementing it after this change? If so maybe that'd have to be a follow-up, otherwise we could do that here.
Why exclude cache.menu?
Comment #206
chx commentedbecause cache menu gets redone in the menu rebuild below. And, update module IMO uses hook_cache_flush.
Comment #207
catchupdate module only implements it because it's broken #1547008: Replace Update's cache system with the (expirable) key value store.
Comment #208
yesct commentedmight be an easy reroll (instructions for reroll: http://drupal.org/patch/reroll)
remove that update_cache_flush (hook_cache_flush) from the converted version
invoke calls all of the hook implementations of that hook.
so remove the invoke too
+ module_invoke_all('cache_flush');
check system.api.php too.
read some of the committed patch in #1547008: Replace Update's cache system with the (expirable) key value store to see what other change might be needed.
Comment #209
andyceo commented#203: 1764474-203.patch queued for re-testing.
Comment #211
berdirHere's a re-roll.
As to hook_cache_flush(), can we handle that in a follow-up? There's still config_test_cache_flush(), which is used by config import tests to verify that the cache was cleared.
While re-rolling, also added Drupal::cache() and used that in cache() and also fixed a use of Drupal in the Cache class, should use \Drupal just like PHP top-level classes.
Comment #213
berdirI've no idea what's suddenly causing that issue and opened #1948600: PHP Fatal error: Class 'Insert' not found in \SomeNamespace\SomeClass.php on $lastline because it was so much fun to track down but this fixes it.
Comment #214
berdirRemove tag
Comment #215
robloachWe have Drupal\Core\Cache\Cache. What about moving
Drupal::cache($bin)toCache::get($bin)?Should this be protected, along with public get/setters? Where exactly is
DatabaseBackendUnitTest::$modulesused?Comment #216
berdirCache::get() would internally have to do a Drupal::service() and the reason all those methods are on Drupal is that Drupal is a top level class and doesn't need to be use'd in procedural code.
public static $modules are used by all tests to define the modules they need, that information is collected in setUp(). Must be defined exactly like it is there.
Comment #217
robloachAh, right! Thanks... I've been using too much PHPUnit lately. Overall it looks pretty good to me.
Comment #218
ParisLiakos commentedwell, it looks awesome to me
Well i guess its ok to let drupal_container() be, since there is a todo to clear it.
Created #1949632: Remove hook_cache_flush()
back to RTBC, since catch's concerns seem addressed
Comment #219
catchThanks! Committed/pushed to 8.x.
Comment #220
derhasi commentedI just thought this commit broke the installation process. After i cleaned up the installation (deleted sites/default/files/php and the config folders and run the install.php, an error occured after entering the databse credentials: " ... Base table or view not found: 1146 Table 'do_d8.cache_config' ...".
The problem was, that I still had an old settings.php there., fter using the new default.settings.php all was fine again.
Wanted to leave this here, just for reference.
Comment #221
ParisLiakos commentedactually this is old news..you see settings.php stores the config directory name..so you have to delete it on reinstall since the name changes
Comment #223
effulgentsia commentedThat these do different things is kind of weird and possibly responsible for #2067429: Fix installer to not use Drupal\Core\Cache\DatabaseBackend
Comment #223.0
effulgentsia commentedUpdated issue summary.