Slide 1

Slide 1 text

Demystifying Luís Cobucci
 @lcobucci https://goo.gl/oZPuRc cache in Doctrine ORM

Slide 2

Slide 2 text

Reliability https://goo.gl/1shwsY

Slide 3

Slide 3 text

Maintainability https://goo.gl/D4DvKC

Slide 4

Slide 4 text

Scalability https://goo.gl/M67mS8

Slide 5

Slide 5 text

Trade-offs https://goo.gl/L7YdSp

Slide 6

Slide 6 text

Minions of users! https://goo.gl/7MAkHZ

Slide 7

Slide 7 text

Luís Cobucci
 @lcobucci https://jobs.usabilla.com

Slide 8

Slide 8 text

Doctrine ORM? https://goo.gl/xCBz84

Slide 9

Slide 9 text

Template Message Customer Campaign 1 1 1 * * *

Slide 10

Slide 10 text

Template Message Customer Campaign 1 1 1 * * *

Slide 11

Slide 11 text

Template Message Customer Campaign 1 1 1 * * *

Slide 12

Slide 12 text

Template Message Customer Campaign 1 1 1 * * * Order matters

Slide 13

Slide 13 text

Template Message Customer Campaign 1 1 1 * * * INSERT INTO customer (name, email)
 VALUES (“Luís Cobucci”, “[email protected]”);
 SET @customer_id = LAST_INSERT_ID();

Slide 14

Slide 14 text

Template Message Customer Campaign 1 1 1 * * * INSERT INTO customer (name, email)
 VALUES (“Luís Cobucci”, “[email protected]”);
 SET @customer_id = LAST_INSERT_ID(); INSERT INTO template (name, body)
 VALUES (“Template 1”, “blah… blah… blah…”);

Slide 15

Slide 15 text

Template Message Customer Campaign 1 1 1 * * * INSERT INTO customer (name, email)
 VALUES (“Luís Cobucci”, “[email protected]”);
 SET @customer_id = LAST_INSERT_ID(); INSERT INTO template (name, body)
 VALUES (“Template 1”, “blah… blah… blah…”); INSERT INTO campaign (title, template_id, message)
 VALUES (“Test”, LAST_INSERT_ID(), “blah… blah… blah…”);

Slide 16

Slide 16 text

Template Message Customer Campaign 1 1 1 * * * INSERT INTO customer (name, email)
 VALUES (“Luís Cobucci”, “[email protected]”);
 SET @customer_id = LAST_INSERT_ID(); INSERT INTO template (name, body)
 VALUES (“Template 1”, “blah… blah… blah…”); INSERT INTO campaign (title, template_id, message)
 VALUES (“Test”, LAST_INSERT_ID(), “blah… blah… blah…”); INSERT INTO message (campaign_id, customer_id, sent)
 VALUES (LAST_INSERT_ID(), @customer_id, FALSE);

Slide 17

Slide 17 text

Template Message Customer Campaign 1 1 1 * * * INSERT INTO customer (name, email)
 VALUES (“Luís Cobucci”, “[email protected]”);
 SET @customer_id = LAST_INSERT_ID(); INSERT INTO template (name, body)
 VALUES (“Template 1”, “blah… blah… blah…”); INSERT INTO campaign (title, template_id, message)
 VALUES (“Test”, LAST_INSERT_ID(), “blah… blah… blah…”); INSERT INTO message (campaign_id, customer_id, sent)
 VALUES (LAST_INSERT_ID(), @customer_id, FALSE); Don’t forget to use a transaction!

Slide 18

Slide 18 text

EntityManager persist() flush() find() remove()

Slide 19

Slide 19 text

declare(strict_types=1); $customer = new Customer('Luís Cobucci', '[email protected]');
 $template = new Template('Template 1', 'blah… blah… blah…');
 $campaign = new Campaign($template, 'Test', 'blah… blah… blah…');
 $message = new Message($campaign, $customer);
 
 $entityManager->persist($customer); $entityManager->persist($template); $entityManager->persist($campaign); $entityManager->persist($message); $entityManager->flush();

Slide 20

Slide 20 text

EntityManager UnitOfWork DB

Slide 21

Slide 21 text

declare(strict_types=1); $customer = $entityManager->find('Customer', 2); $campaign = $entityManager->find('Campaign', 1);
 
 $entityManager->persist(new Message($campaign, $customer)); $entityManager->flush();

Slide 22

Slide 22 text

http://goo.gl/gH0hsx Amazing, right?

Slide 23

Slide 23 text

“ORMs are slow!” https://goo.gl/dRfUyZ

Slide 24

Slide 24 text

https://goo.gl/91u2rx

Slide 25

Slide 25 text

https://goo.gl/SAH57F Big ball of mud

Slide 26

Slide 26 text

https://goo.gl/d3DNXm Hydration

Slide 27

Slide 27 text

https://goo.gl/hr22Dx Outdated

Slide 28

Slide 28 text

https://goo.gl/1y3fvm Bugs…

Slide 29

Slide 29 text

https://goo.gl/cuLYT9 Bugs…

Slide 30

Slide 30 text

https://goo.gl/D3Gw7e Bugs…

Slide 31

Slide 31 text

Make it fast! https://goo.gl/6Y2kQd

Slide 32

Slide 32 text

“ a hardware or software component that stores data so future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation, or the duplicate of data stored elsewhere. Cache (computing) - Wikipedia

Slide 33

Slide 33 text

Our software Cache External API

Slide 34

Slide 34 text

Our software Cache External API 1. Give me “external.result”

Slide 35

Slide 35 text

Our software Cache External API 2. Cache miss 1. Give me “external.result”

Slide 36

Slide 36 text

Our software Cache External API 2. Cache miss 3. Give me data 1. Give me “external.result”

Slide 37

Slide 37 text

Our software Cache External API 2. Cache miss 3. Give me data 4. There you go 1. Give me “external.result”

Slide 38

Slide 38 text

Our software Cache External API 2. Cache miss 1. Give me “external.result” 3. Give me data 4. There you go 5. Store “external.result”

Slide 39

Slide 39 text

Our software Cache External API 2. Cache miss 1. Give me “external.result” 3. Give me data 4. There you go 5. Store “external.result” 6. Stored!

Slide 40

Slide 40 text

Our software Cache External API 1. Give me “external.result”

Slide 41

Slide 41 text

Our software Cache External API 2. Cache hit! 1. Give me “external.result”

Slide 42

Slide 42 text

Our software Cache External API 2. Cache hit! 1. Give me “external.result” When should we invalidate the cache?

Slide 43

Slide 43 text

“ There are two hard things in Computer Science: cache invalidation, naming things, and off-by-one errors Common sense

Slide 44

Slide 44 text

Metadata https://goo.gl/AhjBFJ

Slide 45

Slide 45 text

/** @ORM\Entity */ class Customer
 {
 /** 
 * @ORM\Id
 * @ORM\GeneratedValue 
 * @ORM\Column(type="integer")
 */ private $id;
 
 /** @ORM\Column(type="string") */
 private $name;
 
 /** @ORM\Column(type="string") */
 private $email; }

Slide 46

Slide 46 text

/** @ORM\Entity */ class Customer
 {
 /** 
 * @ORM\Id
 * @ORM\GeneratedValue 
 * @ORM\Column(type="integer")
 */ private $id;
 
 /** @ORM\Column(type="string") */
 private $name;
 
 /** @ORM\Column(type="string") */
 private $email; } ClassMetadata

Slide 47

Slide 47 text

declare(strict_types=1); use Doctrine\Common\Cache\RedisCache; use Doctrine\ORM\Configuration; $metadataCache = new RedisCache(); $configuration = new Configuration(); // … $configuration->setMetadataCacheImpl($metadataCache);

Slide 48

Slide 48 text

Query https://goo.gl/nuFRba

Slide 49

Slide 49 text

SELECT customer FROM Customer customer;

Slide 50

Slide 50 text

SELECT customer FROM Customer customer; SELECT
 c0.id AS id_0,
 c0.name AS name_1, c0.email AS email_2,
 FROM customer c0;

Slide 51

Slide 51 text

declare(strict_types=1); $builder = $entityManager->createQueryBuilder()
 ->select(‘customer’) ->from(Customer::class, ‘customer'); $query = $builder->getQuery();
 $result = $query->getResult();

Slide 52

Slide 52 text

declare(strict_types=1); use Doctrine\Common\Cache\RedisCache; use Doctrine\ORM\Configuration; $queryCache = new RedisCache(); $configuration = new Configuration(); // … $configuration->setQueryCacheImpl($queryCache);

Slide 53

Slide 53 text

declare(strict_types=1); $builder = $entityManager->createQueryBuilder()
 ->select(‘customer’) ->from(Customer::class, ‘customer'); if (isset($params[‘email’])) { $builder->where(‘customer.email = :email’)
 ->setParameter(‘email’, $params[‘email’]); } $query = $builder->getQuery();
 $result = $query->getResult();

Slide 54

Slide 54 text

Result set https://goo.gl/7yah7S

Slide 55

Slide 55 text

$query = 'SELECT COUNT(m) FROM Message m WHERE m.user = :user'; 
 $count = $entityManager->createQuery($query)
 ->setParameter('user', 1)
 ->getSingleScalarResult();

Slide 56

Slide 56 text

declare(strict_types=1); use Doctrine\Common\Cache\RedisCache; use Doctrine\ORM\Configuration; $queryCache = new RedisCache(); $configuration = new Configuration(); // … $configuration->setQueryCacheImpl($queryCache);

Slide 57

Slide 57 text

$query = 'SELECT COUNT(m) FROM Message m WHERE m.user = :user'; 
 $count = $entityManager->createQuery($query)
 ->setParameter('user', 1)
 ->useResultCache(true, 3600)
 ->getSingleScalarResult();

Slide 58

Slide 58 text

L2C https://goo.gl/8pbG3y

Slide 59

Slide 59 text

EntityManager UnitOfWork DB

Slide 60

Slide 60 text

declare(strict_types=1); use Doctrine\Common\Cache\RedisCache; use Doctrine\ORM\Cache as L2C; use Doctrine\ORM\Configuration; $level2Cache = new RedisCache(); $level2Config = new L2C\CacheConfiguration(); $level2Config->setSecondLevelCacheEnabled( new L2C\DefaultCacheFactory( new L2C\RegionsConfiguration(), $level2Cache ) ); $configuration = new Configuration(); // … $configuration->setSecondLevelCacheEnabled(true); $configuration->setSecondLevelCacheConfiguration($level2Config);

Slide 61

Slide 61 text

EntityManager UnitOfWork L2C DB

Slide 62

Slide 62 text

L2C Collection Entity Query

Slide 63

Slide 63 text

/**
 * @ORM\Entity
 * @ORM\Cache(usage="NONSTRICT_READ_WRITE")
 */ class Customer
 {
 // …
 }

Slide 64

Slide 64 text

/**
 * @ORM\Entity
 * @ORM\Cache(usage="NONSTRICT_READ_WRITE")
 */ class Customer
 {
 // …
 } READ_ONLY
 NONSTRICT_READ_WRITE
 READ_WRITE

Slide 65

Slide 65 text

/**
 * @ORM\Entity
 * @ORM\Cache(usage="NONSTRICT_READ_WRITE")
 */ class Message
 {
 // …
 
 /**
 * @ORM\ManyToOne(targetEntity="Customer") * @ORM\Cache(usage="READ_ONLY") */
 private $customer; 
 // …
 }

Slide 66

Slide 66 text

$query = ‘SELECT m FROM Message m WHERE m.customer = :id’; 
 $messages = $entityManager->createQuery($query)
 ->setParameter(‘id', 1)
 ->setCacheable(true)
 ->getResult();

Slide 67

Slide 67 text

https://goo.gl/bGP8u8 Intense traffic

Slide 68

Slide 68 text

https://goo.gl/bGP8u8 Upcoming!

Slide 69

Slide 69 text

Demystifying Luís Cobucci
 @lcobucci https://goo.gl/oZPuRc cache in Doctrine ORM

Slide 70

Slide 70 text

Thanks! @lcobucci