Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Executing a Job directly without PHP Resque #89

Open
epicwhale opened this issue Feb 13, 2014 · 5 comments
Open

Executing a Job directly without PHP Resque #89

epicwhale opened this issue Feb 13, 2014 · 5 comments

Comments

@epicwhale
Copy link
Contributor

I am using Job classes to lift out heavy duty work and execute asynchronously. But there are some cases where I want to run the Job synchronously (either in a web request or another Symfony2 Command).

Is there a way I can dispatch a Job Request? By some way initializing this class or so.. and executing the run command with necessary $args.

What would be the cleanest way to achieve this goal?

My aim here is to increase code re-usability without creating a third class which is used by bot the Job and my other requirements.

p.s: My jobs are container aware.

@danhunsaker
Copy link

Not sure how containers play in (not a Symphony dev; pretty much just PHP-Resque itself), but you should be able to just instantiate the class and call the perform() method. In essence, that's about all PHP-Resque does. If you have a setUp() and/or tearDown() method, it'll call those, too, as appropriate, but otherwise that's about it. The rest of the code is there to manage and monitor the queue, and monitor the actual jobs for success or failure. Which turns out to be a pretty complex process, if you want it done well.

That said, the easiest way might be to actually have Resque_Job do most of this work for you. Something like this should work:

$payload = array(
    // The name of your job class goes here, obviously
    'class' => 'MyJobs\JobClass',
    //  For some reason the Ruby version of Resque puts the args two levels
    // deep, so the PHP version does this as well for compatiblity.
    'args' => array(array(
        'some_data' => 'xyz',
        'needed_for' => 'qrs',
        'your_job' => 'abc',
        'foo' => 'bar'
    )),
    //  'id' can be anything you like.  This example gives it a "unique" value.
    'id' => 'MyJobs\JobClass[' . microtime(true) . ']',
);

//  'queue' can also be anything at this point...
$job = new Resque_Job('queue', $payload);
$success = $job->perform();

$success will contain true or false indicating whether the job was successful. As you'd expect. Note that the id element isn't actually used in the code given here; it's included here simply in case your code expects it.

There are, of course, other approaches, but hopefully that helps.

@mrbase
Copy link
Contributor

mrbase commented Feb 13, 2014

If the jobs are Symfony job, you could extract the logic into a separate service, and call that from the job() method - and from anyware in your application you might want to.

@epicwhale
Copy link
Contributor Author

@danhunsaker thanks for that info, will keep it in mind.. Unfortunately, with the symfony2 bundle, it won't be so straight forward.

@mrbase that's certainly my last resort and what I implied when I mentioned not having to "create a third class". Exploring more alternatives before that.

@KeKs0r
Copy link

KeKs0r commented Mar 23, 2014

I am running my jobs directly in my tests and it looks something like this:

Notice that $betIDs are the real arguments, the rest is in order to provide the containeraware functionality.

        $job = new BetInvalidationJob();

        $args = array(
            'bets' => $betIDs,
            'kernel.root_dir' => $this->get('kernel')->getRootDir(),
            'kernel.debug' => true,
            'kernel.environment' => 'test',
            );
        $job->args = $args;
        $job->run($args);

@cjunge-work
Copy link

I know this is an old issue, but I've been trying to come up with some way to test a ContainerAwareJob while mocking the container so that I don't have to worry about the non-important services.

The ContainerAwareJob class instantiates a new Kernel when the getContainer method is called, and then it's assigned as a private property on the class. There is no way to intercept this behaviour, so a new Kernel is created using the config & parameters for the whole app.

The only possible way to change this behaviour is to alter the kernelOptions, which would mean creating a new kernel.root_dir with a different kernel setup. This seems a rabbit hole to me.

A better way might be to add a public setKernel method so test scripts can use a mock, or even make $kernel protected, so that a Job can set the Kernel if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants