Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 28 | class JobManagerTest extends BaseJobManagerTest |
||
| 29 | { |
||
| 30 | use PriorityTestTrait; |
||
| 31 | use AutoRetryTrait; |
||
| 32 | use RetryableTrait; |
||
| 33 | use SaveJobTrait; |
||
| 34 | public static $connection; |
||
| 35 | |||
| 36 | public static function setUpBeforeClass() |
||
| 37 | { |
||
| 38 | if (self::$jobManager) { |
||
| 39 | parent::setUpBeforeClass(); |
||
| 40 | |||
| 41 | return; |
||
| 42 | } |
||
| 43 | |||
| 44 | $host = getenv('REDIS_HOST'); |
||
| 45 | $port = getenv('REDIS_PORT') ?: 6379; |
||
| 46 | $jobTimingClass = JobTiming::class; |
||
| 47 | $runClass = Run::class; |
||
| 48 | $predisClient = new Client(['scheme' => 'tcp', 'host' => $host, 'port' => $port]); |
||
| 49 | $predisClient->flushall(); |
||
| 50 | $predis = new Predis($predisClient); |
||
| 51 | |||
| 52 | self::$jobTimingManager = new JobTimingManager($jobTimingClass, false); |
||
| 53 | self::$runManager = new RunManager($runClass); |
||
| 54 | self::$jobManager = new JobManager(self::$runManager, self::$jobTimingManager, \Dtc\QueueBundle\Redis\Job::class, 'test_cache_key'); |
||
| 55 | self::$jobManager->setRedis($predis); |
||
| 56 | self::$jobManager->setMaxPriority(255); |
||
| 57 | self::$worker = new FibonacciWorker(); |
||
| 58 | parent::setUpBeforeClass(); |
||
| 59 | } |
||
| 60 | |||
| 61 | public function testConstructor() |
||
| 62 | { |
||
| 63 | $test = null; |
||
| 64 | try { |
||
| 65 | $test = new JobManager(self::$runManager, self::$jobTimingManager, Job::class, 'something'); |
||
| 66 | } catch (\Exception $exception) { |
||
| 67 | self::fail("shouldn't get here"); |
||
| 68 | } |
||
| 69 | self::assertNotNull($test); |
||
| 70 | } |
||
| 71 | |||
| 72 | public function testGetJobByWorker() |
||
| 73 | { |
||
| 74 | $failed = false; |
||
| 75 | try { |
||
| 76 | self::$jobManager->getJob(self::$worker->getName()); |
||
| 77 | $failed = true; |
||
| 78 | } catch (\Exception $exception) { |
||
| 79 | self::assertTrue(true); |
||
| 80 | } |
||
| 81 | self::assertFalse($failed); |
||
| 82 | } |
||
| 83 | |||
| 84 | public function testExpiredJob() |
||
| 85 | { |
||
| 86 | $this->drain(); |
||
| 87 | $job = new self::$jobClass(self::$worker, false, null); |
||
| 88 | $time = time() - 1; |
||
| 89 | $job->setExpiresAt(new \DateTime("@$time"))->fibonacci(1); |
||
| 90 | self::assertNotNull($job->getId(), 'Job id should be generated'); |
||
| 91 | |||
| 92 | $jobInQueue = self::$jobManager->getJob(); |
||
| 93 | self::assertNull($jobInQueue, 'The job should have been dropped...'); |
||
| 94 | |||
| 95 | $job = new self::$jobClass(self::$worker, false, null); |
||
| 96 | $time = time() - 1; |
||
| 97 | $job->setExpiresAt(new \DateTime("@$time"))->fibonacci(1); |
||
| 98 | |||
| 99 | $job = new self::$jobClass(self::$worker, false, null); |
||
| 100 | $time = time() - 1; |
||
| 101 | $job->setExpiresAt(new \DateTime("@$time"))->fibonacci(5); |
||
| 102 | |||
| 103 | $job = new self::$jobClass(self::$worker, false, null); |
||
| 104 | $time = time() - 1; |
||
| 105 | $job->setExpiresAt(new \DateTime("@$time"))->fibonacci(2); |
||
| 106 | |||
| 107 | $job = new self::$jobClass(self::$worker, false, null); |
||
| 108 | $job->fibonacci(1); |
||
| 109 | $jobInQueue = self::$jobManager->getJob(); |
||
| 110 | self::assertNotNull($jobInQueue, 'There should be a job.'); |
||
| 111 | self::assertEquals( |
||
| 112 | $job->getId(), |
||
| 113 | $jobInQueue->getId(), |
||
| 114 | 'Job id returned by manager should be the same' |
||
| 115 | ); |
||
| 116 | } |
||
| 117 | |||
| 118 | public function testInvalidReset() |
||
| 119 | { |
||
| 120 | $job = new \Dtc\QueueBundle\RabbitMQ\Job(); |
||
| 121 | $failure = false; |
||
| 122 | try { |
||
| 123 | self::$jobManager->resetJob($job); |
||
| 124 | $failure = true; |
||
| 125 | } catch (\InvalidArgumentException $exception) { |
||
| 126 | self::assertTrue(true); |
||
| 127 | } |
||
| 128 | self::assertFalse($failure); |
||
| 129 | } |
||
| 130 | |||
| 131 | public function testBatchJobs() |
||
| 132 | { |
||
| 133 | $this->drain(); |
||
| 134 | |||
| 135 | /** @var JobManager|\Dtc\QueueBundle\ORM\JobManager $jobManager */ |
||
| 136 | $worker = self::$worker; |
||
| 137 | $job1 = $worker->later()->fibonacci(1); |
||
| 138 | $job2 = $worker->batchLater()->fibonacci(1); |
||
| 139 | |||
| 140 | self::assertEquals($job1->getId(), $job2->getId()); |
||
| 141 | |||
| 142 | $job = self::$jobManager->getJob(); |
||
| 143 | self::assertEquals($job1->getId(), $job->getId()); |
||
| 144 | self::assertEquals($job1->getPriority(), $job->getPriority()); |
||
| 145 | |||
| 146 | $job = self::$jobManager->getJob(); |
||
| 147 | self::assertNull($job); |
||
| 148 | |||
| 149 | if (null !== self::$jobManager->getMaxPriority()) { |
||
| 150 | $job1 = $worker->later()->fibonacci(1); |
||
| 151 | $job2 = $worker->batchLater()->setPriority(3)->fibonacci(1); |
||
| 152 | self::assertEquals($job1->getId(), $job2->getId()); |
||
| 153 | self::assertNotEquals($job1->getPriority(), $job2->getPriority()); |
||
| 154 | |||
| 155 | $job = self::$jobManager->getJob(); |
||
| 156 | self::assertNotNull($job); |
||
| 157 | self::assertEquals($job1->getId(), $job->getId()); |
||
| 158 | self::assertEquals($job->getPriority(), $job2->getPriority()); |
||
| 159 | |||
| 160 | $job = self::$jobManager->getJob(); |
||
| 161 | self::assertNull($job); |
||
| 162 | } |
||
| 163 | |||
| 164 | $job1 = $worker->later(100)->fibonacci(1); |
||
| 165 | $time1 = new \DateTime('@'.time()); |
||
| 166 | $job2 = $worker->batchLater(0)->fibonacci(1); |
||
| 167 | $time2 = Util::getDateTimeFromDecimalFormat(Util::getMicrotimeDecimal()); |
||
| 168 | |||
| 169 | self::assertEquals($job1->getId(), $job2->getId()); |
||
| 170 | self::assertGreaterThanOrEqual($time1, $job2->getWhenAt()); |
||
| 171 | self::assertLessThanOrEqual($time2, $job2->getWhenAt()); |
||
| 172 | |||
| 173 | $job = self::$jobManager->getJob(); |
||
| 174 | self::assertNotNull($job); |
||
| 175 | self::assertEquals($job1->getId(), $job->getId()); |
||
| 176 | if (null !== self::$jobManager->getMaxPriority()) { |
||
| 177 | self::assertNotNull($job->getPriority()); |
||
| 178 | } else { |
||
| 179 | self::assertNull($job->getPriority()); |
||
| 180 | } |
||
| 181 | self::assertGreaterThanOrEqual($time1, $job->getWhenAt()); |
||
| 182 | self::assertLessThanOrEqual($time2, $job->getWhenAt()); |
||
| 183 | |||
| 184 | if (null !== self::$jobManager->getMaxPriority()) { |
||
| 185 | $job1 = $worker->later(100)->setPriority(3)->fibonacci(1); |
||
| 186 | $priority1 = $job1->getPriority(); |
||
| 187 | $time1 = Util::getDateTimeFromDecimalFormat(Util::getMicrotimeDecimal()); |
||
| 188 | $job2 = $worker->batchLater(0)->setPriority(1)->fibonacci(1); |
||
| 189 | $time2 = Util::getDateTimeFromDecimalFormat(Util::getMicrotimeDecimal()); |
||
| 190 | self::assertEquals($job1->getId(), $job2->getId()); |
||
| 191 | self::assertNotEquals($priority1, $job2->getPriority()); |
||
| 192 | |||
| 193 | self::assertGreaterThanOrEqual($time1, $job2->getWhenAt()); |
||
| 194 | self::assertLessThanOrEqual($time2, $job2->getWhenAt()); |
||
| 195 | } |
||
| 196 | |||
| 197 | $this->drain(); |
||
| 198 | } |
||
| 199 | |||
| 200 | public function testGetStatus() |
||
| 201 | { |
||
| 202 | list(, $status1) = $this->getBaseStatus(); |
||
| 203 | list(, $status2) = $this->getBaseStatus(); |
||
| 204 | $fibonacciStatus1 = $status1['fibonacci->fibonacci()']; |
||
| 205 | $fibonacciStatus2 = $status2['fibonacci->fibonacci()']; |
||
| 206 | |||
| 207 | self::assertEquals($fibonacciStatus1[BaseJob::STATUS_NEW] + 1, $fibonacciStatus2[BaseJob::STATUS_NEW]); |
||
| 208 | } |
||
| 209 | |||
| 210 | protected function getBaseStatus() |
||
| 211 | { |
||
| 212 | /** @var JobManager|\Dtc\QueueBundle\ORM\JobManager $jobManager */ |
||
| 213 | $jobManager = self::$jobManager; |
||
| 214 | $job = new self::$jobClass(self::$worker, false, null); |
||
| 215 | $job->fibonacci(1); |
||
| 216 | $status = $jobManager->getStatus(); |
||
| 217 | self::assertArrayHasKey('fibonacci->fibonacci()', $status); |
||
| 218 | $fibonacciStatus = $status['fibonacci->fibonacci()']; |
||
| 219 | |||
| 220 | self::assertArrayHasKey(BaseJob::STATUS_NEW, $fibonacciStatus); |
||
| 221 | self::assertArrayHasKey(BaseJob::STATUS_EXCEPTION, $fibonacciStatus); |
||
| 222 | self::assertArrayHasKey(BaseJob::STATUS_RUNNING, $fibonacciStatus); |
||
| 223 | self::assertArrayHasKey(BaseJob::STATUS_SUCCESS, $fibonacciStatus); |
||
| 224 | self::assertArrayHasKey(Job::STATUS_EXPIRED, $fibonacciStatus); |
||
| 225 | self::assertArrayHasKey(RetryableJob::STATUS_MAX_EXCEPTIONS, $fibonacciStatus); |
||
| 226 | self::assertArrayHasKey(RetryableJob::STATUS_MAX_FAILURES, $fibonacciStatus); |
||
| 227 | self::assertArrayHasKey(RetryableJob::STATUS_MAX_RETRIES, $fibonacciStatus); |
||
| 228 | |||
| 229 | return [$job, $status]; |
||
| 230 | } |
||
| 231 | } |
||
| 232 |