Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[RFC] Refactor caching of Translator component #28851

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

Closed
rpkamp opened this issue Oct 13, 2018 · 4 comments
Closed

[RFC] Refactor caching of Translator component #28851

rpkamp opened this issue Oct 13, 2018 · 4 comments
Labels
RFC RFC = Request For Comments (proposals about features that you want to be discussed) Translation

Comments

@rpkamp
Copy link
Contributor

rpkamp commented Oct 13, 2018

Currently the caching of the Translator component is sprinkled all over the place:

  1. The Translator itself has a notion that catalogues can be cached (see Translator#loadCatalogue)
  2. The Translator Fileloader knows about the Config component for caching (see FileLoader#load)
  3. The Container has FileResources FileExistenceResources and DirectoryResources for translation files so the Container itself will be deemed non fresh when the translation files have changed (see FrameworkExtension#registerTranslatorConfiguration)
  4. For some reason the Translator and the Router share the same ConfigCacheFactory (see here and here) as @stof pointed out this isn't true
  5. All of the above is focused on caching files only, there is no notion of directories

This has the following drawbacks:

  1. The Translator has too many responsibilities and thus too many reasons to change
  2. There is double bookkeeping going on between the Container and Catalogues, so that when a translation file changes both the Container and the Translator cache need to be refreshed, whereas a refresh of just the Translator cache would suffice
  3. When a new translation file is added to a directory the container will conclude it needs a refresh (because it has DirectoryResources for the translation directories), but the catalogue itself will never consider the new file (because it only has FileResources, no DirectoryResources - see Add new translation files without clearing the cache #27600)
  4. When the routing configuration changes the translator has to be rebuilt and vice versa (because of the shared ConfigCacheFactory) as @stof pointed out this isn't true

Proposal to solve these drawbacks:

  1. Remove the responsibility of loading catalogues from the Translator, give this responsibility to a new MessageCatalogueLoader that knows how to load catalogues, but has no idea about caching
  2. Add a CachedMessageCatalogueLoader that can decorate the MessageCatalogueLoader (so they both implement a common interface) and that knows how to cache catalogues, but has no idea how to load them (it delegates this to the MessageCatalogueLoader). This CachedMessageCatalogueLoader would also implement SelfCheckingResourceInterface, so it can indicate to the Container when it's no longer fresh - the container no longer needs to concern itself with that. This also decouples the Translator cache from the Router cache.
  3. Remove the notion of caching from the FileLoader class - as @stof pointed out this isn't going to work because the decorator would need too much knowledge about what it's decorating
  4. Add a CacheAwareFileloader that decorates all FileLoaders to add caching (add FileResource to catalogue on load). Symfony Framework would use this decoration by default, but for the Translator component it's optional. - as @stof pointed out this isn't going to work because the decorator would need too much knowledge about what it's decorating
  5. Add a new DirectoryLoader that iterates all files in a directory and passes all files to FileLoaders to be loaded
  6. Add a CacheAwareDirectoryLoader that decorates DirectoryLoader to add the notion of caching (add DirectoryResource to catalogue on load). Symfony Framework would use this decoration by default, but for the Translator component it's optional. - as @stof pointed out this isn't going to work because the decorator would need too much knowledge about what it's decorating

There are still a lot of implementation details to be considered, but this is the broad overview.

I'd love to hear what people think about this proposal!
If anything is unclear I'd love to clarify - ask me anything!

Also, I'd be willing to create a PR for this if this RFC gets accepted

@javiereguiluz javiereguiluz added Translation RFC RFC = Request For Comments (proposals about features that you want to be discussed) labels Oct 13, 2018
@stof
Copy link
Member

stof commented Oct 15, 2018

The container should only have FileExistenceResource, not FileResource, as it cares about the list of files, not their content.

4\. When the routing configuration changes the translator has to be rebuilt and vice versa (because of the shared ConfigCacheFactory)

what makes them shared ? Using the same ConfigCacheFactory does not mean they use the same ConfigCache (each call to the factory creates a separate one, and the router and translator don't use the path).

I'm not convinced by the usage of a decorator to register the resource in the catalogue. Knowing which resource to register depends on the implementation details of the loader, which makes it unsuited for being handled by a decorator.

@rpkamp
Copy link
Contributor Author

rpkamp commented Oct 17, 2018

The container should only have FileExistenceResource, not FileResource, as it cares about the list of files, not their content.

Indeed it only checks for directories, so it will have FileExistenceResources and DirectoryResources, no FileResources. My bad.

what makes them shared ? Using the same ConfigCacheFactory does not mean they use the same ConfigCache (each call to the factory creates a separate one, and the router and translator don't use the path).

Ah, it seems I misunderstood the code there. Indeed they don't seem to share a cache after all.

I'm not convinced by the usage of a decorator to register the resource in the catalogue. Knowing which resource to register depends on the implementation details of the loader, which makes it unsuited for being handled by a decorator.

In my mind there only were Php, Xml and Yaml loaders, but indeed there is also ArrayFileLoader, plus people can write their own by implementing LoaderInterface. I agree, decorator won't work here, the logic for adding FileResources should stay in the FileLoader as there is no viable alternative (without abstracting it so much it becomes unrecognisable).

I'll update my original proposal to take this feedback on board. Thanks!

@rpkamp
Copy link
Contributor Author

rpkamp commented Oct 17, 2018

@stof I've updated my proposal. Points 1 (extract catalogue loading from Translator), 2 (caching catalogue loader decorator) and 5 (directory loader) still stand.

How do you feel about those?

@rpkamp
Copy link
Contributor Author

rpkamp commented Oct 20, 2018

I just tried to implement the MessageCatalogueLoaderInterface with a default implementation MessageCatalogueLoader and a caching decorator CachingMessageCatalogueLoader and it's a lot harder than I thought:

  1. It's near impossible to do this without breaking BC in a huge way since everything is so intertwined
  2. The concept of fallback catalogues is so inherently complicated (not the Symfony implementation, just the concept on its own) that both the MessageCatalogueLoader and the CachingMessageCatalogueLoader would need to know a lot about it, kind of missing the point of a decorator

For these reasons I no longer feel this is something that must be pursued any longer. I'll try to solve the directory bug another way.

@rpkamp rpkamp closed this as completed Oct 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
RFC RFC = Request For Comments (proposals about features that you want to be discussed) Translation
Projects
None yet
Development

No branches or pull requests

3 participants