/console/controllers/ContentController.php
PHP | 171 lines | 105 code | 26 blank | 40 comment | 5 complexity | 64197a302befc32e6a7ebb315dbea84f MD5 | raw file
- <?php
- /**
- * @link http://www.noghteh.ir/
- * @copyright Copyright (c) 2015 Noghteh
- * @license http://www.noghteh.ir/license/
- */
- namespace console\controllers;
- use PhpAmqpLib\Wire\AMQPTable;
- use Yii;
- use Exception;
- use common\models\Channel;
- use common\models\Content;
- use yii\helpers\ArrayHelper;
- /**
- * Class ContentController
- * @package console\controllers
- * @author Ali Irani <ali@irani.im>
- */
- class ContentController extends \yii\console\Controller
- {
- /**
- * Get waiting contents to push and then one bye one push to channels
- */
- public function actionSendToChannels()
- {
- $contents = Content::find()
- ->where(['{{%content}}.status' => [Content::STATUS_IN_QUEUE, Content::STATUS_SCHEDULED]])
- ->joinWith(['channels'])
- ->andWhere(['{{%channel}}.type' => [Channel::TYPE_TELEGRAM_BOT, Channel::TYPE_TELEGRAM_CHANNEL, Channel::TYPE_TWITTER]])
- ->all();
- if ($contents) {
- $contentIds = ArrayHelper::getColumn($contents, 'id');
- Content::updateAll(['status' => Content::STATUS_SENDING], ['id' => $contentIds]);
- /* @var Content $content */
- foreach ($contents as $content) {
- if ($content->published_at > time()) {
- Content::updateAll(['status' => Content::STATUS_SCHEDULED], ['id' => $content->id]);
- continue;
- }
- try {
- $content->sendToChannels();
- } catch (Exception $e) {
- Yii::error(['message' => $e->getMessage(), 'file' => $e->getFile().':'.$e->getLine()], __METHOD__);
- }
- $content->status = $content->status === Content::STATUS_SENDING ? Content::STATUS_FAILED : $content->status;
- $content->update(false);
- }
- $this->stdout("Sent \"" . count($contents) . "\" contents to the channels.\n");
- }
- }
- /**
- * Beta worker (consumer) for contents queue in amqp
- * @todo: this action need to be better and optimizing
- */
- public function actionWorker()
- {
- $exchange = 'router';
- $queue = 'contents';
- $consumerTag = 'consumer';
- /* @var \PhpAmqpLib\Connection\AMQPStreamConnection $connection */
- $connection = Yii::$app->amqp->getConnection();
- $channel = $connection->channel();
- $channel->queue_declare($queue, false, true, false, false);
- $channel->exchange_declare($exchange, 'direct', false, true, false);
- $channel->queue_bind($queue, $exchange);
- $channel->basic_consume($queue, $consumerTag, false, false, false, false, [$this, 'processMessage']);
- register_shutdown_function([$this, 'shutdownConsumer'], $channel, $connection);
- // Loop as long as the channel has callbacks registered
- while (count($channel->callbacks)) {
- $channel->wait();
- }
- }
- /**
- * Beta worker (consumer) for delayed contents queue in amqp
- * @todo: this action need to be better and optimizing
- */
- public function actionDelayedWorker()
- {
- $exchange = 'delayed_router';
- $queue = 'delayed_contents';
- $consumerTag = 'delayed_consumer';
- $exchangeType = 'x-delayed-message';
- $exchangeArgs = new AMQPTable(['x-delayed-type' => 'fanout']);
- $queueArgs = new AMQPTable(['x-dead-letter-exchange' => 'delayed']);
- /* @var \PhpAmqpLib\Connection\AMQPStreamConnection $connection */
- $connection = Yii::$app->amqp->getConnection();
- $channel = $connection->channel();
- $channel->queue_declare($queue, false, true, false, false, false, $queueArgs);
- $channel->exchange_declare($exchange, $exchangeType, false, true, false, false, false, $exchangeArgs);
- $channel->queue_bind($queue, $exchange);
- $channel->basic_consume($queue, $consumerTag, false, false, false, false, [$this, 'processMessage']);
- register_shutdown_function([$this, 'shutdownConsumer'], $channel, $connection);
- // Loop as long as the channel has callbacks registered
- while (count($channel->callbacks)) {
- $channel->wait();
- }
- }
- /**
- * Proccess messages for amqp publisher
- * @param $message
- * @return bool
- */
- public function processMessage($message)
- {
- $contentId = $message->body;
- $startTime = date("Y-m-j H:i:s");
- echo "\n[$startTime] Start sending content $contentId to channels.";
- $content = Content::findOne($contentId);
- if ($content === null) {
- return false;
- }
- $content->changeStatus(Content::STATUS_SENDING);
- try {
- $content->sendToChannels();
- } catch (Exception $e) {
- Yii::error(['message' => $e->getMessage(), 'file' => $e->getFile().':'.$e->getLine()], __METHOD__);
- }
- $status = $content->status === Content::STATUS_SENDING ? Content::STATUS_FAILED : $content->status;
- $content->changeStatus($status);
- $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
- $endTime = date("Y-m-j H:i:s");
- echo "\n[$endTime] Finish sending content $contentId to channels.";
- return true;
- }
- /**
- * Shutdown amqp connections
- * @param $channel
- * @param $connection
- */
- public function shutdownConsumer($channel, $connection)
- {
- $channel->close();
- $connection->close();
- }
- /**
- * Restart AMQP worker
- * @param string $user
- */
- public function actionRestartWorker($user = 'gituser')
- {
- shell_exec('ps ax | grep yii> /dev/null & echo $!');
- shell_exec("killall -w -v -u $user php");
- shell_exec('nohup php yii content/worker &>./console/runtime/logs/amqp.log &');
- }
- }