Cleanup/Storage

Cleanup: Storage

Situation

Agavi's current storage implementation only allows for one type of storage to be used at once. This is fine for the current set of available classes (just session handlers), since it is not possible to use more than one session interface at a time.

However, the structure for a storage system is highly flexible, and could be used for a variety of different functions -- essentially any persistence of data organized as a map (key => value). One possibly for this is the the caching system.

Also, while right now, the exclusive use of the storage for sessions is not a problem, it will be a problem if we decided to have a whole bunch of storages available through a storage manager - a mysql storage and a mysql session storage would essentially do the same thing barring some session_set_save_handler() calls. We have the odd situation where the User class deals with all the session information, and the Storage class reads and writes it. This feels unnecessary.

Ideas

  1. We move the responsibility of handling the session completely into the User implementation. This includes session_set_save_handler() calls.
  2. The old session storages die. We make them general purpose. The User class can then use a MysqlStorage, but the responsibility of accessing the storage appropriately lies with the User, not the Storage
  3. AgaviStorageManager handles the storages, similar to AgaviDatabaseManager
  4. BC is retained for old config versions. Magic XSL is magic!
  5. !AgaviILockableStorage etc for more awesomeness (compare #748)
  6. Allow storage chaining; example: session/cache writes always go to memcache first, then database, but attempt to read is first made on memcache, then on database as a last resort

Proposal

  1. Separate storages.xml configures storages implementations
  2. <storage> in factories.xml is removed, <storage_manager> introduced
  3. All bundled Agavi*SessionStorage classes implement AgaviLegacySessionStorage or so
  4. They can still be used by AgaviUser, which now handles all session related stuff
  5. BC XSL rewrites old configs with <storage> appropriately

Configuration

The easiest way to manage this organization would be through a configuration file, storages.xml. A sample:

<ae:configurations xmlns:ae="http://agavi.org/agavi/config/global/envelope/1.0" xmlns="http://agavi.org/agavi/config/parts/storages/1.1">
  <ae:configuration>

    <storages>
      <storage name="cache" class="AgaviFilesystemCacheStorage">
        <ae:parameter name="cache_directory">%core.cache_dir%/bbq</ae:parameter>
      </storage>
      <storage name="session" class="AgaviSessionStorage">
        <!-- parameters here -->
      </storage>
    </storages>

  </ae:configuration>
</ae:configurations>

Storage Manager

This system would also necessitate a storage manager, very similar in nature to the AgaviDatabaseManager?. In fact the API would be nearly identical, so I'll skip defining it for now.

Chaining

I believe we can simply implement this through a meta-storage:

<storage name="session" class="AgaviChainedStorage">
  <ae:parameter name="storages">
    <ae:parameter>memcached_cluster</ae:parameter>
    <ae:parameter>mysqlcache</ae:parameter>
  </ae:parameter>
</storage>

of course, we reference other storage names here, since those have the appropriate configuration (memcache has hosts, mysql has the <database> to use, table and colum names etc)