diff --git a/lib/Alchemy/Phrasea/WorkerManager/Controller/AdminConfigurationController.php b/lib/Alchemy/Phrasea/WorkerManager/Controller/AdminConfigurationController.php index cb774650c3..5d2f6d9ecc 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Controller/AdminConfigurationController.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Controller/AdminConfigurationController.php @@ -58,26 +58,35 @@ class AdminConfigurationController extends Controller { $AMQPConnection = $this->getAMQPConnection(); - $conf = $this->getConf()->get(['workers', 'queues'], []); - $form = $app->form(new WorkerConfigurationType($AMQPConnection), $conf); + $conf = ['queues' => $this->getConf()->get(['workers', 'queues'], [])]; + // ttl's are saved in conf in ms, display in form as sec. + foreach($conf['queues'] as $qname => $settings) { + foreach ($settings as $k=>$v) { + if(in_array($k, [AMQPConnection::TTL_RETRY, AMQPConnection::TTL_DELAYED])) { + $conf['queues'][$qname][$k] /= 1000.0; + } + } + } + $form = $app->form(new WorkerConfigurationType($AMQPConnection), $conf); $form->handleRequest($request); if ($form->isValid()) { // save config // too bad we must remove null entries from data to not save in conf - $data = $form->getData(); - array_walk( - $data, - function(&$qSettings, $qName) { - $qSettings = array_filter( - $qSettings, - function($setting) { - return $setting !== null; + $_data = $form->getData(); + $data = $conf['queues']; // we will save a patched conf (not only data) so custom settings will be preserved + foreach($_data['queues'] as $qname => $settings) { + $data[$qname] = []; + foreach ($settings as $k=>$v) { + if(!is_null($v)) { // ignore null values from form + if(in_array($k, [AMQPConnection::TTL_RETRY, AMQPConnection::TTL_DELAYED])) { + $v = (int)(1000 * (float)$v); } - ); + $data[$qname][$k] = $v; + } } - ); + } ksort($data); $app['conf']->set(['workers', 'queues'], $data); diff --git a/lib/Alchemy/Phrasea/WorkerManager/Form/QueueSettingsType.php b/lib/Alchemy/Phrasea/WorkerManager/Form/QueueSettingsType.php index ee3cc86e95..1271582c0a 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Form/QueueSettingsType.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Form/QueueSettingsType.php @@ -41,20 +41,20 @@ class QueueSettingsType extends AbstractType ] ]) ->add('ttl_retry', IntegerType::class, [ - 'label' => 'admin::workermanager:tab:workerconfig:retry delay in ms', + 'label' => 'admin::workermanager:tab:workerconfig:retry delay in seconds', 'required' => false, 'attr' => [ - 'placeholder' => $this->AMQPConnection->getDefaultSetting($this->baseQueueName, AMQPConnection::TTL_RETRY), + 'placeholder' => $this->AMQPConnection->getDefaultSetting($this->baseQueueName, AMQPConnection::TTL_RETRY) / 1000.0, //'class'=>'col' ] ]); } if($this->AMQPConnection->hasDelayedQueue($this->baseQueueName)) { $builder->add('ttl_delayed', IntegerType::class, [ - 'label' => 'admin::workermanager:tab:workerconfig:delayed delay in ms', + 'label' => 'admin::workermanager:tab:workerconfig:delayed delay in seconds', 'required' => false, 'attr' => [ - 'placeholder' => $this->AMQPConnection->getDefaultSetting($this->baseQueueName, AMQPConnection::TTL_DELAYED), + 'placeholder' => $this->AMQPConnection->getDefaultSetting($this->baseQueueName, AMQPConnection::TTL_DELAYED) / 1000.0, //'class'=>'col' ] ]); diff --git a/lib/Alchemy/Phrasea/WorkerManager/Form/WorkerConfigurationType.php b/lib/Alchemy/Phrasea/WorkerManager/Form/WorkerConfigurationType.php index 3828875fe9..7682183ba3 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Form/WorkerConfigurationType.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Form/WorkerConfigurationType.php @@ -4,6 +4,7 @@ namespace Alchemy\Phrasea\WorkerManager\Form; use Alchemy\Phrasea\WorkerManager\Queue\AMQPConnection; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\FormBuilderInterface; @@ -20,62 +21,26 @@ class WorkerConfigurationType extends AbstractType { parent::buildForm($builder, $options); + $g = $builder->create("queues", FormType::class, ['attr'=>['class'=>'form-row']]); + foreach($this->AMQPConnection->getBaseQueueNames() as $baseQueueName) { - /* - $g = null; - if($this->AMQPConnection->hasRetryQueue($baseQueueName) || $this->AMQPConnection->hasLoopQueue($baseQueueName)) { - $g = $g ?? $this->createFormGroup($builder, $baseQueueName); - $g->add('max_retry', TextType::class, [ - 'label' => 'admin::workermanager:tab:workerconfig:max retry', - 'required' => false, - 'attr' => [ - 'placeholder' => $this->AMQPConnection->getMaxRetry($baseQueueName) - ] - ]); - $g->add('ttl_retry', TextType::class, [ - 'label' => 'admin::workermanager:tab:workerconfig:retry delay in ms', - 'required' => false, - 'attr' => [ - 'placeholder' => $this->AMQPConnection->getTTLRetry($baseQueueName) - ] - ]); - } - if($this->AMQPConnection->hasDelayedQueue($baseQueueName)) { - $g = $g ?? $this->createFormGroup($builder, $baseQueueName); - $g->add('ttl_delayed', TextType::class, [ - 'label' => 'admin::workermanager:tab:workerconfig:delayed delay in ms', - 'required' => false, - 'attr' => [ - 'placeholder' => $this->AMQPConnection->getTTLDelayed($baseQueueName) - ] - ]); - } - if($g) { -// $builder->add($g); - } - */ if($this->AMQPConnection->hasRetryQueue($baseQueueName) || $this->AMQPConnection->hasLoopQueue($baseQueueName) || $this->AMQPConnection->hasDelayedQueue($baseQueueName) ) { $f = new QueueSettingsType($this->AMQPConnection, $baseQueueName); - $builder->add($baseQueueName, $f, ['attr' => ['class' => 'norow'], 'block_name' => 'queue']); + $g->add($baseQueueName, $f, ['attr' => ['class' => 'norow'], 'block_name' => 'queue']); } } + + $builder->add($g); + $builder->add("boutton::appliquer", SubmitType::class, [ 'label' => "boutton::appliquer" ]); } - /* - private function createFormGroup(FormBuilderInterface $builder, string $name) - { - // todo : fix form render : one horizontal block per queue - return $builder->create($name, FormType::class, ['attr'=>['class'=>'form-row']]); - } - */ - public function getName() { return 'worker_configuration'; diff --git a/lib/Alchemy/Phrasea/WorkerManager/Queue/AMQPConnection.php b/lib/Alchemy/Phrasea/WorkerManager/Queue/AMQPConnection.php index ca43f74da1..fc784f4095 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Queue/AMQPConnection.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Queue/AMQPConnection.php @@ -49,28 +49,6 @@ class AMQPConnection const TTL_DELAYED = 'ttl_delayed'; const MESSAGES = [ - MessagePublisher::WRITE_METADATAS_TYPE => [ - 'with' => self::WITH_RETRY | self::WITH_DELAYED, - self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, - self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, - self::TTL_DELAYED => self::DEFAULT_DELAYED_DELAY_VALUE - ], - MessagePublisher::SUBDEF_CREATION_TYPE => [ - 'with' => self::WITH_RETRY | self::WITH_DELAYED, - self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, - self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, - self::TTL_DELAYED => self::DEFAULT_DELAYED_DELAY_VALUE - ], - MessagePublisher::EXPORT_MAIL_TYPE => [ - 'with' => self::WITH_RETRY, - self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, - self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, - ], - MessagePublisher::WEBHOOK_TYPE => [ - 'with' => self::WITH_RETRY, - self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, - self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, - ], MessagePublisher::ASSETS_INGEST_TYPE => [ 'with' => self::WITH_RETRY, self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, @@ -81,31 +59,14 @@ class AMQPConnection self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, ], - MessagePublisher::PULL_ASSETS_TYPE => [ - 'with' => self::WITH_LOOP, - self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, - self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, - ], - MessagePublisher::POPULATE_INDEX_TYPE => [ - 'with' => self::WITH_RETRY, - self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, - self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, - ], - MessagePublisher::RECORD_EDIT_TYPE => [ - 'with' => self::WITH_NOTHING, - self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, - ], MessagePublisher::DELETE_RECORD_TYPE => [ 'with' => self::WITH_NOTHING, self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, ], - MessagePublisher::MAIN_QUEUE_TYPE => [ - 'with' => self::WITH_NOTHING, - self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, - ], - MessagePublisher::SUBTITLE_TYPE => [ - 'with' => self::WITH_NOTHING, + MessagePublisher::EXPORT_MAIL_TYPE => [ + 'with' => self::WITH_RETRY, self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, + self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, ], MessagePublisher::EXPOSE_UPLOAD_TYPE => [ 'with' => self::WITH_NOTHING, @@ -116,11 +77,50 @@ class AMQPConnection self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, self::TTL_RETRY => 180 * 1000, ], + MessagePublisher::MAIN_QUEUE_TYPE => [ + 'with' => self::WITH_NOTHING, + self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, + ], + MessagePublisher::POPULATE_INDEX_TYPE => [ + 'with' => self::WITH_RETRY, + self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, + self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, + ], + MessagePublisher::PULL_ASSETS_TYPE => [ + 'with' => self::WITH_LOOP, + self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, + self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, + ], + MessagePublisher::RECORD_EDIT_TYPE => [ + 'with' => self::WITH_NOTHING, + self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, + ], + MessagePublisher::SUBDEF_CREATION_TYPE => [ + 'with' => self::WITH_RETRY | self::WITH_DELAYED, + self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, + self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, + self::TTL_DELAYED => self::DEFAULT_DELAYED_DELAY_VALUE + ], + MessagePublisher::SUBTITLE_TYPE => [ + 'with' => self::WITH_NOTHING, + self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, + ], MessagePublisher::VALIDATION_REMINDER_TYPE => [ 'with' => self::WITH_LOOP, self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, self::TTL_RETRY => 7200 * 1000, ], + MessagePublisher::WEBHOOK_TYPE => [ + 'with' => self::WITH_RETRY, + self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, + self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, + ], + MessagePublisher::WRITE_METADATAS_TYPE => [ + 'with' => self::WITH_RETRY | self::WITH_DELAYED, + self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, + self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE, + self::TTL_DELAYED => self::DEFAULT_DELAYED_DELAY_VALUE + ], ]; private $queues = []; // filled during construct, from msg list, default values and conf @@ -381,14 +381,14 @@ class AMQPConnection $this->queue_declare_and_bind($queueName, self::RETRY_ALCHEMY_EXCHANGE, [ 'x-dead-letter-exchange' => self::ALCHEMY_EXCHANGE, 'x-dead-letter-routing-key' => $queue['BaseQ'], - 'x-message-ttl' => $this->queues[$queue['BaseQ']]['settings'][self::TTL_RETRY] + 'x-message-ttl' => (int)$this->queues[$queue['BaseQ']]['settings'][self::TTL_RETRY] ]); break; case self::DELAYED_QUEUE: $this->queue_declare_and_bind($queueName, self::RETRY_ALCHEMY_EXCHANGE, [ 'x-dead-letter-exchange' => self::ALCHEMY_EXCHANGE, 'x-dead-letter-routing-key' => $queue['BaseQ'], - 'x-message-ttl' => $this->queues[$queue['BaseQ']]['settings'][self::TTL_DELAYED] + 'x-message-ttl' => (int)$this->queues[$queue['BaseQ']]['settings'][self::TTL_DELAYED] ]); break; case self::FAILED_QUEUE: diff --git a/templates/web/admin/worker-manager/worker_configuration.html.twig b/templates/web/admin/worker-manager/worker_configuration.html.twig index 0a0c701463..0882196394 100644 --- a/templates/web/admin/worker-manager/worker_configuration.html.twig +++ b/templates/web/admin/worker-manager/worker_configuration.html.twig @@ -1,12 +1,38 @@ +{% form_theme form 'form_table_layout.html.twig' %} +{% form_theme form.queues 'bootstrap_3_horizontal_layout.html.twig' %} + +
{{ 'admin::workermanager:tab:workerconfig: warning' |trans }}
-{{ 'admin::workermanager:tab:workerconfig: Set up the delay between two attempts per queue! (if not set, default 10000 millisecond)' |trans }}
{{ form_start(form, {'action': path('worker_admin_configuration')}) }} +
+ + {{ form_label(child) }} + {{ form_errors(child) }} + |
+ |||
+ {{ form_row(child2) }} + | + {% endfor %} + {{ form_widget(child) }} +