wa0x6e / Cake-Resque

Resque plugin for CakePHP : for creating background jobs that can be processed offline later
MIT License
159 stars 56 forks source link

Configuration for custom routes #25

Closed rodelta closed 10 years ago

rodelta commented 11 years ago

Hi. I have separated folders for my app and cake core, working with a modified path in webroot/index.php. The structure is

When I tried to run CakeResque I had a issue with the include path (workers failed to create). I fixed it making a symlink from htdocs to cake/lib/ to avoid changing CakeResqueBootstrap.php. Workers now work fine, but when I try to enqueue a Job it always fails (Both console and code). Looking at the log file found this error:

[mydate] main.ERROR: {"queue":"default","id":"340fe4379d2f260509884ff517cc03b4","class":"myShell","args":[["funcion"]]} failed: Plugin CakeResque could not be found. {"type":"fail","log":"Plugin CakeResque could not be found.","job_id":"340fe4379d2f260509884ff517cc03b4","time":12,"worker":"mypc:20873"} []

I've tried searching for that error string to see where it's failing, but I couldn't find it. It's possible to configure the plugin so it can work with a custom folder structure?, if so, is in the docs? I've searched for this and couldn't find anything. Where in the plugin is trown this error?

Thanks for your time.

wa0x6e commented 11 years ago

Give me more information about your setup so I can reproduce it.

I assume that the myapp folder is the equivalent of the app folder in a vanilla install ? The one containing models/controllers/Plugin/webroot ?

And cake is the symlink to the cake core ? (lib folder in the root of a vanilla install)

What version of Cake are you using ?

rodelta commented 11 years ago

CakePHP version 2.3.8 stable. Yes. myapp folder is like app but outside the folder of cake. It's accessed via custom path definition in myapp/webroot/index.php. CakeResque is installed there. cake is the cake folder that you get when you download the framework. Inside is the default app (not used) along with lib, plugins and vendors.

rodelta commented 11 years ago

Hi. I've investigated some more today on this. The line of code that's giving this error is if (class_exists('Resque_Job_Creator')) { (Line 159) in file CakeResque/vendor/php-resque-ex/lib/Resque/Job.php. This get's called from function perfom() in the same file, called in turn from Worker.php function perform() line 273 -> $job->perform();. Seeing that this is happening in the php-resque-ex lib i wonder if I should move this issue it's repo instead of here. But I am not sure exactly how this is failing.

wa0x6e commented 11 years ago

Try the fix/25 branch : https://github.com/kamisama/Cake-Resque/tree/fix/25

rodelta commented 11 years ago

Thanks for your time. I've tried the fix. Workers start fine but the Job still fails. The log show this:

main.INFO: Starting worker pcname:19586:default {"type":"start","worker":"pcname:19586:default"} []
main.INFO: got {"queue":"default","id":"33713ea1bcca615e985205829ad6606e","class":"TestShell","args":[["funcion"]]} {"type":"got","args":"[object] (Resque_Job: {\"queue\":\"default\",\"worker\":null,\"payload\":{\"class\":\"TestShell\",\"args\":[[\"funcion\"]],\"id\":\"33713ea1bcca615e985205829ad6606e\"}})","worker":"pcname:19586"} []
main.INFO: Processing ID:33713ea1bcca615e985205829ad6606e in default {"type":"process","worker":"pcname:19586","job_id":"33713ea1bcca615e985205829ad6606e"} []
main.ERROR: {"queue":"default","id":"33713ea1bcca615e985205829ad6606e","class":"TestShell","args":[["funcion"]]} failed: Job class TestShell does not contain a perform method. {"type":"fail","log":"Job class TestShell does not contain a perform method.","job_id":"33713ea1bcca615e985205829ad6606e","time":26,"worker":"pcname:19586"} []

Now the initial error doesn't appear but this is shown instead. When I see the stats trough the console the Jobs appear as failed

i'm calling the job in my app in the controller like this

CakeResque::enqueue(
        'default',
        'TestShell',
        array('function')
    );

My TestShell.php file, for testing purposes, contains this:

App::uses('AppShell', 'Console/Command');
class TestShell extends AppShell
{
    public function function() {
        var $a = 2;
    }
}

AppShell.php has the perform method as shown in the installation docs:

<?php
App::uses('Shell', 'Console');
class AppShell extends Shell {
   public function perform()
   {
      $this->initialize();
      $this->{array_shift($this->args)}();
   }
}
rodelta commented 11 years ago

Hi Changing App::uses('AppShell', 'Console/Command'); to require_once 'AppShell.php'; in TestShell.php has apparently solved the issue. Job now executes without problems.

wa0x6e commented 11 years ago

Is your fix working without mine ?

On Wed, Aug 21, 2013 at 3:48 PM, Cristián De la Rivera < notifications@github.com> wrote:

Hi Changing App::uses('AppShell', 'Console/Command'); to require_once 'AppShell.php'; in TestShell.php has apparently solved the issue. Job now executes without problems.

— Reply to this email directly or view it on GitHubhttps://github.com/kamisama/Cake-Resque/issues/25#issuecomment-23044668 .

rodelta commented 11 years ago

No, both are needed.

wa0x6e commented 11 years ago

Issue closed for now, I've merged my fixes into the master. It'll only handle the case where the app folder was renamed to anything else.

For the case where the lib folder is also customized, I'm a bit hesitant about your fix, since App::uses should always be used to load a core class.

I'll make a note somewhere in the doc about your fix, and they'll have to fix it themselves if they encounter it.

wa0x6e commented 11 years ago

Note added

irongomme commented 11 years ago

This works for me too, but not if i have to use my app models ...

TestShell cannot load AppModel Class, and therefore cannot load others app models.

My structure is :

/var/www/lib/cakephp (cakephp core) /var/www/mydomain.tld/subdomain/ (project root) /var/www/mydomain.tld/subdomain/lib/ (symlink to /var/www/lib/cakephp/lib/) /var/www/mydomain.tld/subdomain/plugins/ (symlink to /var/www/lib/cakephp/plugins/) /var/www/mydomain.tld/subdomain/vendor/ (symlink to /var/www/lib/cakephp/vendor/) /var/www/mydomain.tld/subdomain/myappname/ (app folder) /var/www/mydomain.tld/subdomain/app/ (symlink to /var/www/mydomain.tld/subdomain/myappname/ to make cakeresque start) /var/www/mydomain.tld/subdomain/ (symlink to /var/www/lib/cakephp/index.php)

Meanwhile i'm using symlinks, i'm in a native cake configuration. But, when i read core definition constants, it put /var/www/lib/cakephp/app/ to APP constant.

This is a tricky situation, I've only got myself to blame. It's just a simple fact of life. It could happen to anyone ... lalala :-D

Anyone can help me ?

rodelta commented 11 years ago

can you post your /var/www/mydomain.tld/console/cake.php configuration?

irongomme commented 11 years ago

Yes i can ;)

Oh, i haven't tell about it, i work with cake 2.2.3

_./Console/cake.php _

#!/usr/bin/php -q
<?php
/**
 * Command-line code generation utility to automate programmer chores.
 *
 * PHP 5
 *
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 * Copyright 2005-2012, Cake Software Foundation, Inc.
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://ca                                                                                                                                                             kefoundation.org)
 * @link          http://cakephp.org CakePHP(tm) Project
 * @package       app.Console
 * @since         CakePHP(tm) v 2.0
 * @license       MIT License (http://www.opensource.org/licenses/mit-license.ph                                                                                                                                                             p)
 */
$ds = DIRECTORY_SEPARATOR;
$dispatcher = 'Cake' . $ds . 'Console' . $ds . 'ShellDispatcher.php';

if (function_exists('ini_set')) {
        $root = dirname(dirname(dirname(__FILE__)));
        ini_set('include_path', $root . $ds . 'lib' . PATH_SEPARATOR . ini_get('                                                                                                                                                             include_path'));
}

if (!include ($dispatcher)) {
        trigger_error('Could not locate CakePHP core files.', E_USER_ERROR);
}
unset($paths, $path, $dispatcher, $root, $ds);

return ShellDispatcher::run($argv);
rodelta commented 11 years ago

try this

$root = dirname(dirname(dirname(__FILE__)));
$dispatcher = 'cakephp'. $ds . 'lib' . $ds . 'Cake' . $ds . 'Console' . $ds . 'ShellDispatcher.php';

if (function_exists('ini_set')) {
    ini_set('include_path', $root . PATH_SEPARATOR .  $ds . 'cakephp' . $ds . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
}
irongomme commented 11 years ago

Thanks for your contribution, but unfortunately this still doesn't work !

I've got this : E_ERROR: Class 'AppModel' not found init called at /var/www/lib/cakephp/lib/Cake/Utility/ClassRegistry.php (174)

This is the same for AppShell like if it tries to load files from cakephp core, and not from the specific app

Here is my TestShell.php :

<?php
    App::uses('CakeEmail', 'Network/Email');
    App::uses('AppShell', 'Console/Command');

    class TestShell extends AppShell {

        public function perform() {
            $this->initialize();
            $this->{array_shift($this->args)}();
        }

        public function run() {
            $Ticket = ClassRegistry::init('Ticket');
            CakeEmail::deliver('jerome.denis@e-wi.fr', 'TEST2', $Ticket->$displayField, array('from' => 'noreply@iwibox.net'));
        }
    }
?>
irongomme commented 11 years ago

Good news, i 've made it works in a test environment by removing symlinks to cakephp core, and copyng it directly in my project folder ... i don't like the idea having to upgrade all my apps piece by piece, but i need resque !

Thanks for all !

rodelta commented 11 years ago

instead of using symlinks, try to change the routes in your app. (webroot/index.php)

irongomme commented 11 years ago

Yes my app works with this change, but it is still the same for models loading by resque tasks. The tasks uses only the core path for the whole project, so it doesn't work.

My final solution is to put physical core files instead symlinks, or custom routes config ... and it works

wa0x6e commented 10 years ago

From my tests, the latest fix resolve the issue when:

Can anyone confirm ?

bar commented 10 years ago

I think the solution to all cases, should be to pass all the params needed by ShellDispatcher(), from $this->params:

Array
(
    [app] => web
    [root] => /var/www
    [working] => /var/www/project
    [webroot] => webroot
)

instead of trying to infer them from CAKE env variable.

Actually, this line sets the app dir from where CakeResqueBootstrap.php resides, but if it resides in the plugins shared folder it will fail, or if you clone the file and put it inside your own Lib folder.

wa0x6e commented 10 years ago

The latest fix should make all workers uses the same CAKE library and APP as the main application

bar commented 10 years ago

Is the info note Custom lib folder on EXAMPLE OF JOB CLASS safe to be removed?¿

wa0x6e commented 10 years ago

I think so. I'll test everything again once #41 will be fixed.