diff --git a/lib/Alchemy/Phrasea/WorkerManager/Provider/AlchemyWorkerServiceProvider.php b/lib/Alchemy/Phrasea/WorkerManager/Provider/AlchemyWorkerServiceProvider.php index 22b20b8be2..de66cb78a1 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Provider/AlchemyWorkerServiceProvider.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Provider/AlchemyWorkerServiceProvider.php @@ -73,7 +73,6 @@ class AlchemyWorkerServiceProvider implements PluginProviderInterface $app['elasticsearch.indexer'] )) ->setApplicationBox($app['phraseanet.appbox']) - ->setEntityManagerLocator(new LazyLocator($app, 'orm.em')) ; })); diff --git a/lib/Alchemy/Phrasea/WorkerManager/Subscriber/RecordSubscriber.php b/lib/Alchemy/Phrasea/WorkerManager/Subscriber/RecordSubscriber.php index fb4ef41ba5..8c60604299 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Subscriber/RecordSubscriber.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Subscriber/RecordSubscriber.php @@ -9,7 +9,10 @@ use Alchemy\Phrasea\Core\Event\Record\MetadataChangedEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvent; use Alchemy\Phrasea\Core\Event\Record\RecordEvents; use Alchemy\Phrasea\Core\Event\Record\SubdefinitionCreateEvent; +use Alchemy\Phrasea\Core\PhraseaTokens; use Alchemy\Phrasea\Databox\Subdef\MediaSubdefRepository; +use Alchemy\Phrasea\Model\Entities\WorkerRunningJob; +use Alchemy\Phrasea\Model\Repositories\WorkerRunningJobRepository; use Alchemy\Phrasea\WorkerManager\Event\StoryCreateCoverEvent; use Alchemy\Phrasea\WorkerManager\Event\SubdefinitionCreationFailureEvent; use Alchemy\Phrasea\WorkerManager\Event\SubdefinitionWritemetaEvent; @@ -35,6 +38,10 @@ class RecordSubscriber implements EventSubscriberInterface * @var callable */ private $appboxLocator; + /** + * @var WorkerRunningJobRepository + */ + private $repoWorker; public function __construct(Application $app, callable $appboxLocator) { @@ -42,6 +49,7 @@ class RecordSubscriber implements EventSubscriberInterface $this->workerResolver = $app['alchemy_worker.type_based_worker_resolver']; $this->app = $app; $this->appboxLocator = $appboxLocator; + $this->repoWorker = $app['repo.worker-running-job']; } public function onSubdefinitionCreate(SubdefinitionCreateEvent $event) @@ -96,6 +104,23 @@ class RecordSubscriber implements EventSubscriberInterface ] ]; + $em = $this->repoWorker->getEntityManager(); + $workerRunningJob = $this->repoWorker->findOneBy([ + 'databoxId' => $event->getRecord()->getDataboxId(), + 'recordId' => $event->getRecord()->getRecordId(), + 'work' => PhraseaTokens::MAKE_SUBDEF, + 'workOn' => $event->getSubdefName() + ]); + + $em->beginTransaction(); + try { + $em->remove($workerRunningJob); + $em->flush(); + $em->commit(); + } catch (\Exception $e) { + $em->rollback(); + } + $this->messagePublisher->publishMessage( $payload, MessagePublisher::RETRY_SUBDEF_QUEUE, @@ -198,6 +223,25 @@ class RecordSubscriber implements EventSubscriberInterface ); $this->messagePublisher->pushLog($logMessage); + $jeton = ($event->getSubdefName() == "document") ? PhraseaTokens::WRITE_META_DOC : PhraseaTokens::WRITE_META_SUBDEF; + + $em = $this->repoWorker->getEntityManager(); + $workerRunningJob = $this->repoWorker->findOneBy([ + 'databoxId' => $event->getRecord()->getDataboxId(), + 'recordId' => $event->getRecord()->getRecordId(), + 'work' => $jeton, + 'workOn' => $event->getSubdefName() + ]); + + $em->beginTransaction(); + try { + $em->remove($workerRunningJob); + $em->flush(); + $em->commit(); + } catch (\Exception $e) { + $em->rollback(); + } + $this->messagePublisher->publishMessage( $payload, MessagePublisher::RETRY_METADATAS_QUEUE, diff --git a/lib/Alchemy/Phrasea/WorkerManager/Worker/SubdefCreationWorker.php b/lib/Alchemy/Phrasea/WorkerManager/Worker/SubdefCreationWorker.php index efe9ec4958..9a769e222d 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Worker/SubdefCreationWorker.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Worker/SubdefCreationWorker.php @@ -21,7 +21,6 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; class SubdefCreationWorker implements WorkerInterface { use ApplicationBoxAware; - use EntityManagerAware; private $subdefGenerator; @@ -84,7 +83,7 @@ class SubdefCreationWorker implements WorkerInterface } // tell that a file is in used to create subdef - $em = $this->getEntityManager(); + $em = $this->repoWorker->getEntityManager(); $em->beginTransaction(); try { @@ -107,76 +106,57 @@ class SubdefCreationWorker implements WorkerInterface $em->rollback(); } - try { - $this->subdefGenerator->setLogger($this->logger); + $this->subdefGenerator->setLogger($this->logger); - $this->subdefGenerator->generateSubdefs($record, $wantedSubdef); + $this->subdefGenerator->generateSubdefs($record, $wantedSubdef); - // begin to check if the subdef is successfully generated - $subdef = $record->getDatabox()->get_subdef_structure()->getSubdefGroup($record->getType())->getSubdef($payload['subdefName']); - $filePathToCheck = null; + // begin to check if the subdef is successfully generated + $subdef = $record->getDatabox()->get_subdef_structure()->getSubdefGroup($record->getType())->getSubdef($payload['subdefName']); + $filePathToCheck = null; - if ($record->has_subdef($payload['subdefName']) ) { - $filePathToCheck = $record->get_subdef($payload['subdefName'])->getRealPath(); - } - - $filePathToCheck = $this->filesystem->generateSubdefPathname($record, $subdef, $filePathToCheck); - - if (!$this->filesystem->exists($filePathToCheck)) { - - $count = isset($payload['count']) ? $payload['count'] + 1 : 2 ; - - $this->dispatcher->dispatch(WorkerEvents::SUBDEFINITION_CREATION_FAILURE, new SubdefinitionCreationFailureEvent( - $record, - $payload['subdefName'], - 'Subdef generation failed !', - $count - )); - - $this->subdefGenerator->setLogger($oldLogger); - return ; - } - // checking ended - - // order to write meta for the subdef if needed - $this->dispatcher->dispatch(WorkerEvents::SUBDEFINITION_WRITE_META, new SubdefinitionWritemetaEvent($record, $payload['subdefName'])); - - $this->subdefGenerator->setLogger($oldLogger); - - // update jeton when subdef is created - $this->updateJeton($record); - - $parents = $record->get_grouping_parents(); - - // create a cover for a story - // used when uploaded via uploader-service and grouped as a story - if (!$parents->is_empty() && isset($payload['status']) && $payload['status'] == MessagePublisher::NEW_RECORD_MESSAGE && in_array($payload['subdefName'], array('thumbnail', 'preview'))) { - foreach ($parents->get_elements() as $story) { - if (self::checkIfFirstChild($story, $record)) { - $data = implode('_', [$databoxId, $story->getRecordId(), $recordId, $payload['subdefName']]); - - $this->dispatcher->dispatch(WorkerEvents::STORY_CREATE_COVER, new StoryCreateCoverEvent($data)); - } - } - } - } catch (\Exception $e) { - $payload = [ - 'message_type' => MessagePublisher::SUBDEF_CREATION_TYPE, - 'payload' => $payload - ]; - $this->messagePublisher->publishMessage($payload, MessagePublisher::DELAYED_SUBDEF_QUEUE); - - $em->beginTransaction(); - try { - $workerRunningJob->setStatus(WorkerRunningJob::FINISHED); - $em->persist($workerRunningJob); - $em->flush(); - $em->commit(); - } catch (\Exception $e) { - $em->rollback(); - } + if ($record->has_subdef($payload['subdefName']) ) { + $filePathToCheck = $record->get_subdef($payload['subdefName'])->getRealPath(); } + $filePathToCheck = $this->filesystem->generateSubdefPathname($record, $subdef, $filePathToCheck); + + if (!$this->filesystem->exists($filePathToCheck)) { + + $count = isset($payload['count']) ? $payload['count'] + 1 : 2 ; + + $this->dispatcher->dispatch(WorkerEvents::SUBDEFINITION_CREATION_FAILURE, new SubdefinitionCreationFailureEvent( + $record, + $payload['subdefName'], + 'Subdef generation failed !', + $count + )); + + $this->subdefGenerator->setLogger($oldLogger); + return ; + } + // checking ended + + // order to write meta for the subdef if needed + $this->dispatcher->dispatch(WorkerEvents::SUBDEFINITION_WRITE_META, new SubdefinitionWritemetaEvent($record, $payload['subdefName'])); + + $this->subdefGenerator->setLogger($oldLogger); + + // update jeton when subdef is created + $this->updateJeton($record); + + $parents = $record->get_grouping_parents(); + + // create a cover for a story + // used when uploaded via uploader-service and grouped as a story + if (!$parents->is_empty() && isset($payload['status']) && $payload['status'] == MessagePublisher::NEW_RECORD_MESSAGE && in_array($payload['subdefName'], array('thumbnail', 'preview'))) { + foreach ($parents->get_elements() as $story) { + if (self::checkIfFirstChild($story, $record)) { + $data = implode('_', [$databoxId, $story->getRecordId(), $recordId, $payload['subdefName']]); + + $this->dispatcher->dispatch(WorkerEvents::STORY_CREATE_COVER, new StoryCreateCoverEvent($data)); + } + } + } // update elastic $this->indexer->flushQueue(); diff --git a/lib/Alchemy/Phrasea/WorkerManager/Worker/WriteMetadatasWorker.php b/lib/Alchemy/Phrasea/WorkerManager/Worker/WriteMetadatasWorker.php index 5191f325e9..fc2c7c7215 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Worker/WriteMetadatasWorker.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Worker/WriteMetadatasWorker.php @@ -107,165 +107,146 @@ class WriteMetadatasWorker implements WorkerInterface $em->rollback(); } - try { - $record = $databox->get_record($recordId); + $record = $databox->get_record($recordId); - $subdef = $record->get_subdef($payload['subdefName']); + $subdef = $record->get_subdef($payload['subdefName']); - if ($subdef->is_physically_present()) { - $metadata = new MetadataBag(); + if ($subdef->is_physically_present()) { + $metadata = new MetadataBag(); - // add Uuid in metadatabag - if ($record->getUuid()) { - $metadata->add( - new Metadata( - new Tag\XMPExif\ImageUniqueID(), - new Mono($record->getUuid()) - ) - ); - $metadata->add( - new Metadata( - new Tag\ExifIFD\ImageUniqueID(), - new Mono($record->getUuid()) - ) - ); - $metadata->add( - new Metadata( - new Tag\IPTC\UniqueDocumentID(), - new Mono($record->getUuid()) - ) - ); + // add Uuid in metadatabag + if ($record->getUuid()) { + $metadata->add( + new Metadata( + new Tag\XMPExif\ImageUniqueID(), + new Mono($record->getUuid()) + ) + ); + $metadata->add( + new Metadata( + new Tag\ExifIFD\ImageUniqueID(), + new Mono($record->getUuid()) + ) + ); + $metadata->add( + new Metadata( + new Tag\IPTC\UniqueDocumentID(), + new Mono($record->getUuid()) + ) + ); + } + + // read document fields and add to metadatabag + $caption = $record->get_caption(); + foreach ($databox->get_meta_structure() as $fieldStructure) { + + $tagName = $fieldStructure->get_tag()->getTagname(); + $fieldName = $fieldStructure->get_name(); + + // skip fields with no src + if ($tagName == '' || $tagName == 'Phraseanet:no-source') { + continue; } - // read document fields and add to metadatabag - $caption = $record->get_caption(); - foreach ($databox->get_meta_structure() as $fieldStructure) { - - $tagName = $fieldStructure->get_tag()->getTagname(); - $fieldName = $fieldStructure->get_name(); - - // skip fields with no src - if ($tagName == '' || $tagName == 'Phraseanet:no-source') { - continue; - } - - // check exiftool known tags to skip Phraseanet:tf-* - try { - $tag = TagFactory::getFromRDFTagname($tagName); - if(!$tag->isWritable()) { - continue; - } - } catch (TagUnknown $e) { - continue; - } - - try { - $field = $caption->get_field($fieldName); - $fieldValues = $field->get_values(); - - if ($fieldStructure->is_multi()) { - $values = array(); - foreach ($fieldValues as $value) { - $values[] = $this->removeNulChar($value->getValue()); - } - - $value = new Multi($values); - } else { - $fieldValue = array_pop($fieldValues); - $value = $this->removeNulChar($fieldValue->getValue()); - - // fix the dates edited into phraseanet - if($fieldStructure->get_type() === $fieldStructure::TYPE_DATE) { - try { - $value = self::fixDate($value); // will return NULL if the date is not valid - } - catch (\Exception $e) { - $value = null; // do NOT write back to iptc - } - } - - if($value !== null) { // do not write invalid dates - $value = new Mono($value); - } - } - } catch(\Exception $e) { - // the field is not set in the record, erase it - if ($fieldStructure->is_multi()) { - $value = new Multi(array('')); - } - else { - $value = new Mono(''); - } - } - - if($value !== null) { // do not write invalid data - $metadata->add( - new Metadata($fieldStructure->get_tag(), $value) - ); - } - } - - $this->writer->reset(); - - if ($MWG) { - $this->writer->setModule(Writer::MODULE_MWG, true); - } - - $this->writer->erase($subdef->get_name() != 'document' || $clearDoc, true); - - // write meta in file + // check exiftool known tags to skip Phraseanet:tf-* try { - $this->writer->write($subdef->getRealPath(), $metadata); - - $this->messagePublisher->pushLog(sprintf('meta written for sbasid=%1$d - recordid=%2$d (%3$s)', $databox->get_sbas_id(), $recordId, $subdef->get_name() )); - } catch (PHPExiftoolException $e) { - $workerMessage = sprintf('meta NOT written for sbasid=%1$d - recordid=%2$d (%3$s) because "%s"', $databox->get_sbas_id(), $recordId, $subdef->get_name() , $e->getMessage()); - $this->logger->error($workerMessage); - - $count = isset($payload['count']) ? $payload['count'] + 1 : 2 ; - - $this->dispatch(WorkerEvents::SUBDEFINITION_WRITE_META, new SubdefinitionWritemetaEvent( - $record, - $payload['subdefName'], - SubdefinitionWritemetaEvent::FAILED, - $workerMessage, - $count - )); + $tag = TagFactory::getFromRDFTagname($tagName); + if(!$tag->isWritable()) { + continue; + } + } catch (TagUnknown $e) { + continue; } - // mark write metas finished - $this->updateJeton($record); - } else { + try { + $field = $caption->get_field($fieldName); + $fieldValues = $field->get_values(); + + if ($fieldStructure->is_multi()) { + $values = array(); + foreach ($fieldValues as $value) { + $values[] = $this->removeNulChar($value->getValue()); + } + + $value = new Multi($values); + } else { + $fieldValue = array_pop($fieldValues); + $value = $this->removeNulChar($fieldValue->getValue()); + + // fix the dates edited into phraseanet + if($fieldStructure->get_type() === $fieldStructure::TYPE_DATE) { + try { + $value = self::fixDate($value); // will return NULL if the date is not valid + } + catch (\Exception $e) { + $value = null; // do NOT write back to iptc + } + } + + if($value !== null) { // do not write invalid dates + $value = new Mono($value); + } + } + } catch(\Exception $e) { + // the field is not set in the record, erase it + if ($fieldStructure->is_multi()) { + $value = new Multi(array('')); + } + else { + $value = new Mono(''); + } + } + + if($value !== null) { // do not write invalid data + $metadata->add( + new Metadata($fieldStructure->get_tag(), $value) + ); + } + } + + $this->writer->reset(); + + if ($MWG) { + $this->writer->setModule(Writer::MODULE_MWG, true); + } + + $this->writer->erase($subdef->get_name() != 'document' || $clearDoc, true); + + // write meta in file + try { + $this->writer->write($subdef->getRealPath(), $metadata); + + $this->messagePublisher->pushLog(sprintf('meta written for sbasid=%1$d - recordid=%2$d (%3$s)', $databox->get_sbas_id(), $recordId, $subdef->get_name() )); + } catch (PHPExiftoolException $e) { + $workerMessage = sprintf('meta NOT written for sbasid=%1$d - recordid=%2$d (%3$s) because "%s"', $databox->get_sbas_id(), $recordId, $subdef->get_name() , $e->getMessage()); + $this->logger->error($workerMessage); + $count = isset($payload['count']) ? $payload['count'] + 1 : 2 ; $this->dispatch(WorkerEvents::SUBDEFINITION_WRITE_META, new SubdefinitionWritemetaEvent( $record, $payload['subdefName'], SubdefinitionWritemetaEvent::FAILED, - 'Subdef is not physically present!', + $workerMessage, $count )); } - } catch(\Exception $e) { - $payload = [ - 'message_type' => MessagePublisher::WRITE_METADATAS_TYPE, - 'payload' => $payload - ]; - $this->messagePublisher->publishMessage($payload, MessagePublisher::DELAYED_METADATAS_QUEUE); + // mark write metas finished + $this->updateJeton($record); + } else { + $count = isset($payload['count']) ? $payload['count'] + 1 : 2 ; - - $em->beginTransaction(); - try { - $workerRunningJob->setStatus(WorkerRunningJob::FINISHED); - $em->persist($workerRunningJob); - $em->flush(); - $em->commit(); - } catch (\Exception $e) { - $em->rollback(); - } + $this->dispatch(WorkerEvents::SUBDEFINITION_WRITE_META, new SubdefinitionWritemetaEvent( + $record, + $payload['subdefName'], + SubdefinitionWritemetaEvent::FAILED, + 'Subdef is not physically present!', + $count + )); } + // tell that we have finished to work on this file $em->beginTransaction(); try {