Beispiel #1
0
 private function jobThatWasCreated($relativeTime)
 {
     $wasCreatedAt = T\Moment::fromTimestamp(strtotime($relativeTime), T\now()->seconds());
     $job = $this->getMockBuilder('Recruiter\\JobAfterFailure')->disableOriginalConstructor()->setMethods(['createdAt', 'scheduleAt'])->getMock();
     $job->expects($this->any())->method('createdAt')->will($this->returnValue($wasCreatedAt));
     return $job;
 }
Beispiel #2
0
 public function cleanScheduled(Interval $gracePeriod = null)
 {
     $upperLimit = T\now();
     if (!is_null($gracePeriod)) {
         $upperLimit = $upperLimit->before($gracePeriod);
     }
     return $this->repository->cleanScheduled($upperLimit);
 }
Beispiel #3
0
 public function testNotWithstandingCrashesJobsAreEventuallyPerformed()
 {
     $this->limitTo(100)->forAll(Generator\bind(Generator\choose(1, 4), function ($workers) {
         return Generator\tuple(Generator\constant($workers), Generator\seq(Generator\oneOf(Generator\map(function ($durationAndTag) {
             list($duration, $tag) = $durationAndTag;
             return ['enqueueJob', $duration, $tag];
         }, Generator\tuple(Generator\nat(), Generator\elements(['generic', 'fast-lane']))), Generator\map(function ($workerIndex) {
             return ['restartWorkerGracefully', $workerIndex];
         }, Generator\choose(0, $workers - 1)), Generator\map(function ($workerIndex) {
             return ['restartWorkerByKilling', $workerIndex];
         }, Generator\choose(0, $workers - 1)), Generator\constant('restartRecruiterGracefully'), Generator\constant('restartRecruiterByKilling'), Generator\map(function ($milliseconds) {
             return ['sleep', $milliseconds];
         }, Generator\choose(1, 1000)))));
     }))->hook(Listener\log('/tmp/recruiter-test-iterations.log'))->hook(Listener\collectFrequencies())->disableShrinking()->then(function ($tuple) {
         list($workers, $actions) = $tuple;
         $this->clean();
         $this->start($workers);
         foreach ($actions as $action) {
             $this->logAction($action);
             if (is_array($action)) {
                 $arguments = $action;
                 $method = array_shift($arguments);
                 call_user_func_array([$this, $method], $arguments);
             } else {
                 $this->{$action}();
             }
         }
         $estimatedTime = max(count($actions) * 4, 60);
         Timeout::inSeconds($estimatedTime, function () {
             return "all {$this->jobs} jobs to be performed. Now is " . date('c') . " Logs: " . $this->files();
         })->until(function () {
             return $this->jobRepository->countArchived() === $this->jobs;
         });
         $at = T\now();
         $statistics = $this->recruiter->statistics($tag = null, $at);
         $this->assertInvariantsOnStatistics($statistics);
         // TODO: remove duplication
         $statisticsByTag = [];
         $cumulativeThroughput = 0;
         foreach (['generic', 'fast-lane'] as $tag) {
             $statisticsByTag[$tag] = $this->recruiter->statistics($tag, $at);
             $this->assertInvariantsOnStatistics($statisticsByTag[$tag]);
             $cumulativeThroughput += $statisticsByTag[$tag]['throughput']['value'];
         }
         var_dump($statistics, $statisticsByTag);
         // TODO: add tolerance
         $this->assertEquals($statistics['throughput']['value'], $cumulativeThroughput);
     });
 }
Beispiel #4
0
 private static function estimateHowManyRetriesIn($timeTable)
 {
     $now = T\now()->seconds();
     $howManyRetries = 0;
     $timeWindowInSeconds = 0;
     foreach ($timeTable as $timeWindow => $rescheduleTime) {
         $timeWindowInSeconds = $now - strtotime($timeWindow, $now) - $timeWindowInSeconds;
         if ($timeWindowInSeconds <= 0) {
             throw new Exception("Time window `{$timeWindow}` is invalid, must be in the past");
         }
         $rescheduleTimeInSeconds = strtotime($rescheduleTime, $now) - $now;
         if ($rescheduleTimeInSeconds <= 0) {
             throw new Exception("Reschedule time `{$rescheduleTime}` is invalid, must be in the future");
         }
         if ($rescheduleTimeInSeconds > $timeWindowInSeconds) {
             throw new Exception("Reschedule time `{$rescheduleTime}` is invalid, must be greater than the time window");
         }
         $howManyRetries += floor($timeWindowInSeconds / $rescheduleTimeInSeconds);
     }
     return $howManyRetries;
 }
Beispiel #5
0
 private function aJob()
 {
     $workable = $this->getMockBuilder('Recruiter\\Workable')->getMock();
     return Job::around($workable, $this->repository)->scheduleAt(T\now()->before(T\seconds(5)));
 }
Beispiel #6
0
 public function inBackground()
 {
     return $this->scheduleAt(T\now());
 }
Beispiel #7
0
 public function completedWith($result)
 {
     $this->endedAt = T\now();
     $this->completedWith = $result;
 }
Beispiel #8
0
 public function recentHistory($group = null, T\Moment $at = null, array $query = [])
 {
     if ($at === null) {
         $at = T\now();
     }
     $lastMinute = array_merge($query, ['last_execution.ended_at' => ['$gt' => T\MongoDate::from($at->before(T\minute(1))), '$lte' => T\MongoDate::from($at)]]);
     if ($group !== null) {
         $lastMinute['group'] = $group;
     }
     $document = $this->archived->aggregate($pipeline = [['$match' => $lastMinute], ['$project' => ['latency' => ['$subtract' => ['$last_execution.started_at', '$last_execution.scheduled_at']], 'execution_time' => ['$subtract' => ['$last_execution.ended_at', '$last_execution.started_at']]]], ['$group' => ['_id' => 1, 'throughput' => ['$sum' => 1], 'latency' => ['$avg' => '$latency'], 'execution_time' => ['$avg' => '$execution_time']]]]);
     if (!$document['ok']) {
         throw new RuntimeException("Pipeline failed: " . var_export($pipeline, true));
     }
     if (count($document['result']) === 0) {
         $throughputPerMinute = 0.0;
         $averageLatency = 0.0;
         $averageExecutionTime = 0;
     } else {
         if (count($document['result']) === 1) {
             $throughputPerMinute = (double) $document['result'][0]['throughput'];
             $averageLatency = $document['result'][0]['latency'] / 1000;
             $averageExecutionTime = $document['result'][0]['execution_time'] / 1000;
         } else {
             throw new RuntimeException("Result was not ok: " . var_export($document, true));
         }
     }
     return ['throughput' => ['value' => $throughputPerMinute, 'value_per_second' => $throughputPerMinute / 60.0], 'latency' => ['average' => $averageLatency], 'execution_time' => ['average' => $averageExecutionTime]];
 }