简体   繁体   中英

Laravel queues & Persistent Variables across classes

There i am diving into the world of queues and all of its goodness and it hit me:

Session data is lost when the application pushes a task to the queue, due to serialization of information by laravel.

Having found out how to send data to queues, a question remains:

Given that the queue pushes information to a single class,

how do i make that information persistent(such as a session) across other classes throughout the duration of this task?

Coding Example:

//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);
    }
}

The above code illustrates my problem.

Do i have to pass the $user_id or User object around, if my classes need this information?

Isn't there a cleaner way to do it?

When you queue up a job, you should pass all data required by the job to do its work. So if it's a job to resize a user's avatar, the necessary information required is the primary key of the user so we can pull their model out in the job. Just like if you're viewing a user's profile page in the browser, the necessary information (the user's primary key) is likely provided in the request URI (eg users/profile/{id}).

Sessions won't work for queue jobs, because sessions are used to carry state over from browser requests, and queue jobs are run by the system, so they simply don't exist. But that's fine, because it's not good practice for every class to be responsible for looking up data. The class that handles the request (a controller for an HTTP request, or a job class for a queue job) can take the input and look up models and such, but every call thereafter can pass those objects around.

Back to the user avatar example. You would pass the ID of the user as a primitive when queueing the job. You could pass the whole user model, but if the job is delayed for a long time, the state of that user could have changed in the meanwhile, so you'd be working with inaccurate data. And also, as you mention, not all objects can be serialised, so it's best to just pass the primary key to the job and it can pull it fresh from the database.

So queue your job:

Queue::push('AvatarProcessor', [$user->id]);

When your job is fired, pull the user fresh from the database and then you're able to pass it around to other classes, just like in a web request or any other scenario.

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
    }

}

As mentioned by maknz, the data needs to be passed explicitly to the job. But in the job handle() method, you can use session() :

public function handle()
{
    session()->put('query_id', 'H123214e890890');

Then your variable is directly accessible in any class:

$query_id = session()->get('query_id')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM