<!-- 
RSS generated by JIRA (5.2.7#850-sha1:b2af0c8dc8537b36121c6a579fabbdf79fc919e5) at Tue May 21 16:56:46 UTC 2013

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary add field=key&field=summary to the URL of your request.
For example:
http://www.doctrine-project.org/jira/si/jira.issueviews:issue-xml/DDC-2295/DDC-2295.xml?field=key&field=summary
-->
<rss version="0.92" >
<channel>
    <title>Doctrine Project</title>
    <link>http://www.doctrine-project.org/jira</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>5.2.7</version>
        <build-number>850</build-number>
        <build-date>21-02-2013</build-date>
    </build-info>

<item>
            <title>[DDC-2295] [GH-580] Second cache level POC</title>
                <link>http://www.doctrine-project.org/jira/browse/DDC-2295</link>
                <project id="10032" key="DDC">Doctrine 2 - ORM</project>
                        <description>&lt;p&gt;This issue is created automatically through a Github pull request on behalf of FabioBatSilva:&lt;/p&gt;

&lt;p&gt;  Url: &lt;a href=&quot;https://github.com/doctrine/doctrine2/pull/580&quot; class=&quot;external-link&quot;&gt;https://github.com/doctrine/doctrine2/pull/580&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Message:&lt;/p&gt;

&lt;p&gt;Hi guys. &lt;img class=&quot;emoticon&quot; src=&quot;http://www.doctrine-project.org/jira/images/icons/emoticons/smile.gif&quot; height=&quot;20&quot; width=&quot;20&quot; align=&quot;absmiddle&quot; alt=&quot;&quot; border=&quot;0&quot;/&gt;&lt;/p&gt;


&lt;p&gt;After a look into some implementations I end up with the following solution for the second level cache..&lt;/p&gt;

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

&lt;ol&gt;
	&lt;li&gt;
	&lt;ol&gt;
		&lt;li&gt;
		&lt;ol&gt;
			&lt;li&gt;Cache strategies&lt;/li&gt;
		&lt;/ol&gt;
		&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
&lt;/ol&gt;


&lt;ul&gt;
	&lt;li&gt;READ_ONLY (DEFAULT)   : ReadOnly cache can do reads, inserts and deletes, cannot perform updates or employ any locks.&lt;/li&gt;
	&lt;li&gt;NONSTRICT_READ_WRITE  : Nonstrict Read Write Cache doesn&#8217;t employ any locks but can do reads, inserts , updates and deletes.&lt;/li&gt;
	&lt;li&gt;NONSTRICT_READ_WRITE  : Read Write cache employs locks the entity before update/delete.&lt;/li&gt;
&lt;/ul&gt;



&lt;ol&gt;
	&lt;li&gt;
	&lt;ol&gt;
		&lt;li&gt;
		&lt;ol&gt;
			&lt;li&gt;classes / interfaces&lt;/li&gt;
		&lt;/ol&gt;
		&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
&lt;/ol&gt;


&lt;ul&gt;
	&lt;li&gt;*&lt;b&gt;Region&lt;/b&gt;* :&lt;br/&gt;
    Defines a contract for accessing a entity/collection data cache. (Doesn&#8217;t employ any locks)&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
	&lt;li&gt;*&lt;b&gt;ConcurrentRegion&lt;/b&gt;* :&lt;br/&gt;
    Defines contract for concurrently managed data region. (Locks the data before update/delete.)&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
	&lt;li&gt;*&lt;b&gt;RegionAccess&lt;/b&gt;* :&lt;br/&gt;
    Defines a contract to access a cache region&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
	&lt;li&gt;*&lt;b&gt;ConcurrentRegionAccess&lt;/b&gt;* :&lt;br/&gt;
    Defines contract for regions which hold concurrently managed data.&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
	&lt;li&gt;*&lt;b&gt;CacheKey / EntityCacheKey / CollectionCacheKey/ QueryCacheKey&lt;/b&gt;*:&lt;br/&gt;
    Defines entity / collection key to be stored in the cache region.&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
	&lt;li&gt;*&lt;b&gt;EntityEntryStructure / CollectionEntryStructure&lt;/b&gt;*&lt;br/&gt;
    Build cache entries and rebuild entities/colection from cache&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
	&lt;li&gt;*&lt;b&gt;AccessProvider&lt;/b&gt;*&lt;br/&gt;
    Build RegionAccess based on entity / collection cache configuration&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Collection Caching&lt;/p&gt;




&lt;p&gt;The most common use case is to cache entities. But we can also cache relationships.&#160;&lt;br/&gt;
A &#8220;collection cache&#8221; caches the primary keys of entities that are members of a collection (OneToMany/ManyToMany).&#160;&lt;br/&gt;
and each element will be cached into its region.&lt;/p&gt;




&lt;p&gt;Only identifiers will be cached for collection. When a collection is read from the second level cache it will create proxies based on the cached identifiers, if the application needs to access an element, Doctrine will go to the cache to load the element data.&lt;/p&gt;

&lt;ol&gt;
	&lt;li&gt;
	&lt;ol&gt;
		&lt;li&gt;
		&lt;ol&gt;
			&lt;li&gt;OPERATIONS&lt;/li&gt;
		&lt;/ol&gt;
		&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
&lt;/ol&gt;



&lt;ol&gt;
	&lt;li&gt;
	&lt;ol&gt;
		&lt;li&gt;
		&lt;ol&gt;
			&lt;li&gt;
			&lt;ol&gt;
				&lt;li&gt;INSERT :&lt;/li&gt;
			&lt;/ol&gt;
			&lt;/li&gt;
		&lt;/ol&gt;
		&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;    *********************************************************************************************&lt;br/&gt;
    UnitOfWork#commit&lt;br/&gt;
        Connection#beginTransaction&lt;br/&gt;
        Persister#executeInserts&lt;br/&gt;
        Connection#commit&lt;br/&gt;
        Persister#afterTransactionComplete&lt;br/&gt;
            -&amp;gt; EntityRegionAccessStrategy#afterInsert&lt;br/&gt;
    *********************************************************************************************&lt;br/&gt;
    METHOD      | READ-ONLY             | NONSTRICT-READ-WRITE      | READ-WRITE                |&lt;br/&gt;
    ---------------------------------------------------------------------------------------------&lt;br/&gt;
    afterInsert | add item to the cache | add item to the cache     | add item to the cache     |&lt;br/&gt;
    ---------------------------------------------------------------------------------------------&lt;/p&gt;


&lt;ol&gt;
	&lt;li&gt;
	&lt;ol&gt;
		&lt;li&gt;
		&lt;ol&gt;
			&lt;li&gt;
			&lt;ol&gt;
				&lt;li&gt;UPDATE :&lt;/li&gt;
			&lt;/ol&gt;
			&lt;/li&gt;
		&lt;/ol&gt;
		&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;    *********************************************************************************************&lt;br/&gt;
    UnitOfWork#commit&lt;br/&gt;
        Connection#beginTransaction&lt;br/&gt;
        Persister#update&lt;br/&gt;
            -&amp;gt; TransactionalRegionAccess#lockItem&lt;br/&gt;
            -&amp;gt; execute&lt;br/&gt;
        Connection#commit&lt;br/&gt;
        Persister#afterTransactionComplete&lt;br/&gt;
            -&amp;gt; RegionAccess#afterUpdate&lt;br/&gt;
            -&amp;gt; TransactionalRegionAccess#unlockItem&lt;br/&gt;
    *********************************************************************************************&lt;br/&gt;
    METHOD      | READ-ONLY             | NONSTRICT-READ-WRITE      | READ-WRITE                |&lt;br/&gt;
    ---------------------------------------------------------------------------------------------&lt;br/&gt;
    lockItem    |                       |                           | lock item                 |&lt;br/&gt;
    ---------------------------------------------------------------------------------------------&lt;br/&gt;
    afterUpdate | throws exception      | update item cache         | update item cache         |&lt;br/&gt;
    ---------------------------------------------------------------------------------------------&lt;br/&gt;
    unlockItem  |                       |                           | unlock item               |&lt;br/&gt;
    ---------------------------------------------------------------------------------------------&lt;/p&gt;


&lt;ol&gt;
	&lt;li&gt;
	&lt;ol&gt;
		&lt;li&gt;
		&lt;ol&gt;
			&lt;li&gt;
			&lt;ol&gt;
				&lt;li&gt;DELETE :&lt;/li&gt;
			&lt;/ol&gt;
			&lt;/li&gt;
		&lt;/ol&gt;
		&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;    *********************************************************************************************&lt;br/&gt;
    UnitOfWork#commit&lt;br/&gt;
        Connection#beginTransaction&lt;br/&gt;
        Persister#delete&lt;br/&gt;
            -&amp;gt; TransactionalRegionAccess#lockItem&lt;br/&gt;
            -&amp;gt; execute&lt;br/&gt;
        Connection#commit&lt;br/&gt;
        Persister#afterTransactionComplete&lt;br/&gt;
            -&amp;gt; RegionAccess#evict&lt;br/&gt;
    *********************************************************************************************&lt;br/&gt;
    METHOD      | READ-ONLY             | NONSTRICT-READ-WRITE      | READ-WRITE                |&lt;br/&gt;
    ---------------------------------------------------------------------------------------------&lt;br/&gt;
    lockItem    |                       |                           | lock item                 |&lt;br/&gt;
    ---------------------------------------------------------------------------------------------&lt;br/&gt;
    evict       | remove item cache     | remove item cache         | remove item cache         |&lt;br/&gt;
    ---------------------------------------------------------------------------------------------&lt;/p&gt;


&lt;ol&gt;
	&lt;li&gt;
	&lt;ol&gt;
		&lt;li&gt;
		&lt;ol&gt;
			&lt;li&gt;
			&lt;ol&gt;
				&lt;li&gt;USAGE :&lt;/li&gt;
			&lt;/ol&gt;
			&lt;/li&gt;
		&lt;/ol&gt;
		&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
&lt;/ol&gt;


&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
```php
&amp;lt;?php

/**
 * @Entity
 * @Cache(&lt;span class=&quot;code-quote&quot;&gt;&quot;NONSTRICT_READ_WRITE&quot;&lt;/span&gt;)
 */
class State
{
    /**
     * @Id
     * @GeneratedValue
     * @Column(type=&lt;span class=&quot;code-quote&quot;&gt;&quot;integer&quot;&lt;/span&gt;)
     */
    &lt;span class=&quot;code-keyword&quot;&gt;protected&lt;/span&gt; $id;
    /**
     * @Column
     */
    &lt;span class=&quot;code-keyword&quot;&gt;protected&lt;/span&gt; $name;
    /**
     * @Cache()
     * @ManyToOne(targetEntity=&lt;span class=&quot;code-quote&quot;&gt;&quot;Country&quot;&lt;/span&gt;)
     * @JoinColumn(name=&lt;span class=&quot;code-quote&quot;&gt;&quot;country_id&quot;&lt;/span&gt;, referencedColumnName=&lt;span class=&quot;code-quote&quot;&gt;&quot;id&quot;&lt;/span&gt;)
     */
    &lt;span class=&quot;code-keyword&quot;&gt;protected&lt;/span&gt; $country;
    /**
     * @Cache()
     * @OneToMany(targetEntity=&lt;span class=&quot;code-quote&quot;&gt;&quot;City&quot;&lt;/span&gt;, mappedBy=&lt;span class=&quot;code-quote&quot;&gt;&quot;state&quot;&lt;/span&gt;)
     */
    &lt;span class=&quot;code-keyword&quot;&gt;protected&lt;/span&gt; $cities;
}
```

```php
&amp;lt;?php

$em-&amp;gt;persist(&lt;span class=&quot;code-keyword&quot;&gt;new&lt;/span&gt; State($name, $country));
$em-&amp;gt;flush();                                &lt;span class=&quot;code-comment&quot;&gt;// Put into cache
&lt;/span&gt;
$em-&amp;gt;clear();                                &lt;span class=&quot;code-comment&quot;&gt;// Clear entity manager
&lt;/span&gt;
$state   = $em-&amp;gt;find(&apos;Entity\State&apos;, 1);     &lt;span class=&quot;code-comment&quot;&gt;// Retreive item from cache
&lt;/span&gt;$country = $state-&amp;gt;getCountry();             &lt;span class=&quot;code-comment&quot;&gt;// Retreive item from cache
&lt;/span&gt;$cities  = $state-&amp;gt;getCities();              &lt;span class=&quot;code-comment&quot;&gt;// Load from database and put into cache
&lt;/span&gt;
$state-&amp;gt;setName(&lt;span class=&quot;code-quote&quot;&gt;&quot;New Name&quot;&lt;/span&gt;);
$em-&amp;gt;persist($state);
$em-&amp;gt;flush();                                &lt;span class=&quot;code-comment&quot;&gt;// Update item cache
&lt;/span&gt;
$em-&amp;gt;clear();                                &lt;span class=&quot;code-comment&quot;&gt;// Clear entity manager
&lt;/span&gt;
$em-&amp;gt;find(&apos;Entity\State&apos;, 1)-&amp;gt;getCities();   &lt;span class=&quot;code-comment&quot;&gt;// Retreive from cache
&lt;/span&gt;

$em-&amp;gt;getCache()-&amp;gt;containsEntity(&apos;Entity\State&apos;, $state-&amp;gt;getId())  &lt;span class=&quot;code-comment&quot;&gt;// Check &lt;span class=&quot;code-keyword&quot;&gt;if&lt;/span&gt; the cache exists
&lt;/span&gt;$em-&amp;gt;getCache()-&amp;gt;evictEntity(&apos;Entity\State&apos;, $state-&amp;gt;getId());    &lt;span class=&quot;code-comment&quot;&gt;// Remove an entity from cache
&lt;/span&gt;$em-&amp;gt;getCache()-&amp;gt;evictEntityRegion(&apos;Entity\State&apos;);               &lt;span class=&quot;code-comment&quot;&gt;// Remove all entities from cache
&lt;/span&gt;
$em-&amp;gt;getCache()-&amp;gt;containsCollection(&apos;Entity\State&apos;, &apos;cities&apos;, $state-&amp;gt;getId());   &lt;span class=&quot;code-comment&quot;&gt;// Check &lt;span class=&quot;code-keyword&quot;&gt;if&lt;/span&gt; the cache exists        
&lt;/span&gt;$em-&amp;gt;getCache()-&amp;gt;evictCollection(&apos;Entity\State&apos;, &apos;cities&apos;, $state-&amp;gt;getId());      &lt;span class=&quot;code-comment&quot;&gt;// Remove an entity collection from cache
&lt;/span&gt;$em-&amp;gt;getCache()-&amp;gt;evictCollectionRegion(&apos;Entity\State&apos;, &apos;cities&apos;);                 &lt;span class=&quot;code-comment&quot;&gt;// Remove all collections from cache
&lt;/span&gt;
```
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
	&lt;li&gt;
	&lt;ol&gt;
		&lt;li&gt;
		&lt;ol&gt;
			&lt;li&gt;
			&lt;ol&gt;
				&lt;li&gt;TODO :&lt;/li&gt;
			&lt;/ol&gt;
			&lt;/li&gt;
		&lt;/ol&gt;
		&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
	&lt;li&gt;handle many to many collection&lt;/li&gt;
	&lt;li&gt;handle inheritance&lt;/li&gt;
	&lt;li&gt;remove/add colection items on update&lt;/li&gt;
	&lt;li&gt;improve region tests&lt;/li&gt;
	&lt;li&gt;improve access strategy tests&lt;/li&gt;
	&lt;li&gt;implement xml / yml / php drivers&lt;/li&gt;
	&lt;li&gt;implement transaction region&lt;/li&gt;
	&lt;li&gt;implement transaction  access strategy&lt;/li&gt;
	&lt;li&gt;.... ????&lt;/li&gt;
&lt;/ul&gt;
</description>
                <environment></environment>
            <key id="14481">DDC-2295</key>
            <summary>[GH-580] Second cache level POC</summary>
                <type id="2" iconUrl="http://www.doctrine-project.org/jira/images/icons/issuetypes/newfeature.png">New Feature</type>
                                <priority id="3" iconUrl="http://www.doctrine-project.org/jira/images/icons/priorities/major.png">Major</priority>
                    <status id="1" iconUrl="http://www.doctrine-project.org/jira/images/icons/statuses/open.png">Open</status>
                    <resolution id="-1">Unresolved</resolution>
                    <security id="10000">All</security>
                        <assignee username="beberlei">Benjamin Eberlei</assignee>
                                <reporter username="beberlei">Benjamin Eberlei</reporter>
                        <labels>
                    </labels>
                <created>Thu, 14 Feb 2013 01:01:12 +0000</created>
                <updated>Thu, 14 Mar 2013 21:36:42 +0000</updated>
                                                                            <due></due>
                    <votes>0</votes>
                        <watches>1</watches>
                                <attachments>
                </attachments>
            <subtasks>
        </subtasks>
        </item>
</channel>
</rss>