Files
Phraseanet/lib/Alchemy/Phrasea/WorkerManager/Queue/MessagePublisher.php
2020-07-03 11:54:19 +03:00

163 lines
5.9 KiB
PHP

<?php
namespace Alchemy\Phrasea\WorkerManager\Queue;
use Monolog\Logger;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPTable;
use Psr\Log\LoggerInterface;
class MessagePublisher
{
const EXPORT_MAIL_TYPE = 'exportMail';
const SUBDEF_CREATION_TYPE = 'subdefCreation';
const WRITE_METADATAS_TYPE = 'writeMetadatas';
const ASSETS_INGEST_TYPE = 'assetsIngest';
const CREATE_RECORD_TYPE = 'createRecord';
const DELETE_RECORD_TYPE = 'deleteRecord';
const WEBHOOK_TYPE = 'webhook';
const POPULATE_INDEX_TYPE = 'populateIndex';
const PULL_ASSETS_TYPE = 'pullAssets';
const SUBTITLE_TYPE = 'subtitle';
const MAIN_QUEUE_TYPE = 'mainQueue';
const MAIN_QUEUE = 'main-queue';
const SUBTITLE_QUEUE = 'subtitle-queue';
// worker queue to be consumed, when no ack , it is requeued to the retry queue
const EXPORT_QUEUE = 'export-queue';
const SUBDEF_QUEUE = 'subdef-queue';
const METADATAS_QUEUE = 'metadatas-queue';
const WEBHOOK_QUEUE = 'webhook-queue';
const ASSETS_INGEST_QUEUE = 'ingest-queue';
const CREATE_RECORD_QUEUE = 'createrecord-queue';
const DELETE_RECORD_QUEUE = 'deleterecord-queue';
const POPULATE_INDEX_QUEUE = 'populateindex-queue';
const PULL_QUEUE = 'pull-queue';
// retry queue
// we can use these retry queue with TTL, so when message expires it is requeued to the corresponding worker queue
const RETRY_EXPORT_QUEUE = 'retry-export-queue';
const RETRY_SUBDEF_QUEUE = 'retry-subdef-queue';
const RETRY_METADATAS_QUEUE = 'retry-metadatas-queue';
const RETRY_WEBHOOK_QUEUE = 'retry-webhook-queue';
const RETRY_ASSETS_INGEST_QUEUE = 'retry-ingest-queue';
const RETRY_CREATE_RECORD_QUEUE = 'retry-createrecord-queue';
const RETRY_POPULATE_INDEX_QUEUE = 'retry-populateindex-queue';
// use this queue to make a loop on a consumer
const LOOP_PULL_QUEUE = 'loop-pull-queue';
// all failed queue, if message is treated over 3 times it goes to the failed queue
const FAILED_EXPORT_QUEUE = 'failed-export-queue';
const FAILED_SUBDEF_QUEUE = 'failed-subdef-queue';
const FAILED_METADATAS_QUEUE = 'failed-metadatas-queue';
const FAILED_WEBHOOK_QUEUE = 'failed-webhook-queue';
const FAILED_ASSETS_INGEST_QUEUE = 'failed-ingest-queue';
const FAILED_CREATE_RECORD_QUEUE = 'failed-createrecord-queue';
const FAILED_POPULATE_INDEX_QUEUE = 'failed-populateindex-queue';
// delayed queue when record is locked
const DELAYED_SUBDEF_QUEUE = 'delayed-subdef-queue';
const DELAYED_METADATAS_QUEUE = 'delayed-metadatas-queue';
const NEW_RECORD_MESSAGE = 'newrecord';
/** @var AMQPConnection $serverConnection */
private $serverConnection;
/** @var Logger */
private $logger;
public function __construct(AMQPConnection $serverConnection, LoggerInterface $logger)
{
$this->serverConnection = $serverConnection;
$this->logger = $logger;
}
public function publishMessage(array $payload, $queueName, $retryCount = null, $workerMessage = '')
{
// add published timestamp to all message payload
$payload['payload']['published'] = time();
$msg = new AMQPMessage(json_encode($payload));
$routing = array_search($queueName, AMQPConnection::$defaultRetryQueues);
if (count($retryCount) && $routing != false) {
// add a message header information
$headers = new AMQPTable([
'x-death' => [
[
'count' => $retryCount,
'exchange' => AMQPConnection::ALCHEMY_EXCHANGE,
'queue' => $routing,
'routing-keys' => $routing,
'reason' => 'rejected', // rejected is sended like nack
'time' => new \DateTime('now', new \DateTimeZone('UTC'))
]
],
'worker-message' => $workerMessage
]);
$msg->set('application_headers', $headers);
}
$channel = $this->serverConnection->setQueue($queueName);
if ($channel == null) {
$this->pushLog("Can't connect to rabbit, check configuration!", "error");
return true;
}
$exchange = in_array($queueName, AMQPConnection::$defaultQueues) ? AMQPConnection::ALCHEMY_EXCHANGE : AMQPConnection::RETRY_ALCHEMY_EXCHANGE;
$channel->basic_publish($msg, $exchange, $queueName);
return true;
}
public function initializePullAssets()
{
$payload = [
'message_type' => self::PULL_ASSETS_TYPE,
'payload' => [
'initTimestamp' => new \DateTime('now', new \DateTimeZone('UTC'))
]
];
$this->publishMessage($payload, self::PULL_QUEUE);
}
public function connectionClose()
{
$this->serverConnection->connectionClose();
}
/**
* @param $message
* @param string $method
* @param array $context
*/
public function pushLog($message, $method = 'info', $context = [])
{
// write logs directly in file
call_user_func(array($this->logger, $method), $message, $context);
}
public function publishFailedMessage(array $payload, AMQPTable $headers, $queueName)
{
$msg = new AMQPMessage(json_encode($payload));
$msg->set('application_headers', $headers);
$channel = $this->serverConnection->setQueue($queueName);
if ($channel == null) {
$this->pushLog("Can't connect to rabbit, check configuration!", "error");
return ;
}
$channel->basic_publish($msg, AMQPConnection::RETRY_ALCHEMY_EXCHANGE, $queueName);
}
}