PHRAS-4057: log_doc - report mark as "cancel" for running_job entry (#4501)

* log_docs mark as canceled too

* PHRAS-4058 auto cancelling job

* add auto-cancelingJob in hour in the config

* add patch rc12
This commit is contained in:
Aina Sitraka
2024-04-30 12:44:14 +03:00
committed by GitHub
parent 7e3fe51a2c
commit b0eba5217c
8 changed files with 157 additions and 5 deletions

View File

@@ -367,6 +367,7 @@ geocoding-providers:
provincefields: Province provincefields: Province
countryfields: Country, Pays countryfields: Country, Pays
workers: workers:
auto-cancelingJob: 24 # period in hours, not define or null to not execute
queue: queue:
worker-queue: worker-queue:
registry: alchemy_worker.queue_registry registry: alchemy_worker.queue_registry

View File

@@ -503,7 +503,7 @@ class WorkerRunningJobRepository extends EntityRepository
]); ]);
} }
public function getRunningSinceCreated($hour = 0) public function getRunningSinceCreated($hour = 0, array $action = null)
{ {
$rsm = new ResultSetMappingBuilder($this->_em); $rsm = new ResultSetMappingBuilder($this->_em);
$rsm->addRootEntityFromClassMetadata('Alchemy\Phrasea\Model\Entities\WorkerRunningJob', 'w'); $rsm->addRootEntityFromClassMetadata('Alchemy\Phrasea\Model\Entities\WorkerRunningJob', 'w');
@@ -516,6 +516,11 @@ class WorkerRunningJobRepository extends EntityRepository
AND (TO_SECONDS(CURRENT_TIMESTAMP()) - TO_SECONDS(w.created)) > :second' AND (TO_SECONDS(CURRENT_TIMESTAMP()) - TO_SECONDS(w.created)) > :second'
; ;
if ($action != null) {
$action = join('" ,"', $action);
$sql .= ' AND work IN("' . $action . '")';
}
$q = $this->_em->createNativeQuery($sql, $rsm); $q = $this->_em->createNativeQuery($sql, $rsm);
$q->setParameters([ $q->setParameters([
'second' => $hour * 3600, 'second' => $hour * 3600,

View File

@@ -3,6 +3,7 @@
namespace Alchemy\Phrasea\WorkerManager\Controller; namespace Alchemy\Phrasea\WorkerManager\Controller;
use Alchemy\Phrasea\Application as PhraseaApplication; use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Application\Helper\DataboxLoggerAware;
use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Model\Entities\WorkerRunningJob; use Alchemy\Phrasea\Model\Entities\WorkerRunningJob;
use Alchemy\Phrasea\Model\Repositories\WorkerRunningJobRepository; use Alchemy\Phrasea\Model\Repositories\WorkerRunningJobRepository;
@@ -32,6 +33,8 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class AdminConfigurationController extends Controller class AdminConfigurationController extends Controller
{ {
use DataboxLoggerAware;
public function indexAction(PhraseaApplication $app, Request $request) public function indexAction(PhraseaApplication $app, Request $request)
{ {
return $this->render('admin/worker-manager/index.html.twig', [ return $this->render('admin/worker-manager/index.html.twig', [
@@ -223,8 +226,10 @@ class AdminConfigurationController extends Controller
$workerRunningJob = $repoWorker->find($workerId); $workerRunningJob = $repoWorker->find($workerId);
$workerRunningJob->setStatus($request->request->get('status')); $workerRunningJob->setStatus($request->request->get('status'));
$finishedDate = new \DateTime('now');
if($request->request->get('finished') == '1') { if($request->request->get('finished') == '1') {
$workerRunningJob->setFinished(new \DateTime('now'))->setFlock(null); $workerRunningJob->setFinished($finishedDate)->setFlock(null);
} }
$em = $repoWorker->getEntityManager(); $em = $repoWorker->getEntityManager();
@@ -232,6 +237,10 @@ class AdminConfigurationController extends Controller
$em->flush(); $em->flush();
if (in_array($workerRunningJob->getWork(), ['subdefCreation', 'writeMetadatas'])) {
$this->updateLogDocs($workerRunningJob, $workerRunningJob->getStatus(), $finishedDate);
}
return $this->app->json(['success' => true]); return $this->app->json(['success' => true]);
} }
@@ -250,8 +259,16 @@ class AdminConfigurationController extends Controller
{ {
/** @var WorkerRunningJobRepository $repoWorker */ /** @var WorkerRunningJobRepository $repoWorker */
$repoWorker = $this->app['repo.worker-running-job']; $repoWorker = $this->app['repo.worker-running-job'];
$workerRunningJobs = $repoWorker->getRunningSinceCreated($request->request->get('hour'), ['subdefCreation', 'writeMetadatas']);
$repoWorker->updateStatusRunningToCanceledSinceCreated($request->request->get('hour')); $repoWorker->updateStatusRunningToCanceledSinceCreated($request->request->get('hour'));
$finishedDate = new \DateTime('now');
/** @var WorkerRunningJob $workerRunningJob */
foreach ($workerRunningJobs as $workerRunningJob) {
$this->updateLogDocs($workerRunningJob, 'canceled', $finishedDate);
}
return $this->app->json(['success' => true]); return $this->app->json(['success' => true]);
} }
@@ -557,6 +574,17 @@ class AdminConfigurationController extends Controller
return $repoWorkerJob->checkPopulateStatusByDataboxIds($databoxIds); return $repoWorkerJob->checkPopulateStatusByDataboxIds($databoxIds);
} }
private function updateLogDocs(WorkerRunningJob $workerRunningJob, $status, $finishedDate)
{
$databox = $this->findDataboxById($workerRunningJob->getDataboxId());
$record = $databox->get_record($workerRunningJob->getRecordId());
$subdefName = $workerRunningJob->getWorkOn();
$action = $workerRunningJob->getWork();
$this->getDataboxLogger($databox)->initOrUpdateLogDocsFromWorker($record, $databox, $workerRunningJob, $subdefName, $action, $finishedDate, $status);
}
private function getDefaultRecordsActionsSettings() private function getDefaultRecordsActionsSettings()
{ {
return <<<EOF return <<<EOF

View File

@@ -165,7 +165,10 @@ class AlchemyWorkerServiceProvider implements PluginProviderInterface
})); }));
$app['alchemy_worker.type_based_worker_resolver']->addFactory(MessagePublisher::MAIN_QUEUE_TYPE, new CallableWorkerFactory(function () use ($app) { $app['alchemy_worker.type_based_worker_resolver']->addFactory(MessagePublisher::MAIN_QUEUE_TYPE, new CallableWorkerFactory(function () use ($app) {
return new MainQueueWorker($app['alchemy_worker.message.publisher'], $app['repo.worker-job']); return (new MainQueueWorker($app['alchemy_worker.message.publisher'], $app['repo.worker-job'], $app['repo.worker-running-job'], $app['conf']))
->setDataboxLoggerLocator($app['phraseanet.logger'])
->setApplicationBox($app['phraseanet.appbox'])
;
})); }));
$app['alchemy_worker.type_based_worker_resolver']->addFactory(MessagePublisher::FTP_TYPE, new CallableWorkerFactory(function () use ($app) { $app['alchemy_worker.type_based_worker_resolver']->addFactory(MessagePublisher::FTP_TYPE, new CallableWorkerFactory(function () use ($app) {

View File

@@ -22,7 +22,9 @@ class ControllerServiceProvider implements ControllerProviderInterface, ServiceP
public function register(Application $app) public function register(Application $app)
{ {
$app['controller.worker.admin.configuration'] = $app->share(function (PhraseaApplication $app) { $app['controller.worker.admin.configuration'] = $app->share(function (PhraseaApplication $app) {
return new AdminConfigurationController($app); return (new AdminConfigurationController($app))
->setDataboxLoggerLocator($app['phraseanet.logger'])
;
}); });
// example of route to check webhook // example of route to check webhook

View File

@@ -2,24 +2,38 @@
namespace Alchemy\Phrasea\WorkerManager\Worker; namespace Alchemy\Phrasea\WorkerManager\Worker;
use Alchemy\Phrasea\Application\Helper\ApplicationBoxAware;
use Alchemy\Phrasea\Application\Helper\DataboxLoggerAware;
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
use Alchemy\Phrasea\Model\Entities\WorkerJob; use Alchemy\Phrasea\Model\Entities\WorkerJob;
use Alchemy\Phrasea\Model\Entities\WorkerRunningJob;
use Alchemy\Phrasea\Model\Repositories\WorkerJobRepository; use Alchemy\Phrasea\Model\Repositories\WorkerJobRepository;
use Alchemy\Phrasea\Model\Repositories\WorkerRunningJobRepository;
use Alchemy\Phrasea\WorkerManager\Event\RecordEditInWorkerEvent; use Alchemy\Phrasea\WorkerManager\Event\RecordEditInWorkerEvent;
use Alchemy\Phrasea\WorkerManager\Queue\MessagePublisher; use Alchemy\Phrasea\WorkerManager\Queue\MessagePublisher;
class MainQueueWorker implements WorkerInterface class MainQueueWorker implements WorkerInterface
{ {
use ApplicationBoxAware;
use DataboxLoggerAware;
private $messagePublisher; private $messagePublisher;
private $repoWorkerJob; private $repoWorkerJob;
private $repoWorkerRunningJob;
private $conf;
public function __construct( public function __construct(
MessagePublisher $messagePublisher, MessagePublisher $messagePublisher,
WorkerJobRepository $repoWorkerJob WorkerJobRepository $repoWorkerJob,
WorkerRunningJobRepository $repoWorkerRunningJob,
PropertyAccess $conf
) )
{ {
$this->messagePublisher = $messagePublisher; $this->messagePublisher = $messagePublisher;
$this->repoWorkerJob = $repoWorkerJob; $this->repoWorkerJob = $repoWorkerJob;
$this->repoWorkerRunningJob = $repoWorkerRunningJob;
$this->conf = $conf;
} }
public function process(array $payload) public function process(array $payload)
@@ -29,6 +43,31 @@ class MainQueueWorker implements WorkerInterface
'payload' => $payload 'payload' => $payload
]; ];
$autoCancelingJob = $this->conf->get(['workers', 'auto-cancelingJob'], null);
if (!empty($autoCancelingJob)) {
$autoCancelingJob = intval($autoCancelingJob);
// first get the workerRunningJobs for log_docs 'subdefCreation', 'writeMetadatas'
$workerRunningJobs = $this->repoWorkerRunningJob->getRunningSinceCreated($autoCancelingJob, ['subdefCreation', 'writeMetadatas']);
// update the status for table workerRunningJob
$this->repoWorkerRunningJob->updateStatusRunningToCanceledSinceCreated($autoCancelingJob);
// last, treat the log_docs
$finishedDate = new \DateTime('now');
/** @var WorkerRunningJob $workerRunningJob */
foreach ($workerRunningJobs as $workerRunningJob) {
$databox = $this->findDataboxById($workerRunningJob->getDataboxId());
$record = $databox->get_record($workerRunningJob->getRecordId());
$subdefName = $workerRunningJob->getWorkOn();
$action = $workerRunningJob->getWork();
$status = 'canceled';
$this->getDataboxLogger($databox)->initOrUpdateLogDocsFromWorker($record, $databox, $workerRunningJob, $subdefName, $action, $finishedDate, $status);
}
}
$em = $this->repoWorkerJob->getEntityManager(); $em = $this->repoWorkerJob->getEntityManager();
$em->getConnection()->beginTransaction(); $em->getConnection()->beginTransaction();
/** @var WorkerJob $workerJob */ /** @var WorkerJob $workerJob */

View File

@@ -0,0 +1,73 @@
<?php
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
class patch_418RC12PHRAS4058 implements patchInterface
{
/** @var string */
private $release = '4.1.8-rc12';
/** @var array */
private $concern = [base::APPLICATION_BOX];
/**
* {@inheritdoc}
*/
public function get_release()
{
return $this->release;
}
/**
* {@inheritdoc}
*/
public function getDoctrineMigrations()
{
return [];
}
/**
* {@inheritdoc}
*/
public function require_all_upgrades()
{
return false;
}
/**
* {@inheritdoc}
*/
public function concern()
{
return $this->concern;
}
/**
* {@inheritdoc}
*/
public function apply(base $base, Application $app)
{
if ($base->get_base_type() === base::DATA_BOX) {
$this->patch_databox($base, $app);
} elseif ($base->get_base_type() === base::APPLICATION_BOX) {
$this->patch_appbox($base, $app);
}
return true;
}
private function patch_databox(databox $databox, Application $app)
{
}
private function patch_appbox(base $appbox, Application $app)
{
/** @var PropertyAccess $conf */
$conf = $app['conf'];
if (!$conf->has(['workers', 'auto-cancelingJob'])) {
$conf->set(['workers', 'auto-cancelingJob'], 24);
}
}
}

View File

@@ -364,6 +364,7 @@ video-editor:
- '1.5' - '1.5'
- 3 - 3
workers: workers:
auto-cancelingJob: 24 # period in hours, not define or null to not execute
queue: queue:
worker-queue: worker-queue:
registry: alchemy_worker.queue_registry registry: alchemy_worker.queue_registry