tedivm/Stash — Issue #22: Handler error states / canEnable
Author: jhallbachner
Created: 2012-02-23 19:54:27+00:00
State: open

Right now, there are two distinct, not entirely compatible reasons one might want to use the canEnable methods:

* For a specific, instantiated cache handler object, to find out whether the object can be used given its current configuration
* For a type of handler, to get information about whether the necessary system resources (PHP extensions, etc.) are present for that handler type to be used

Right now, the handlers do not deal with either issue consistently:

* **FileSystem**: Always returns true for canEnable; will return false on storeData and getData (usually with a system-level warning on the former) if file system permissions don't allow writing at the provided location.
* **SQLite**: Returns true from canEnable if the _currently specified subhandler_ is available; generates a fatal PDO error on storeData if the target filesystem is not writeable.
* **APC**: Returns true from canEnable if the extension is loaded; generates a fatal undefined-function error if store or get is called when it isn't.
* **Memcached**: Returns the subhandler's value (i.e. a class_exists on either 'Memcache' or 'Memcached') from canEnable, but it throws a MemcacheException from the constructor if neither extension is available to load.
* **MultiHandler**: Always returns true from canEnable, but throws a MultiHandlerException from the constructor if no handlers are provided at instantiation.

My off-the-cuff proposal for a rework:

* Remove all exceptions from the constructors; let all handlers be instantiated without any errors.
* Give each handler an isAvailable() method; this would perform the system-level check regarding whether it is possible to use that handler at all, i.e., return false if the extension isn't loaded.
* Expand the canEnable methods to check fully that the current instance of the cache object can in fact be used; e.g. check file permissions for FileSystem and SQLite, check that the servers are available for Memcache, etc.
* Have store/get/purge call canEnable first thing and throw a handler-specific exception if the result is false. (Alternately, return false if that's a preferable error-handling behavior here.)
* All subhandler-based handlers (currently SQLite and Memcache) should apply a priority of subhandlers and automatically step through it to find the best option when no specific version is specified (Memcache does this but SQLite does not.)