Там я погружаюсь в мир очередей и всего его добра, и он меня поразил:
Данные сеанса теряются, когда приложение помещает задачу в очередь из-за сериализации информации с помощью laravel.
Узнав, как отправлять данные в очереди, остается вопрос:
Учитывая, что очередь отправляет информацию в один класс,
Как сделать эту информацию постоянной (например, сеанс) в других классах на протяжении всей задачи?
Пример кодирования:
//Case where the user object is needed by each class
class queueme {
...
//function called by queue
function atask($job,$data)
{
//Does xyz
if(isset($data['user_id'])
{
//Push user_id to another class
anotherclass::anothertask($data['user_id']);
}
}
}
class anotherclass {
...
function anothertask($user_id)
{
//Does abc
//Yup, that anotherofanother class needs user_id, we send it again.
anotherofanotherclass::yetanothertask($user_id);
}
}
Приведенный выше код иллюстрирует мою проблему.
Должен ли я передать $user_id
или же User
вокруг, если мои классы нуждаются в этой информации?
Нет ли более чистого способа сделать это?
Когда вы ставите в очередь задание, вы должны передать все данные, необходимые для выполнения задания. Таким образом, если задание изменить размер аватара пользователя, необходимая информация является первичным ключом пользователя, чтобы мы могли использовать его модель в работе. Так же, как если вы просматриваете страницу профиля пользователя в браузере, необходимая информация (первичный ключ пользователя), вероятно, указывается в URI запроса (например, users / profile / {id}).
Сеансы не будут работать для заданий очереди, потому что сеансы используются для переноса состояния из запросов браузера, а задания очереди выполняются системой, поэтому их просто не существует. Но это нормально, потому что не каждый класс несет ответственность за поиск данных. Класс, который обрабатывает запрос (контроллер для HTTP-запроса или класс задания для задания очереди), может принимать входные данные и искать модели и тому подобное, но каждый последующий вызов может передавать эти объекты.
Вернуться к примеру аватара пользователя. Вы бы передали идентификатор пользователя в качестве примитива при постановке в очередь. Вы можете передать всю пользовательскую модель, но если задание откладывается на длительное время, состояние этого пользователя могло бы измениться за это время, поэтому вы будете работать с неточными данными. Кроме того, как вы упоминаете, не все объекты могут быть сериализованы, поэтому лучше просто передать первичный ключ в задание, и он сможет извлечь его из базы данных.
Итак, поставьте в очередь свою работу:
Queue::push('AvatarProcessor', [$user->id]);
Когда ваша работа будет уволена, извлеките пользователя из базы данных, и вы сможете передать его другим классам, как в веб-запросе или любом другом сценарии.
class AvatarProcessor {
public function fire($job, $data)
{
$user_id = $data[0]; // the user id is the first item in the array
$user = User::find($user_id); // re-pull the model from the database
if ($user == null)
{
// handle the possibility the user has been deleted since
// the job was pushed
}
// Do any work you like here. For an image manipulation example,
// we'll probably do some work and upload a new version of the avatar
// to a cloud provider like Amazon S3, and change the URL to the avatar
// on the user object. The method accepts the user model, it doesn't need
// to reconstruct the model again
(new ImageManipulator)->resizeAvatar($user);
$user->save(); // save the changes the image manipulator made
$job->delete(); // delete the job since we've completed it
}
}
Других решений пока нет …