laminas-cache icon indicating copy to clipboard operation
laminas-cache copied to clipboard

[RFC]: Move `StorageInterface::getMetadata` to `MetadataCapableInterface`

Open boesing opened this issue 4 years ago • 0 comments

RFC

Q A
Proposed Version(s) 4.00
BC Break? Yes

Goal

Having those adapters which do support metadata must explicitly implement that interface rather than assuming that all adapters will have that capability.

Background

Just a handful of adapters do support Metadata. Almost all adapters have different metadatas aswell. With having a dedicated interface which also have a template to annotate the generic Metadata instance with getters of these metadatas will provide properly typed informations long-term.

Given the example of the filesystem adapter which can provided filesystem-specific metadatas (mtime, atime, ...), almost all metadatas are already "explicitly" used. So upstream projects will probably implement Filesystem directly rather than using StorageInterface. If they do, there might be a point where they use assert($storage instanceOf Filesystem); because otherwise, that wont make any sense when using getMetadata while also accessing the atime array key.

With having that new interface in addition with the generic annotation to mark the Metadata instance, we can provide a FilesystemMetadata instance which then provides type-safe getters for mtime and atime.

So in the end, all adapters have to provide their own metadata implementation.

Considerations

As already mentioned, I assume that those users which do make use of the StorageInterface::getMetadata do this, because they know the underlying storage implementation. Currently usage would be something like:

$storage = new Filesystem();

$metadata = $storage->getMetadata('key1');
assert($metadata !== false);

$cacheCreatedOn = $metadata['atime'];

This would never work with the Redis or Memcached implementation. So in the end, we will provide proper FilesystemMetadata instance with properly typed methods to provide metadata informations of existing cache keys. Migration to the new functionality would also quite easy because instead of accessing array keys, users only have to access the provided getters/setters.

Proposal(s)

The MetadataCapableInterface would have been asserted by either using instanceof or by directly consuming the adapter rather than the interface. I guess, thats already the case in those projects which do use the StorageInterface::getMedata

Appendix

The new MetadataCapableInterface might look like this:


/**
 * @template TMetadata of object
 */
interface MetadataCapableInterface
{
	/**
	 * @psalm-return TMetadata
	 */
	public function getMetadata(string $key): ?object;
}

A possible implementation in the Filesystem adapter could look like this:

final class FilesystemMetadata
{
	private $mtime;
	private $atime;
	// [...]

    public function __construct(int $mtime, int $atime)
    {}

    public function getMTime(): int
    {}

    public function getATime(): int
    {}
}
/**
 * @template-implements MetadataCapableInterface<FilesystemMetadata>
 */
final class Filesystem extends AbstractAdapter implements MetadataCapableInterface
{
	public function getMetadata(string $key): ?object
	{
		if (!$this->hasItem($key)) {
			return null;
		}

		$options  = $this->getOptions();
        $filespec = $this->getFileSpec($key);
        $file     = $this->formatFilename($filespec);

        return new FilesystemMetadata(filemtime($file), fileatime($file));
	}
}

Currently available metadata (depending on adapters)

these links might be outdated in the future as we dont have adapter-specific documentations available and all adapters share the same configuration structure. @froschdesign maybe finds a way to have this fixed in future documentation implementations (as stated in one of my other PRs).

https://docs.laminas.dev/laminas-cache/storage/adapter/#capabilities https://docs.laminas.dev/laminas-cache/storage/adapter/#capabilities_3 https://docs.laminas.dev/laminas-cache/storage/adapter/#capabilities_5 https://docs.laminas.dev/laminas-cache/storage/adapter/#capabilities_6 https://docs.laminas.dev/laminas-cache/storage/adapter/#capabilities_7 https://docs.laminas.dev/laminas-cache/storage/adapter/#capabilities_8 https://docs.laminas.dev/laminas-cache/storage/adapter/#capabilities_9 https://docs.laminas.dev/laminas-cache/storage/adapter/#capabilities_10 https://docs.laminas.dev/laminas-cache/storage/adapter/#capabilities_11

boesing avatar Jul 11 '21 12:07 boesing