Skip to content

Commit

Permalink
Adding improved synchronization process
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Vison committed May 6, 2018
1 parent d540715 commit 36c73b5
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 55 deletions.
17 changes: 17 additions & 0 deletions Annotations/SyncParent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace NTI\SyncBundle\Annotations;
use Doctrine\Common\Annotations\Annotation\Required;

/**
* Class SyncParent
* @package NTI\SyncBundle\Annotations
* @Annotation
*/
class SyncParent {
/**
* @var string
* @Required()
*/
public $getter;
}
93 changes: 39 additions & 54 deletions EventListener/DoctrineEventSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@

namespace NTI\SyncBundle\EventListener;

use AppBundle\Entity\Empanada\Empanada;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\UnitOfWork;
use NTI\SyncBundle\Annotations\SyncParent;
use NTI\SyncBundle\Interfaces\SyncEntityInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class DoctrineEventSubscriber implements EventSubscriber
{
private $container;
private $syncService;

public function __construct(ContainerInterface $container) {
public function __construct(ContainerInterface $container)
{
$this->container = $container;
$this->syncService = $this->container->get('nti.sync');
}
Expand All @@ -28,72 +34,51 @@ public function getSubscribedEvents()

public function onFlush(OnFlushEventArgs $args)
{

$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();

$somethingChanged = false;

$identityMap = $uow->getIdentityMap();

// ehhehehehee LOL
$deletedEntities = count($uow->getScheduledEntityDeletions()) > 0;
$insertedEntities = count($uow->getScheduledEntityInsertions()) > 0;

foreach($identityMap as $map) {
foreach($map as $object) {
$changes = $uow->getEntityChangeSet($object);
if(count($changes) > 1 || (count($changes) > 0 && !isset($changes["lastTimestamp"]) && !isset($changes["lastLogin"]))) {
$somethingChanged = true;
break;
}
}

if($somethingChanged) {
break;
foreach ($uow->getScheduledEntityUpdates() as $entity) {
// Check if the entity should be synchronized
if (!($entity instanceof SyncEntityInterface)) {
continue;
}
$this->processEntity($em, $entity);
}

if($deletedEntities || $insertedEntities)
$somethingChanged = true;

foreach ($uow->getScheduledEntityUpdates() as $keyEntity => $entity) {
$changes = $uow->getEntityChangeSet($entity);

if(count($changes) == 1 && isset($changes["lastTimestamp"]) && !isset($changes["lastLogin"]) && !$somethingChanged) {
$oid = spl_object_hash($entity);
$uow->clearEntityChangeSet($oid);
} else {
$this->handleEntityChange($em, $entity);
}
}
}

foreach ($uow->getScheduledEntityInsertions() as $keyEntity => $entity) {
$this->handleEntityChange($em, $entity);
}
public function preRemove(LifecycleEventArgs $args)
{

}

public function preRemove(LifecycleEventArgs $args) {
$entity = $args->getEntity();
$class = get_class($entity);
$id = null;
private function processEntity(EntityManagerInterface $em, $entity)
{
$uow = $em->getUnitOfWork();

if(method_exists($entity, 'getId')) {
$id = $entity->getId();
}
$timestamp = time();

$this->syncService->addToDeleteSyncState($class, $id);
}
// Check if this class itself has a lastTimestamp
if(method_exists($entity, 'setLastTimestamp')) {
$entity->setLastTimestamp($timestamp);
$uow->computeChangeSet($em->getClassMetadata(get_class($entity)), $entity);
}

private function handleEntityChange(EntityManagerInterface $em, $entity) {
if(method_exists($entity, 'getLastTimestamp')) {
$timestamp = $entity->getLastTimestamp() ?? time();
} else {
$timestamp = time();
// Check if there are any relationships that should notified
$annotationReader = new AnnotationReader();
$reflection = new \ReflectionClass(get_class($entity));

/** @var \ReflectionProperty $property */
foreach ($reflection->getProperties() as $property) {
/** @var SyncParent $annotation */
if (null !== ($annotation = $annotationReader->getPropertyAnnotation($property, SyncParent::class))) {
$getter = $annotation->getter;
$parent = $entity->$getter();
if($parent instanceof SyncEntityInterface) {
$this->processEntity($em, $parent);
}
}
}
$class = get_class($entity);
$this->syncService->updateSyncState($em, $class, $timestamp);
}


}
6 changes: 6 additions & 0 deletions Interfaces/SyncEntityInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

namespace NTI\SyncBundle\Interfaces;

interface SyncEntityInterface {
}
2 changes: 1 addition & 1 deletion Service/SyncService.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public function getFromMappings($mappings) {
'changes' => $result["data"],
'deletes' => json_decode($this->container->get('jms_serializer')->serialize($deletes, 'json'), true),
'newItems' => json_decode($this->container->get('jms_serializer')->serialize($newItems, 'json'), true),
'failedItems' => json_decode($this->container->get('jms_serializer')->serialize($failedItems, 'json'), true),
'failedItems' => json_decode($this->container->get('jms_serializer')->serialize($failedItems, 'json'), true),
SyncState::REAL_LAST_TIMESTAMP => $result[SyncState::REAL_LAST_TIMESTAMP],
);
}
Expand Down

0 comments on commit 36c73b5

Please sign in to comment.