doctrine/doctrine2 — pull request #580 by FabioBatSilva (2013-02-14 01:01:02+00:00)
Title: Second cache level POC

Hi guys. :)

@guilhermeblanco / @instaclick have asked me to take a look into second level cache.
and i end up with the following solution..

There is lot of work todo before merge it, but i'd like to get your thoughts before i go any further on this approach.
I hope my drafts are good enough to explain the idea :

### Cache strategies

* READ_ONLY	: ReadOnly cache can do reads, inserts and deletes, cannot perform updates or employ any locks.
* NONSTRICT_READ_WRITE : Nonstrict Read Write Cache doesn’t employ any locks but can do reads, inserts , updates and deletes.
* READ_WRITE	: Read Write cache employs locks the entity before update/delete.

### classes / interfaces

* **Region** :
Defines a contract for accessing a entity/collection data cache. (Doesn’t employ any locks)

* **TransactionalRegion** :
Defines a contract for accessing a entity/collection data cache. (Locks the data before update/delete.)

* **RegionAccess** :
Defines a contract to access a cache region

* **TransactionalRegionAccess** :
Defines contract to access regions which hold transactionally-managed data.

* **CacheKey / EntityCacheKey / CollectionCacheKey/ QueryCacheKey**:
Defines entity / collection key to be stored in the cache region.

* **EntityEntryStructure / CollectionEntryStructure**
Build cache entries and rebuild entities/colection from cache

* **AccessProvider**
Build RegionAccess based on entity / collection cache configuration

### OPERATIONS

#### INSERT :

*********************************************************************************************
UnitOfWork#commit
Connection#beginTransaction
Persister#executeInserts
Connection#commit
Persister#afterTransactionComplete
-> EntityRegionAccessStrategy#afterInsert
*********************************************************************************************
METHOD | READ-ONLY | NONSTRICT-READ-WRITE | READ-WRITE |
---------------------------------------------------------------------------------------------
afterInsert | add item to the cache | add item to the cache | add item to the cache |
---------------------------------------------------------------------------------------------

#### UPDATE :

*********************************************************************************************
UnitOfWork#commit
Connection#beginTransaction
Persister#update
-> TransactionalRegionAccess#lockItem
-> execute
Connection#commit
Persister#afterTransactionComplete
-> RegionAccess#afterUpdate
-> TransactionalRegionAccess#unlockItem
*********************************************************************************************
METHOD | READ-ONLY | NONSTRICT-READ-WRITE | READ-WRITE |
---------------------------------------------------------------------------------------------
lockItem |	|	| lock item |
---------------------------------------------------------------------------------------------
afterUpdate | throws exception | update item cache | update item cache |
---------------------------------------------------------------------------------------------
unlockItem |	|	| unlock item |
---------------------------------------------------------------------------------------------

#### DELETE :

*********************************************************************************************
UnitOfWork#commit
Connection#beginTransaction
Persister#delete
-> TransactionalRegionAccess#lockItem
-> execute
Connection#commit
Persister#afterTransactionComplete
-> RegionAccess#evict
*********************************************************************************************
METHOD | READ-ONLY | NONSTRICT-READ-WRITE | READ-WRITE |
---------------------------------------------------------------------------------------------
lockItem |	| | lock item |
---------------------------------------------------------------------------------------------
evict	| remove item cache | remove item cache	| remove item cache |
---------------------------------------------------------------------------------------------

#### USAGE :
```php
persist(new State($name, $country));
$em->flush();	// Put itens into cache

$em->clear();	// Clear entity manager

$state	= $em->find('Entity\State', 1);	// Retreive item from cache
$country = $state->getCountry();	// Retreive item from cache
$cities = $state->getCities();	// Load from database and put into cache

$state->setName("New Name");
$em->persist($state);
$em->flush();	// Update item cache

$em->clear();	// Clear entity manager

$em->find('Entity\State', 1)->getCities(); // Retreive from cache

$metadata	= $em->getClassMetadata('Entity\State');
$identifier	= array('id'=>$state->getId());

$em->getCache()->containsEntity($metadata, $identifier)	// Check if the cache exists
$em->getCache()->evictEntity($metadata, $identifier);	// Remove an entity from cache
$em->getCache()->evictEntityRegion($metadata);	// Remove all entities from cache

$em->getCache()->containsCollection($metadata, 'cities', $identifier);	// Check if the cache exists
$em->getCache()->evictCollection($metadata, 'cities', $identifier);	// Remove an entity collection from cache
$em->getCache()->evictCollectionRegion($metadata, 'cities');	// Remove all collections from cache

```

#### TODO :
* handle many to many collection
* handle inheritance
* remove/add colection items on update
* improve region tests
* improve access strategy tests
* implement xml / yml /php drivers
* implement transaction region
* implement transaction access strategy
* .... ????