mirror of
https://github.com/elyby/accounts.git
synced 2025-05-31 14:11:46 +05:30
Implemented WebHooks delivery queue.
Completely removed usage of the RabbitMQ. Queue now based on Redis channels. Worker process now extracted as separate docker container. Base image upgraded to the 1.8.0 version (PHP 7.2.7 and pcntl extension).
This commit is contained in:
@@ -1,98 +0,0 @@
|
||||
<?php
|
||||
namespace console\controllers;
|
||||
|
||||
use common\components\Mojang\Api as MojangApi;
|
||||
use common\components\Mojang\exceptions\NoContentException;
|
||||
use common\models\Account;
|
||||
use common\models\amqp\AccountBanned;
|
||||
use common\models\amqp\UsernameChanged;
|
||||
use common\models\MojangUsername;
|
||||
use Ely\Amqp\Builder\Configurator;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use Yii;
|
||||
|
||||
class AccountQueueController extends AmqpController {
|
||||
|
||||
public function getExchangeName() {
|
||||
return 'events';
|
||||
}
|
||||
|
||||
public function configure(Configurator $configurator) {
|
||||
$configurator->exchange->topic()->durable();
|
||||
$configurator->queue->name('accounts-accounts-events')->durable();
|
||||
$configurator->bind->routingKey('accounts.username-changed')
|
||||
->add()->routingKey('account.account-banned');
|
||||
}
|
||||
|
||||
public function getRoutesMap() {
|
||||
return [
|
||||
'accounts.username-changed' => 'routeUsernameChanged',
|
||||
'accounts.account-banned' => 'routeAccountBanned',
|
||||
];
|
||||
}
|
||||
|
||||
public function routeUsernameChanged(UsernameChanged $body): bool {
|
||||
Yii::$app->statsd->inc('worker.account.usernameChanged.attempt');
|
||||
$mojangApi = $this->createMojangApi();
|
||||
try {
|
||||
$response = $mojangApi->usernameToUUID($body->newUsername);
|
||||
Yii::$app->statsd->inc('worker.account.usernameChanged.found');
|
||||
} catch (NoContentException $e) {
|
||||
$response = false;
|
||||
Yii::$app->statsd->inc('worker.account.usernameChanged.not_found');
|
||||
} catch (RequestException $e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @var MojangUsername|null $mojangUsername */
|
||||
$mojangUsername = MojangUsername::findOne($body->newUsername);
|
||||
if ($response === false) {
|
||||
if ($mojangUsername !== null) {
|
||||
$mojangUsername->delete();
|
||||
}
|
||||
} else {
|
||||
if ($mojangUsername === null) {
|
||||
$mojangUsername = new MojangUsername();
|
||||
$mojangUsername->username = $response->name;
|
||||
$mojangUsername->uuid = $response->id;
|
||||
} else {
|
||||
$mojangUsername->uuid = $response->id;
|
||||
$mojangUsername->touch('last_pulled_at');
|
||||
}
|
||||
|
||||
$mojangUsername->save();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function routeAccountBanned(AccountBanned $body): bool {
|
||||
$account = Account::findOne($body->accountId);
|
||||
if ($account === null) {
|
||||
Yii::warning('Cannot find banned account ' . $body->accountId . '. Skipping.');
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($account->sessions as $authSession) {
|
||||
$authSession->delete();
|
||||
}
|
||||
|
||||
foreach ($account->minecraftAccessKeys as $key) {
|
||||
$key->delete();
|
||||
}
|
||||
|
||||
foreach ($account->oauthSessions as $oauthSession) {
|
||||
$oauthSession->delete();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MojangApi
|
||||
*/
|
||||
protected function createMojangApi(): MojangApi {
|
||||
return new MojangApi();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
namespace console\controllers;
|
||||
|
||||
use Ely\Amqp\ControllerTrait;
|
||||
use Exception;
|
||||
use PhpAmqpLib\Message\AMQPMessage;
|
||||
use Yii;
|
||||
use yii\console\Controller;
|
||||
use yii\db\Exception as YiiDbException;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Inflector;
|
||||
|
||||
abstract class AmqpController extends Controller {
|
||||
use ControllerTrait {
|
||||
callback as _callback;
|
||||
}
|
||||
|
||||
private $reconnected = false;
|
||||
|
||||
final public function actionIndex() {
|
||||
$this->start();
|
||||
}
|
||||
|
||||
public function getRoutesMap() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Переопределяем метод callback, чтобы избержать логгирования в консоль ошибок,
|
||||
* связанных с обвалом того или иного соединения. Это нормально, PHP рождён умирать,
|
||||
* а не работать 24/7 в качестве демона.
|
||||
*
|
||||
* @param AMQPMessage $msg
|
||||
* @throws YiiDbException
|
||||
*/
|
||||
public function callback(AMQPMessage $msg) {
|
||||
try {
|
||||
$this->_callback($msg);
|
||||
} catch (YiiDbException $e) {
|
||||
if ($this->reconnected || !$this->isRestorableException($e)) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->reconnected = true;
|
||||
Yii::$app->db->close();
|
||||
Yii::$app->db->open();
|
||||
$this->callback($msg);
|
||||
}
|
||||
|
||||
$this->reconnected = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getConnection() {
|
||||
return Yii::$app->amqp->getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function buildRouteActionName($route) {
|
||||
return ArrayHelper::getValue($this->getRoutesMap(), $route, 'route' . Inflector::camelize($route));
|
||||
}
|
||||
|
||||
private function isRestorableException(Exception $e): bool {
|
||||
return strpos($e->getMessage(), 'MySQL server has gone away') !== false
|
||||
|| strcmp($e->getMessage(), 'Error while sending QUERY packet') !== false;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user