Details

    • Type: New Feature New Feature
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Duplicate
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Security Level: All
    • Labels:
      None

      Description

      This issue is created automatically through a Github pull request on behalf of FabioBatSilva:

      Url: https://github.com/doctrine/doctrine2/pull/580

      Message:

      Hi guys.

      After a look into some implementations I end up with the following solution for the second level cache..

      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 :

          1. Cache strategies
      • READ_ONLY (DEFAULT) : 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.
      • NONSTRICT_READ_WRITE : Read Write cache employs locks the entity before update/delete.
          1. classes / interfaces
      • *Region* :
        Defines a contract for accessing a entity/collection data cache. (Doesn’t employ any locks)
      • *ConcurrentRegion* :
        Defines contract for concurrently managed data region. (Locks the data before update/delete.)
      • *RegionAccess* :
        Defines a contract to access a cache region
      • *ConcurrentRegionAccess* :
        Defines contract for regions which hold concurrently 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

      Collection Caching

      The most common use case is to cache entities. But we can also cache relationships. 
      A “collection cache” caches the primary keys of entities that are members of a collection (OneToMany/ManyToMany). 
      and each element will be cached into its region.

      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.

          1. OPERATIONS
            1. 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 |
      ---------------------------------------------------------------------------------------------

            1. 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 |
      ---------------------------------------------------------------------------------------------

            1. 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 |
      ---------------------------------------------------------------------------------------------

            1. USAGE :
      ```php
      <?php
      
      /**
       * @Entity
       * @Cache("NONSTRICT_READ_WRITE")
       */
      class State
      {
          /**
           * @Id
           * @GeneratedValue
           * @Column(type="integer")
           */
          protected $id;
          /**
           * @Column
           */
          protected $name;
          /**
           * @Cache()
           * @ManyToOne(targetEntity="Country")
           * @JoinColumn(name="country_id", referencedColumnName="id")
           */
          protected $country;
          /**
           * @Cache()
           * @OneToMany(targetEntity="City", mappedBy="state")
           */
          protected $cities;
      }
      ```
      
      ```php
      <?php
      
      $em->persist(new State($name, $country));
      $em->flush();                                // Put 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
      
      
      $em->getCache()->containsEntity('Entity\State', $state->getId())  // Check if the cache exists
      $em->getCache()->evictEntity('Entity\State', $state->getId());    // Remove an entity from cache
      $em->getCache()->evictEntityRegion('Entity\State');               // Remove all entities from cache
      
      $em->getCache()->containsCollection('Entity\State', 'cities', $state->getId());   // Check if the cache exists        
      $em->getCache()->evictCollection('Entity\State', 'cities', $state->getId());      // Remove an entity collection from cache
      $em->getCache()->evictCollectionRegion('Entity\State', 'cities');                 // Remove all collections from cache
      
      ```
      
            1. 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
      • .... ????

        Activity

        Hide
        Doctrine Bot added a comment -

        A related Github Pull-Request [GH-580] was closed:
        https://github.com/doctrine/doctrine2/pull/580

        Show
        Doctrine Bot added a comment - A related Github Pull-Request [GH-580] was closed: https://github.com/doctrine/doctrine2/pull/580
        Hide
        Sergii Shymko added a comment -

        Is the proposed solution going to allow to cache scalar properties of entities of specific type?

        The behavior I'm looking for is the following:

        • Certain entity fields are explicitly marked as cached via annotation or something
        • Regardless of how a partially loaded entity is acquired (EM, repository, DQL), those fields are populated with the cached data
        • Getters for those fields simply return assigned values, not causing the full entity load, similarly to identifier fields
        Show
        Sergii Shymko added a comment - Is the proposed solution going to allow to cache scalar properties of entities of specific type? The behavior I'm looking for is the following: Certain entity fields are explicitly marked as cached via annotation or something Regardless of how a partially loaded entity is acquired (EM, repository, DQL), those fields are populated with the cached data Getters for those fields simply return assigned values, not causing the full entity load, similarly to identifier fields
        Hide
        Marco Pivetta added a comment -

        Sergii Shymko no, that is not covered. That would require a major overhaul in code generation tools and it would introduce major rewrites of the internal components. It's not covered here and is not really related with implementing the L2 Cache.

        Show
        Marco Pivetta added a comment - Sergii Shymko no, that is not covered. That would require a major overhaul in code generation tools and it would introduce major rewrites of the internal components. It's not covered here and is not really related with implementing the L2 Cache.

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Benjamin Eberlei
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: