function testResolveAsyncJobClearMutexWhenNotInWaitAsync() { // create a queuestore $q = new JQStore_Array(); $mJob = $q->enqueue(new SampleAsyncJob(NULL)); $mJob->markJobStarted(); $mJob->markJobFailed(); $this->assertEquals(JQManagedJob::STATUS_FAILED, $mJob->getStatus()); try { JQManagedJob::resolveWaitAsyncJob($q, $mJob->getJobId(), NULL); } catch (JQManagedJob_InvalidStateException $e) { $this->assertEquals($mJob, $q->getWithMutex($mJob->getJobId())); return; } $this->fail('should never get here'); }
print <<<EXPLAIN *********************************************************************************************************** This test makes sure that a fatal error during job execution will result in the job being marked failed. This exercises our shutdown error detection. This test works if you see output indicating: - a job starts running - then a fatal error - finally "Status change: running => failed" *********************************************************************************************************** EXPLAIN; class SampleFatalJob extends SampleLoggingJob { function run(JQManagedJob $mJob) { // causes a FATAL error $foo->bar(); } } // run a job that will FATAL $q = new JQStore_Array(); $goodJob = $q->enqueue(new SampleFatalJob()); if ($q->count('test') !== 1) { throw new Exception("assert failed"); } SampleJobCounter::reset(); // Start a worker to run the job. $w = new JQWorker($q, array('queueName' => 'test', 'exitIfNoJobs' => true, 'verbose' => true, 'enableJitter' => false)); $w->start();
function testJobsAutoRetryOnFailure() { // create a queuestore $maxAttempts = 5; $q = new JQStore_Array(); $mJob = $q->enqueue(new SampleFailJob(array('maxAttempts' => $maxAttempts))); // Start a worker to run the jobs. $w = new JQWorker($q, array('queueName' => 'test', 'exitIfNoJobs' => true, 'silent' => true, 'enableJitter' => false)); $w->start(); $this->assertEquals(0, $q->count('test', 'queued')); $this->assertEquals(1, $q->count('test', 'failed')); $this->assertEquals($maxAttempts, $mJob->getAttemptNumber()); }
<?php /** * This script verifies that a job that generates a CATCHABLE FATAL ERROR will gracefully fail the job... */ require_once dirname(__FILE__) . '/../TestCommon.php'; print <<<EXPLAIN *********************************************************************************************************** This test makes sure that a fatal error AFTER a job runs successfully doesn't try to fail the already completed job. This test works if you see output indicating: - a successful job run - then a fatal error - no subsequent job status changes *********************************************************************************************************** EXPLAIN; // run a job that will FATAL $q = new JQStore_Array(); $goodJob = $q->enqueue(new SampleLoggingJob()); if ($q->count('test') !== 1) { throw new Exception("assert failed"); } SampleJobCounter::reset(); // Start a worker to run the job. $w = new JQWorker($q, array('queueName' => 'test', 'exitIfNoJobs' => true, 'silent' => true, 'enableJitter' => false)); $w->start(); // trigger a fatal error; shouldn't fail our job, though as we should be out-of-scope. $foo->bar();
<?php // we have the job in a separate file as a proof-of-concept that the declare(ticks=1) works in this situation. require_once 'jq-test-signal-job.php'; // to have JQJobs be able to gracefully handle SIGKILL (or other *immediate termination* signals) the declare() must be at this level. declare (ticks=1); // The idea of these signal tests is to test the time between the SIGTERM and the SIGKILL; // THERE are 2 cases to test: // 1. Job finishes in time window between SIGTERM and SIGKILL, expect JOB COMPLETION and GRACEFUL SHUTDOWN // The way this test works is to run a job that takes 3 seconds; send TERM after 1s and KILL after 7 // 2. Job doesn't finish before SIGKILL; expect JOB FAILURE (retry) AND NON-GRACEFUL SHUTDOWN // The way this test works is to run a job that takes 10 seconds; send TERM after 1s and KILL after 7 if (!isset($argv[1])) { die("Pass one argument with integer number of seconds the job under signal test should take."); } $params = json_decode($argv[1], true); print "Job Runtime: {$params['jobRunTime']}\n"; print "System TERM-to-KILL window: {$params['systemTermToKillWindow']}\n"; $q = new JQStore_Array(); $q->enqueue(new UninterruptibleJob($params['jobRunTime'])); $q->enqueue(new UninterruptibleJob()); // this 2nd job is there so that in test #1, that the worker has more work to do but gracefully exits anyway due to receiving the signal $w = new JQWorker($q, array('verbose' => true, 'enableJitter' => false, 'gracefulShutdownTimeout' => $params['systemTermToKillWindow'])); $w->start();