Комментарии 12
всё зря было, удаляйте о сколько нам открытий чудных...
Добавить yield перед вызовом методов и функций не очень сложно.
но не все yield одинаково полезны. yield сам по себе никакую магию асинхронности не делает, магию асинхронности делает amp, в котором вызывается функция-генератор.
когда вы пишете
Amp\Loop::run(function () {
yield $promise;
});
внутри функции run происходит примерно следующее (ну если прям совсем на пальцах):
public static function run(callable $callable)
{
$generator = $callable();
if ($generator->valid()) {
$promise = $generator->current();
$promise->onResolve(function ($error, $result) use ($generator) {
if ($error !== null) {
return $generator->throw($error);
}
return $generator->send($result);
});
}
}
то есть за асинхронной функцией на yield должен стоят бекенд, который при yield промиса из этой функции будет дожидаться его и делать send при резолве этого промиса.
это происходит в случае, если вы выбрасываете из генератора промис в
1) контексте генератора, переданного в Loop::run()
2) в контексте генератора, вызванного через call/callAsync
3) в контексте корутины, созданной с помощью coroutine/asyncCoroutine
4) в контексте генератора, переданного в Promise\wait (который под капотом просто вызовет Loop::run())
мало того, вы не можете выбросить с помощью yield что угодно, вы должны выбрасывать инстанс amp или reactphp промиса.
пытаясь, например, сделать
yield unset($storage['index']);
вы выбросите результат выполнения функции unset (а именно null);
и этот код с точки зрения amphp будет эквивалентен
yield null;
на самом деле, учитывая что у вас далеко не самая высокая нагрузка, а доступ к бд осуществляется практически всегда по PK, очень вряд ли вы существенно потеряли бы в производительности, если бы написали просто перегрузку массива на не асинхронном доступе к бд, просто через pdo. а еще лучше — взяли бы что-то более ориентированное на key-value, тот же редис.
вообще madeline, наверное, самое ужасное, что я видел из написанного на php в последние годы, и очень хороший пример, как проект выглядеть не должен. а попытки использования его не as is преврящаются в вот такие костыли, что на самом деле скорее грустно.
а доступ к бд осуществляется практически всегда по PKДа, доступ всегда по primary за исключением полного перебора.
учитывая что у вас далеко не самая высокая нагрузка…MadelineProto у меня крутится на публичном демо tg.i-c-a.su, как часть TelegramApiServer. В рамках одного процесса amphp loop обслуживает еще и amphp/http_server. Не хайлоад, конечно, но 10 одновременных запросов может придти легко. Лишние задержки сильно скажутся на времени ответа.
Кроме того, инстансов madelineProto может быть много внутри одного процесса. И в фоне они постоянно получают апдейты из telegram, которые тоже могут требовать дступа к бд.
Первые версии обновления действительно были частично блокирующими, но решил не «экономить на спичках» во время такого большого pull request.
а еще лучше — взяли бы что-то более ориентированное на key-value, тот же редисВыбранная архитектура не завязана на конкретную бд. Написать адаптер для redis дело пары часов, и драйвер асинхронный есть. Мне привычнее было начать с mysql. Кроме того, mysql более распространен на shared и бесплатных хостингах. А пользователи активно их используют для madeline.
а попытки использования его не as is преврящаются в вот такие костылиА что имеется ввиду под использовать, как есть? Не использовать на аккаунтах с большим количеством данных? Или купить vps с 16 gb ram специально под нее? :)
А что имеется ввиду под использовать, как есть?
я имею ввиду, что вот это вот:
Выбранная архитектура не завязана на конкретную бд
по-хорошему должен сделать был danog, предоставив интерфейс работы с хранилищем сессий, и дефолтный драйвер а-ля SessionStorageInterface, который бы работал как сейчас, но была бы возможность писать свои драйверы по-человечески.
в конкретно данном случае это должно быть что-то в духе (опять же, если совсем на пальцах)
interface SessionStorageInterface {
public function set($key, $value) : \Amp\Promise;
public function get($key) : \Amp\Promise;
public function has($key) : \Amp\Promise;
}
с дефолтной заглушкой, а-ля
class ArraySessionStorage implements SessionStorageInterface {
private $storage = [];
public function set($key, $value) : \Amp\Promise {
$this->storage[$key] = $value;
return new \Amp\Success();
}
public function get($key) : \Amp\Promise {
if (isset($this->storage[$key])) {
return new \Amp\Success($this->storage[$key]);
}
return new \Amp\Failure();
}
public function has($key) : \Amp\Promise {
return isset($this->storage[$key])
? new \Amp\Success(true);
: new \Amp\Success(false);
}
}
да и вообще сама структура madeline это ужас и боль.
я представляю себе объем работы, который выполнил автор, честь ему и хвала за усидчивость и вложенные силы, но качество проекта очень печальное.
и если стоит вопрос как-то серьезно кастомизировать её под свои нужды, то порой проще будет написать своё.
function unset($key) {
return $this->offsetUnset($key);
}
По факту оказалось так:
function unset($key) {
$this->offsetUnset($key);
}
Yield становится аналогом async… await из js
До появления async/await в js также строили асинхронный flow через генераторы и yeild. Посмотрите на koa 1, окажется что все очень похоже.
Ну теоретически в свой username/имя можно попробовать запихнуть какую то вредоносную строку и тогда другой аккаунт в madelineProto сериализует эту строку в базу. Но опять же, как эксплуатировать это?
А вообще, если даже сейчас нет уязвимых классов, они могут появится в будущем. Не в этом репозитории так в любой композер зависимости.
В общем, сериализировать юзер инпут — зло. Лучше заменить на json.
сериализировать юзер инпут — зло
Благодарю за развернутый комент, но о каком вводе идет речь? Это демон, работающий в cli. Данные он принимает только от telegram.
Пишем простую ORM с возможностью смены БД на лету