better worker-configuration ux (display in table)

show ttl's in seconds (still in ms in conf)
fix : no more error if a ttl is entered a 'string' into conf
This commit is contained in:
jygaulier
2021-01-05 19:21:55 +01:00
parent 8f1d132c39
commit 38f1720fb4
5 changed files with 103 additions and 103 deletions

View File

@@ -58,26 +58,35 @@ class AdminConfigurationController extends Controller
{ {
$AMQPConnection = $this->getAMQPConnection(); $AMQPConnection = $this->getAMQPConnection();
$conf = $this->getConf()->get(['workers', 'queues'], []); $conf = ['queues' => $this->getConf()->get(['workers', 'queues'], [])];
$form = $app->form(new WorkerConfigurationType($AMQPConnection), $conf); // 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); $form->handleRequest($request);
if ($form->isValid()) { if ($form->isValid()) {
// save config // save config
// too bad we must remove null entries from data to not save in conf // too bad we must remove null entries from data to not save in conf
$data = $form->getData(); $_data = $form->getData();
array_walk( $data = $conf['queues']; // we will save a patched conf (not only data) so custom settings will be preserved
$data, foreach($_data['queues'] as $qname => $settings) {
function(&$qSettings, $qName) { $data[$qname] = [];
$qSettings = array_filter( foreach ($settings as $k=>$v) {
$qSettings, if(!is_null($v)) { // ignore null values from form
function($setting) { if(in_array($k, [AMQPConnection::TTL_RETRY, AMQPConnection::TTL_DELAYED])) {
return $setting !== null; $v = (int)(1000 * (float)$v);
} }
); $data[$qname][$k] = $v;
}
} }
); }
ksort($data); ksort($data);
$app['conf']->set(['workers', 'queues'], $data); $app['conf']->set(['workers', 'queues'], $data);

View File

@@ -41,20 +41,20 @@ class QueueSettingsType extends AbstractType
] ]
]) ])
->add('ttl_retry', IntegerType::class, [ ->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, 'required' => false,
'attr' => [ 'attr' => [
'placeholder' => $this->AMQPConnection->getDefaultSetting($this->baseQueueName, AMQPConnection::TTL_RETRY), 'placeholder' => $this->AMQPConnection->getDefaultSetting($this->baseQueueName, AMQPConnection::TTL_RETRY) / 1000.0,
//'class'=>'col' //'class'=>'col'
] ]
]); ]);
} }
if($this->AMQPConnection->hasDelayedQueue($this->baseQueueName)) { if($this->AMQPConnection->hasDelayedQueue($this->baseQueueName)) {
$builder->add('ttl_delayed', IntegerType::class, [ $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, 'required' => false,
'attr' => [ 'attr' => [
'placeholder' => $this->AMQPConnection->getDefaultSetting($this->baseQueueName, AMQPConnection::TTL_DELAYED), 'placeholder' => $this->AMQPConnection->getDefaultSetting($this->baseQueueName, AMQPConnection::TTL_DELAYED) / 1000.0,
//'class'=>'col' //'class'=>'col'
] ]
]); ]);

View File

@@ -4,6 +4,7 @@ namespace Alchemy\Phrasea\WorkerManager\Form;
use Alchemy\Phrasea\WorkerManager\Queue\AMQPConnection; use Alchemy\Phrasea\WorkerManager\Queue\AMQPConnection;
use Symfony\Component\Form\AbstractType; 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\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
@@ -20,62 +21,26 @@ class WorkerConfigurationType extends AbstractType
{ {
parent::buildForm($builder, $options); parent::buildForm($builder, $options);
$g = $builder->create("queues", FormType::class, ['attr'=>['class'=>'form-row']]);
foreach($this->AMQPConnection->getBaseQueueNames() as $baseQueueName) { 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) if($this->AMQPConnection->hasRetryQueue($baseQueueName)
|| $this->AMQPConnection->hasLoopQueue($baseQueueName) || $this->AMQPConnection->hasLoopQueue($baseQueueName)
|| $this->AMQPConnection->hasDelayedQueue($baseQueueName) || $this->AMQPConnection->hasDelayedQueue($baseQueueName)
) { ) {
$f = new QueueSettingsType($this->AMQPConnection, $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, $builder->add("boutton::appliquer", SubmitType::class,
[ [
'label' => "boutton::appliquer" '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() public function getName()
{ {
return 'worker_configuration'; return 'worker_configuration';

View File

@@ -49,28 +49,6 @@ class AMQPConnection
const TTL_DELAYED = 'ttl_delayed'; const TTL_DELAYED = 'ttl_delayed';
const MESSAGES = [ 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 => [ MessagePublisher::ASSETS_INGEST_TYPE => [
'with' => self::WITH_RETRY, 'with' => self::WITH_RETRY,
self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE,
@@ -81,31 +59,14 @@ class AMQPConnection
self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE,
self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_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 => [ MessagePublisher::DELETE_RECORD_TYPE => [
'with' => self::WITH_NOTHING, 'with' => self::WITH_NOTHING,
self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE,
], ],
MessagePublisher::MAIN_QUEUE_TYPE => [ MessagePublisher::EXPORT_MAIL_TYPE => [
'with' => self::WITH_NOTHING, 'with' => self::WITH_RETRY,
self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE,
],
MessagePublisher::SUBTITLE_TYPE => [
'with' => self::WITH_NOTHING,
self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE,
self::TTL_RETRY => self::DEFAULT_RETRY_DELAY_VALUE,
], ],
MessagePublisher::EXPOSE_UPLOAD_TYPE => [ MessagePublisher::EXPOSE_UPLOAD_TYPE => [
'with' => self::WITH_NOTHING, 'with' => self::WITH_NOTHING,
@@ -116,11 +77,50 @@ class AMQPConnection
self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE,
self::TTL_RETRY => 180 * 1000, 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 => [ MessagePublisher::VALIDATION_REMINDER_TYPE => [
'with' => self::WITH_LOOP, 'with' => self::WITH_LOOP,
self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE, self::MAX_RETRY => self::DEFAULT_MAX_RETRY_VALUE,
self::TTL_RETRY => 7200 * 1000, 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 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, [ $this->queue_declare_and_bind($queueName, self::RETRY_ALCHEMY_EXCHANGE, [
'x-dead-letter-exchange' => self::ALCHEMY_EXCHANGE, 'x-dead-letter-exchange' => self::ALCHEMY_EXCHANGE,
'x-dead-letter-routing-key' => $queue['BaseQ'], '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; break;
case self::DELAYED_QUEUE: case self::DELAYED_QUEUE:
$this->queue_declare_and_bind($queueName, self::RETRY_ALCHEMY_EXCHANGE, [ $this->queue_declare_and_bind($queueName, self::RETRY_ALCHEMY_EXCHANGE, [
'x-dead-letter-exchange' => self::ALCHEMY_EXCHANGE, 'x-dead-letter-exchange' => self::ALCHEMY_EXCHANGE,
'x-dead-letter-routing-key' => $queue['BaseQ'], '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; break;
case self::FAILED_QUEUE: case self::FAILED_QUEUE:

View File

@@ -1,12 +1,38 @@
{% form_theme form 'form_table_layout.html.twig' %}
{% form_theme form.queues 'bootstrap_3_horizontal_layout.html.twig' %}
<h1>{{ 'admin::workermanager:tab:workerconfig: title' |trans }}</h1> <h1>{{ 'admin::workermanager:tab:workerconfig: title' |trans }}</h1>
<p class="alert alert-danger"> <p class="alert alert-danger">
{{ 'admin::workermanager:tab:workerconfig: warning' |trans }} {{ 'admin::workermanager:tab:workerconfig: warning' |trans }}
</p> </p>
<p>{{ 'admin::workermanager:tab:workerconfig: Set up the delay between two attempts per queue! (if not set, default 10000 millisecond)' |trans }}</p>
{{ form_start(form, {'action': path('worker_admin_configuration')}) }} {{ form_start(form, {'action': path('worker_admin_configuration')}) }}
<table>
{% for child in form.queues.children %}
<tr>
<td colspan="4">
<hr/>
{{ form_label(child) }}
{{ form_errors(child) }}
</td>
</tr>
<tr>
{% for child2 in child.children %}
<td>
{{ form_row(child2) }}
</td>
{% endfor %}
{{ form_widget(child) }}
</tr>
{% endfor %}
</table>
<br/>
<br/>
{{ form_widget(form) }} {{ form_widget(form) }}
{{ form_end(form) }} {{ form_end(form) }}
<br/>