├── .gitignore ├── app ├── code │ └── community │ │ └── Mns │ │ └── Resque │ │ ├── Model │ │ ├── PidNotFoundException.php │ │ ├── ConfigurationException.php │ │ ├── DaemonAlreadyRunningException.php │ │ ├── Job.php │ │ ├── Job │ │ │ ├── Logmessage.php │ │ │ ├── Sqltest.php │ │ │ └── Abstract.php │ │ ├── Factory.php │ │ ├── Config.php │ │ ├── Resque.php │ │ └── Runner.php │ │ └── etc │ │ └── config.xml └── etc │ └── modules │ └── Mns_Resque.xml ├── modman ├── tests ├── bootstrap.php ├── unit │ └── Mns │ │ └── Resque │ │ └── Model │ │ ├── FactoryTest.php │ │ ├── ConfigTest.php │ │ ├── RunnerTest.php │ │ └── ResqueTest.php └── phpunit.xml ├── composer.json ├── LICENCE ├── CONTRIBUTING.md ├── shell └── resque.php └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | composer.lock 3 | /store 4 | vendor 5 | -------------------------------------------------------------------------------- /app/code/community/Mns/Resque/Model/PidNotFoundException.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | community 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/code/community/Mns/Resque/Model/Job/Logmessage.php: -------------------------------------------------------------------------------- 1 | args['message'])) { 8 | Mage::log($this->args['message']); 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | create(); 8 | $this->assertInstanceOf('Mns_Resque_Model_Resque', $resque); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/code/community/Mns/Resque/Model/Job/Sqltest.php: -------------------------------------------------------------------------------- 1 | getCollection() 8 | ->setPageSize(10); 9 | 10 | Mage::log('Collection size: ' . $collection->count()); 11 | } 12 | } -------------------------------------------------------------------------------- /tests/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | unit 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/code/community/Mns/Resque/Model/Factory.php: -------------------------------------------------------------------------------- 1 | configureResque(Mage::getModel('mnsresque/config')); 12 | return Mage::getModel('mnsresque/resque', array('resque' => $resqueClient)); 13 | } 14 | 15 | /** 16 | * @param Mns_Resque_Model_Config $config 17 | * @return $this 18 | */ 19 | public function configureResque($config) 20 | { 21 | Resque::setBackend($config->getRedisBackend(), $config->getDatabase()); 22 | return $this; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/code/community/Mns/Resque/Model/Config.php: -------------------------------------------------------------------------------- 1 | =7.2.0", 16 | "ajbonner/magento-composer-autoload": "^0.3.0", 17 | "chrisboulton/php-resque": "dev-master#df69e8980cc21652f10cd775cb6a0e8c572ffd2d", 18 | "magento-hackathon/magento-composer-installer": "~3.2.0" 19 | }, 20 | "repositories": [ 21 | { 22 | "type": "composer", 23 | "url": "https://packages.firegento.com" 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /app/code/community/Mns/Resque/Model/Job/Abstract.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 0.1.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | Mns_Resque_Model 14 | mnsresque_resource 15 | 16 | 17 | 18 | Mns_Resque_Model_Resource 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | localhost:6379 27 | 4 28 | 29 | 30 | shell 31 | 1 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Aaron Bonner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/unit/Mns/Resque/Model/ConfigTest.php: -------------------------------------------------------------------------------- 1 | assertTrue($this->redisBackendIsSet($config)); 12 | $this->assertTrue($this->defaultDatabaseIsSet($config)); 13 | $this->assertTrue($this->defaultWorkerCountIsSet($config)); 14 | } 15 | 16 | /** 17 | * @param Mns_Resque_Model_Config $inConfig 18 | * @return bool 19 | */ 20 | protected function redisBackendIsSet($inConfig) 21 | { 22 | return 'localhost:6379' == $inConfig->getRedisBackend(); 23 | } 24 | 25 | /** 26 | * @param Mns_Resque_Model_Config $inConfig 27 | * @return bool 28 | */ 29 | protected function defaultDatabaseIsSet($inConfig) 30 | { 31 | return 4 == $inConfig->getDatabase(); 32 | } 33 | 34 | /** 35 | * @param Mns_Resque_Model_Config $inConfig 36 | * @return bool 37 | */ 38 | protected function defaultWorkerCountIsSet($inConfig) 39 | { 40 | return 1 == $inConfig->getNumWorkers(); 41 | } 42 | } -------------------------------------------------------------------------------- /tests/unit/Mns/Resque/Model/RunnerTest.php: -------------------------------------------------------------------------------- 1 | resque = new Resque(); 20 | $this->resque->setBackend($config->getRedisBackend(), $config->getDatabase()); 21 | $this->client = Mage::getModel('mnsresque/resque', array('resque' => $this->resque)); 22 | $this->client->deleteAll(); 23 | } 24 | 25 | public function testDaemonRunsQueuedJob() 26 | { 27 | $this->startDaemon(); 28 | $message = 'Hello, world! - ' . microtime(true) * 1000; 29 | $this->client->addJob('Mns_Resque_Model_Job_Logmessage', array('message' => $message)); 30 | $this->stopDaemon(); 31 | $this->assertSystemLogContains($message); 32 | } 33 | 34 | protected function startDaemon() 35 | { 36 | Mage::getModel('mnsresque/runner')->start(); 37 | } 38 | 39 | protected function stopDaemon($pid) 40 | { 41 | Mage::getModel('mnsresque/runner')->stop(); 42 | } 43 | 44 | protected function assertSystemLogContains($message) 45 | { 46 | $log = file_get_contents(Mage::getBaseDir() . DS . 'var' . DS . 'log' . DS . 'system.log'); 47 | $this->assertTrue(stristr($log, $message) !== false, 'Expected message not written to log file'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/code/community/Mns/Resque/Model/Resque.php: -------------------------------------------------------------------------------- 1 | getResque()->enqueue( 23 | self::DEFAULT_QUEUE, $jobClassName, $params, true); 24 | 25 | return $trackingToken; 26 | } 27 | 28 | /** 29 | * @param string $trackingToken 30 | * @return mixed 31 | */ 32 | public function status($trackingToken) 33 | { 34 | $status = new Resque_Job_Status($trackingToken); 35 | 36 | return $status->get(); 37 | } 38 | 39 | /** 40 | * @return Resque_Job 41 | */ 42 | public function popNextJob() 43 | { 44 | return Resque::reserve(self::DEFAULT_QUEUE); 45 | } 46 | 47 | /** 48 | * @param string $ofQueue 49 | * @return int 50 | */ 51 | public function size($ofQueue) 52 | { 53 | return $this->getResque()->size($ofQueue); 54 | } 55 | 56 | /** 57 | * @return $this 58 | */ 59 | public function deleteAll() 60 | { 61 | $this->getResque()->redis()->flushdb(); 62 | } 63 | 64 | /** 65 | * @return array collection containing names of available queues 66 | */ 67 | public function getQueues() 68 | { 69 | return $this->getResque()->queues(); 70 | } 71 | } -------------------------------------------------------------------------------- /tests/unit/Mns/Resque/Model/ResqueTest.php: -------------------------------------------------------------------------------- 1 | resque = new Resque(); 20 | $this->resque->setBackend($config->getRedisBackend(), $config->getDatabase()); 21 | $this->client = Mage::getModel('mnsresque/resque', array('resque' => $this->resque)); 22 | $this->client->deleteAll(); 23 | } 24 | 25 | public function testStoresJob() 26 | { 27 | $trackingToken = $this->addJobToQueue('A_Test_Job', array('foo'=>'bar')); 28 | $this->assertTrue($this->jobStatusIs(Resque_Job_Status::STATUS_WAITING, $trackingToken)); 29 | } 30 | 31 | public function testCanDeleteAllJobs() 32 | { 33 | $this->addJobToQueue('A_Test_Job1', array('foo'=>'bar')); 34 | $this->addJobToQueue('A_Test_Job2', array('foo'=>'bar')); 35 | $this->client->deleteAll(); 36 | $this->assertEquals(0, $this->client->size(Mns_Resque_Model_Resque::DEFAULT_QUEUE)); 37 | } 38 | 39 | public function testCanGetListOfQueues() 40 | { 41 | $this->addJobToQueue('A_Test_Job', array()); 42 | $queues = $this->client->getQueues(); 43 | $this->assertContains(Mns_Resque_Model_Resque::DEFAULT_QUEUE, $queues); 44 | } 45 | 46 | protected function addJobToQueue($job, $withParams) 47 | { 48 | return $this->client->addJob($job, $withParams); 49 | } 50 | 51 | protected function jobStatusIs($expectedStatus, $trackingToken) 52 | { 53 | $status = new Resque_Job_Status($trackingToken); 54 | return $status->get() == $expectedStatus; 55 | } 56 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | Mage Resque is an open community project to help support running background work for a Magento store. We are more than happy to accept external 5 | contributions to the project in the form of feedback, bug reports and even 6 | better - pull requests. 7 | 8 | ## Issue submission 9 | 10 | In order for us to help you please check that you've completed the following 11 | steps: 12 | 13 | * Made sure you're on the latest version `composer.phar update` 14 | * Used the search feature to ensure that the bug hasn't been reported before 15 | * Included as much information about the bug as possible, including any output 16 | you've received, what OS and version you're on, etc. 17 | 18 | [Submit your issue](https://github.com/ajbonner/mage-rescue/issues/new) 19 | 20 | ## Style Guide 21 | 22 | Mage Resque follows the standards defined in the 23 | [PSR-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md), 24 | [PSR-1](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1.md) 25 | and 26 | [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2.md) 27 | documents. 28 | 29 | ## Pull Request Guidelines 30 | 31 | * Please check to make sure that there aren't existing pull requests attempting 32 | to address the issue mentioned. We also recommend checking for issues related 33 | to the issue on the tracker, as a team member may be working on the issue in 34 | a branch or fork. 35 | * Non-trivial changes should be discussed in an issue first 36 | * Develop in a topic/feature branch, not master, we recommend to follow 37 | [this](http://nvie.com/posts/a-successful-git-branching-model/) approach if 38 | possible 39 | * Add relevant unit or integration tests to cover the change 40 | * Lint the code by running `php -l` or using your preferred tool of choice 41 | * Make sure test-suite passes 42 | * Squash your commits 43 | * Write a convincing description of your PR and why we should land it -------------------------------------------------------------------------------- /shell/resque.php: -------------------------------------------------------------------------------- 1 | getArg('daemon')) { 14 | exit($this->startResqueDaemon()); 15 | } else if ($this->getArg('quit')) { 16 | exit($this->stopResqueDaemon()); 17 | } else if ($this->getArg('terminate')) { 18 | exit($this->stopResqueDaemon(true)); 19 | } else if ($this->getArg('test')) { 20 | $this->addJob('Mns_Resque_Model_Job_Logmessage', array('message' => 'Resque Test ' . time())); 21 | exit(0); 22 | } else if ($this->getArg('test-sql')) { 23 | $this->addJob('Mns_Resque_Model_Job_Sqltest'); 24 | exit(0); 25 | } else { 26 | echo $this->usageHelp(); 27 | exit(0); 28 | } 29 | } 30 | 31 | /** 32 | * @param string $jobClassName 33 | * @param mixed 34 | * @return string 35 | */ 36 | protected function addJob($jobClassName, $params=array()) 37 | { 38 | $resque = Mage::getModel('mnsresque/factory')->create(); 39 | return $resque->addJob($jobClassName, $params); 40 | } 41 | 42 | /** 43 | * @return int|void 44 | */ 45 | protected function startResqueDaemon() 46 | { 47 | $params = array( 48 | 'config' => Mage::getModel('mnsresque/config'), 49 | 'log_level' => Mns_Resque_Model_Runner::LOG_NORMAL, 50 | 'queue' => '*'); 51 | 52 | return Mage::getModel('mnsresque/runner', $params)->start(); 53 | } 54 | 55 | /** 56 | * @param bool $shouldKill Stop daemon immediately without letting child processes finish their work 57 | * @return int resque process exit status code 58 | */ 59 | protected function stopResqueDaemon($shouldKill = false) 60 | { 61 | $returnStatus = Mage::getModel('mnsresque/runner')->stop($shouldKill); 62 | 63 | if ($returnStatus != 0) { 64 | $stderr = fopen('php://stderr', 'w+'); 65 | fprintf($stderr, "Could not stop resque daemon\n"); 66 | fclose($stderr); 67 | } else { 68 | $this->waitForDaemonToStop(); 69 | } 70 | 71 | return $returnStatus; 72 | } 73 | 74 | protected function waitForDaemonToStop() 75 | { 76 | sleep(5); 77 | } 78 | 79 | /** 80 | * Retrieve Usage Help Message 81 | */ 82 | public function usageHelp() 83 | { 84 | $scriptName = $_SERVER['argv'][0]; 85 | 86 | return <<run(); 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mage Resque 2 | 3 | Mage Resque is a lightweight [Magento](http://www.magentocommerce.com) implementation of the [PHP Resque](https://github.com/chrisboulton/php-resque/) library and job runner. PHP Resque itself is based on Ruby's [Resque](https://github.com/resque/resque), a Redis backed background job processing library. 4 | 5 | ## Getting started 6 | 7 | ### Licence 8 | Mage Resque is covered by the [MIT](http://opensource.org/licenses/MIT) opensource licence. Unless specifically stated otherwise, terms of use are as laid out in the included LICENCE file. 9 | 10 | ### Requirements 11 | - PHP 7.2+ 12 | - Redis 2.2+ 13 | - ext-pcntl 14 | - Magento 1.9.3.9+ 15 | - Composer 16 | 17 | ### Installation 18 | Mage Resque uses [Composer](http://getcomposer.org) and [Magento Composer Installer](https://github.com/magento-hackathon/magento-composer-installer) to handle installation of the module and its dependencies. To install Mage Resque you will need a copy of _composer.phar_ in your path. If you do not have it availble, run the following commands from your terminal. 19 | 20 | $ curl -sS https://getcomposer.org/installer | php 21 | $ chmod a+x composer.phar 22 | 23 | If you are already using Magento Composer Installer and have an existing _composer.json_, add _https://github.com/ajbonner/mage-resque_ to the repositories list and _ajbonner/mage-resque_ as a required dependency for your project. That's it! 24 | 25 | If you do not have an existing Magento Composer Installer _composer.json_ file defined, you can use the following template. 26 | 27 | { 28 | "require": { 29 | "ajbonner/mage-resque": "*" 30 | }, 31 | "require-dev": { 32 | "fbrnc/Aoe_Profiler": "*", 33 | "MageTest/Mage-Test": "*" 34 | }, 35 | "repositories": [ 36 | { 37 | "type": "vcs", 38 | "url": "https://github.com/magento-hackathon/magento-composer-installer" 39 | }, 40 | { 41 | "type": "vcs", 42 | "url": "https://github.com/ajbonner/magento-composer-autoload" 43 | }, 44 | { 45 | "type": "vcs", 46 | "url": "https://github.com/ajbonner/mage-resque" 47 | }, 48 | { 49 | "type": "vcs", 50 | "url": "https://github.com/MageTest/Mage-Test" 51 | }, 52 | { 53 | "type": "vcs", 54 | "url": "https://github.com/fbrnc/Aoe_Profiler" 55 | } 56 | ], 57 | "extra":{ 58 | "magento-root-dir": "./" 59 | }, 60 | "config": { 61 | "bin-dir": "shell" 62 | }, 63 | "minimum-stability": "dev" 64 | } 65 | 66 | To install Mage Resque and its dependencies just run composer.phar. 67 | 68 | $ ./composer.phar install 69 | 70 | ### Configuration 71 | PHP Resque is a Redis backed job queue, and you will need access to a running Redis instance. To use a particular Redis server and database, add the following xml snippet to local.xml. 72 | 73 | 74 | 75 | 76 | 77 | localhost:6379 78 | 1 79 | 80 | 81 | 82 | 83 | If you use Redis for Magento caching or as a session store, e.g. you use [one of](https://github.com/colinmollenhour/Cm_Cache_Backend_Redis) [Colin Mollenhour's](https://twitter.com/colinmollenhour) [excellent modules](https://github.com/colinmollenhour/Cm_RedisSession), then make sure you select an alternate database, or better yet, a separate Redis instance that is exclusively for Mage Resque. 84 | 85 | If you are storing your binaries in a different directory, you can specify it in local.xml as well: 86 | 87 | 88 | 89 | ... 90 | 91 | bin 92 | 93 | 94 | 95 | 96 | You can configure the number of resque workers to start by adding a element to your mnsresque env configuation: 97 | 98 | 99 | 100 | ... 101 | 102 | ... 103 | 4 104 | 105 | 106 | 107 | 108 | All configuration options can be found in __app/code/community/ajbonner/mage-resque/etc/config.xml__ in the **defaults** section. 109 | 110 | ### Usage 111 | PHP Resque has two functions, to add jobs to Redis backed job queues, and to manage workers processing jobs from those queues. 112 | 113 | As an example, let's add a simple job to a queue that writes a message to Magento's system log. Mage Resque bundles Mns_Resque_Model_Job_Logmessage to do just this. 114 | 115 | $resque = Mage::getSingleton('mnsresque/factory')->create(); 116 | $resque->addJob( 117 | 'Mns_Resque_Model_Job_Logmessage', 118 | array('message'=>'foo')); 119 | 120 | You can pass any classname to addJob that identifies a class implementing a process() method. You can find out more about how Job classes work in the [PHP Redis README](https://github.com/chrisboulton/php-resque/blob/master/README.md). 121 | 122 | To process the queue and run background jobs, Mage Resque provides a job runner in the shell directory. To start it run the following command from your terminal. 123 | 124 | $ php shell/resque.php --daemon 125 | 126 | To stop the daemon gracefully (allow workers to finish their current job) run the following command. 127 | 128 | $ php shell/resque.php --quit 129 | 130 | To stop the daemon immediately (which means stopping workers potentially in the middle of a job) use the --terminate option. 131 | 132 | $ php shell/resque.php --terminate 133 | 134 | ### Running Unit Tests 135 | Mage Resque comes bundled with a UnitTest Suite. This suite serves as a regression safety net and as rough documentation on the use of the module. To execute the tests you will need to install Mage Resque's development dependencies. 136 | 137 | $ composer.phar install --dev 138 | 139 | If you have ran _composer.phar install_, you will need to delete composer.lock and the vendor directory, then re-run install with the --dev argument. 140 | 141 | To run the tests, in your Magento root directory, issue the following command from your terminal. 142 | 143 | $ phpunit -c vendor/ajbonner/mage-resque/tests/phpunit.xml 144 | 145 | Feedback and pull requests are very welcome. You can get in touch with me on twitter [@ajbonner](https://twitter.com/ajbonner) or via the [issues](https://github.com/ajbonner/mage-resque/issues) system here on github. 146 | -------------------------------------------------------------------------------- /app/code/community/Mns/Resque/Model/Runner.php: -------------------------------------------------------------------------------- 1 | getConfig()) { 46 | throw new Mns_Resque_Model_ConfigurationException('Cannot start resque runner without redis config set'); 47 | } 48 | 49 | if ($this->isDaemonRunning()) { 50 | throw new Mns_Resque_Model_DaemonAlreadyRunningException('Cannot start resque runner when daemon already running'); 51 | } 52 | 53 | $return = null; 54 | $command = $this->buildStartShellCommand($this->getConfig(), $this->getLogLevel(), $this->getQueue()); 55 | $this->disableOwnSignalHandlers(); 56 | system($command, $return); 57 | 58 | return $return; 59 | } 60 | 61 | /** 62 | * @param bool $stopImmediately 63 | * @return int 64 | * @throws Mns_Resque_Model_PidNotFoundException 65 | */ 66 | public function stop($stopImmediately = false) 67 | { 68 | $return = null; 69 | $command = $this->buildStopShellCommand($stopImmediately); 70 | system($command, $return); 71 | 72 | if ($return === 0) { 73 | unlink($this->buildPidfilePath()); 74 | } 75 | 76 | return $return; 77 | } 78 | 79 | /** 80 | * @param string $logfile 81 | * @return $this 82 | */ 83 | public function setLogfile($logfile) 84 | { 85 | $this->logfile = $logfile; 86 | return $this; 87 | } 88 | 89 | /** 90 | * @return string 91 | */ 92 | public function getLogfile() 93 | { 94 | return $this->logfile; 95 | } 96 | 97 | /** 98 | * @param string $pidfile 99 | * @return $this; 100 | */ 101 | public function setPidfile($pidfile) 102 | { 103 | $this->pidfile = $pidfile; 104 | return $this; 105 | } 106 | 107 | /** 108 | * @return string 109 | */ 110 | public function getPidfile() 111 | { 112 | return $this->pidfile; 113 | } 114 | 115 | /** 116 | * @return bool 117 | */ 118 | public function isDaemonRunning() 119 | { 120 | return file_exists($this->buildPidfilePath()); 121 | } 122 | 123 | /** 124 | * @param Mns_Resque_Model_Config $config 125 | * @param string $logLevel 126 | * @param string $queue 127 | * @return string 128 | */ 129 | protected function buildStartShellCommand($config, $logLevel, $queue) 130 | { 131 | return sprintf('PIDFILE=%s REDIS_BACKEND=%s REDIS_BACKEND_DB=%s QUEUE=%s COUNT=%s %s nohup %s >> %s 2>&1 &', 132 | $this->buildPidfilePath(), 133 | $config->getRedisBackend(), 134 | $config->getDatabase(), 135 | $this->getQueueEnv($queue), 136 | $config->getNumWorkers(), 137 | $this->getLogEnv($logLevel), 138 | Mage::getBaseDir() . DS . $config->getBinDir() . DS . 'resque', 139 | $this->buildLogfilePath()); 140 | } 141 | 142 | /** 143 | * @param bool $stopImmediately 144 | * @return string 145 | * @throws Mns_Resque_Model_PidNotFoundException 146 | */ 147 | protected function buildStopShellCommand($stopImmediately = false) 148 | { 149 | $pid = file_get_contents($this->buildPidfilePath()); 150 | 151 | if (! $pid) { 152 | throw new Mns_Resque_Model_PidNotFoundException('Cannot stop resque process pidfile not found: ' . Mage::getBaseDir('log') . DS . $this->pidfile); 153 | } 154 | 155 | $signal = ($stopImmediately) ? self::SIGNAL_TERMINATE : self::SIGNAL_GRACEFUL; 156 | 157 | return sprintf('kill -%s %s', $signal, $pid); 158 | } 159 | 160 | /** 161 | * @param string $logLevel 162 | * @return string 163 | */ 164 | protected function getLogEnv($logLevel) 165 | { 166 | $logEnv = ''; 167 | 168 | switch ($logLevel) { 169 | case self::LOG_NORMAL: 170 | $logEnv = 'VERBOSE=1'; 171 | break; 172 | case self::LOG_VERBOSE: 173 | $logEnv = 'VVERBOSE=1'; 174 | break; 175 | default: 176 | } 177 | 178 | return $logEnv; 179 | } 180 | 181 | /** 182 | * Disabling this process's own signal handlers allows 183 | * system()'d resque process handle them instead 184 | */ 185 | protected function disableOwnSignalHandlers() 186 | { 187 | declare(ticks = 1); 188 | pcntl_signal(SIGTERM, function(){}); 189 | pcntl_signal(SIGINT, function(){}); 190 | pcntl_signal(SIGQUIT, function(){}); 191 | pcntl_signal(SIGUSR1, function(){}); 192 | pcntl_signal(SIGUSR2, function(){}); 193 | pcntl_signal(SIGCONT, function(){}); 194 | } 195 | 196 | /** 197 | * @return string 198 | */ 199 | protected function buildPidfilePath() 200 | { 201 | return Mage::getBaseDir('log') . DS . $this->getPidfile(); 202 | } 203 | 204 | /** 205 | * @return string 206 | */ 207 | protected function buildLogfilePath() 208 | { 209 | return Mage::getBaseDir('log') . DS . $this->getLogFile(); 210 | } 211 | 212 | /** 213 | * @param string $queue 214 | * @return string 215 | */ 216 | protected function getQueueEnv($queue) 217 | { 218 | $queue = ($queue != '') ? $queue : '*'; 219 | 220 | return $queue; 221 | } 222 | } 223 | --------------------------------------------------------------------------------