Skip to content

[Config] RFC - Simplify and redesign ResourceInterface #7176

Closed
@mpdude

Description

@mpdude

Currently, Config/ResourceInterface and its implementations serve a single purpose - that is, checking whether data from a ConfigCache is still valid. For that, the cache is associated with a set of Resources which can later be checked for freshness. ConfigCache seems to be the only client of ResourceInterface right now.

The problem with the interface is that it somewhat assumes that resources are filesystem objects. Just as Loaders (Config/Loader/LoaderInterface) can load about anything, the same should be true for Resources.

For example, it is no problem to have a loader pull some information (think of translations) from a database. At a later time, you might need to check if the generated message catalogue is still up to date.

Implementing ResourceInterface in this case is difficult - __toString() and getResource() hardly make sense for "translations from a database", and at least to getResource() is the Loader's job. Anyway, both methods are not used by ConfigCache as the current sole client.

Freshness check based on timestamp

Checking isFresh($timestamp) - which means "is the Resource still the same as it was at $timestamp" - might also be implemented differently for the said database.

The $timestamp need not be a timestamp but just an opaque identifier (think ETag). Even more, as Resource implementations being serialized carry resource type-specific data anyway (a filename, for example), the entire way of validating them should be encapsulated in the Resource. That is, a Resource could upon creation get or keep what it needs for validation.
For example, a FileResource would grab the mtime() of the underlying file, keep it along with the filename (in its serialized form) and later on (when unserialized) check the mtime() again, comparing the two values.

A more simple, self-validating Resource interface

All this would lead to a ResourceInterface like

namespace Symfony\Component\Config\Resource;

interface ResourceInterface
{
    /**
     * Returns true if the resource has been updated since it has been created.
     * @return Boolean true if the resource haseen updated, false otherwise
     */
    public function hasChanged();
}

plus the requirement the implementors are (un)serializable without side effects.

Resource checks using services

I also made a suggestion how Resource validation could be shifted from the Resource implementation to some kind of "voter" or "checker" class which allows for using services (a database connection, a loader implementation) during the check which is not possible if the check has to be within the unserialized resource.

That would even leave Resource as a marker interface and have the "voter" implement a single "hasChanged(Resource $r)" method.

To sum up

I think simplifying the ResourceInterface would be a good thing to do because

  • it adds conceptual clarity
  • yields a segregated interface
  • allows for new Resource types that can reflect what loaders can already do

Shifting the freshness check from Resource implementations to some kind of "voter"/"checker" additionally makes it possible to use services for validation, being a solution for at least one issue.

Opinions please. Will do the work if others agree :-).

Update: The current WIP is #7230.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions