Forráskód Böngészése

Tweaks of scheduling and job responses

Jordi Boggiano 7 éve
szülő
commit
db90d0c015

+ 0 - 7
src/Packagist/WebBundle/Command/UpdatePackagesCommand.php

@@ -102,13 +102,6 @@ class UpdatePackagesCommand extends ContainerAwareCommand
             $idsGroup = array_splice($ids, 0, 100);
 
             foreach ($idsGroup as $id) {
-                if ($scheduler->hasPendingUpdateJob($id, $updateEqualRefs, $deleteBefore)) {
-                    if ($verbose) {
-                        $output->writeln('Package '.$id.' already has a pending job, skipping');
-                    }
-                    continue;
-                }
-
                 $job = $scheduler->scheduleUpdate($id, $updateEqualRefs, $deleteBefore, $randomTimes ? new \DateTime('+'.rand(1, 1800).'seconds') : null);
                 if ($verbose) {
                     $output->writeln('Scheduled update job '.$job->getId().' for package '.$id);

+ 26 - 5
src/Packagist/WebBundle/Service/Scheduler.php

@@ -28,12 +28,35 @@ class Scheduler
             throw new \UnexpectedValueException('Expected Package instance or int package id');
         }
 
+        $pendingJobId = $this->getPendingUpdateJob($packageOrId, $updateEqualRefs, $deleteBefore);
+        if ($pendingJobId) {
+            $pendingJob = $this->doctrine->getManager()->getRepository(Job::class)->findOneBy(['id' => $pendingJobId]);
+
+            // pending job will execute before the one we are trying to schedule so skip scheduling
+            if (
+                (!$pendingJob->getExecuteAfter() && $executeAfter)
+                || ($pendingJob->getExecuteAfter() && $executeAfter && $pendingJob->getExecuteAfter() < $executeAfter)
+            ) {
+                return $pendingJob;
+            }
+
+            // neither job has executeAfter, so the pending one is equivalent to the one we are trying to schedule and we can skip scheduling
+            if (!$pendingJob->getExecuteAfter() && !$executeAfter) {
+                return $pendingJob;
+            }
+
+            // pending job will somehow execute after the one we are scheduling so we mark it complete and schedule a new job to run immediately
+            $pendingJob->start();
+            $pendingJob->complete(['status' => Job::STATUS_COMPLETED, 'message' => 'Another job is attempting to schedule immediately for this package, aborting scheduled-for-later update']);
+            $this->doctrine->getManager()->flush($pendingJob);
+        }
+
         return $this->createJob('package:updates', ['id' => $packageOrId, 'update_equal_refs' => $updateEqualRefs, 'delete_before' => $deleteBefore], $packageOrId, $executeAfter);
     }
 
-    public function hasPendingUpdateJob(int $packageId, $updateEqualRefs = false, $deleteBefore = false): bool
+    private function getPendingUpdateJob(int $packageId, $updateEqualRefs = false, $deleteBefore = false)
     {
-        $result = $this->doctrine->getManager()->getConnection()->fetchAssoc('SELECT payload FROM job WHERE packageId = :package AND status = :status', [
+        $result = $this->doctrine->getManager()->getConnection()->fetchAssoc('SELECT id, payload FROM job WHERE packageId = :package AND status = :status', [
             'package' => $packageId,
             'status' => Job::STATUS_QUEUED,
         ]);
@@ -41,11 +64,9 @@ class Scheduler
         if ($result) {
             $payload = json_decode($result['payload'], true);
             if ($payload['update_equal_refs'] === $updateEqualRefs && $payload['delete_before'] === $deleteBefore) {
-                return true;
+                return $result['id'];
             }
         }
-
-        return false;
     }
 
     /**

+ 4 - 4
src/Packagist/WebBundle/Service/UpdaterWorker.php

@@ -102,14 +102,14 @@ class UpdaterWorker
             if (strpos($e->getMessage(), 'file could not be downloaded: failed to open stream: HTTP request failed!')) {
                 return [
                     'status' => Job::STATUS_FAILED,
-                    'message' => 'Package data could not be downloaded. Could not reach remote VCS server. Please try again later.',
+                    'message' => 'Package data of '.$package->getName().' could not be downloaded. Could not reach remote VCS server. Please try again later.',
                     'exception' => $e
                 ];
             }
 
             return [
                 'status' => Job::STATUS_FAILED,
-                'message' => 'Package data could not be downloaded.',
+                'message' => 'Package data of '.$package->getName().' could not be downloaded.',
                 'exception' => $e
             ];
         } catch (\Throwable $e) {
@@ -125,7 +125,7 @@ class UpdaterWorker
 
             return [
                 'status' => Job::STATUS_FAILED,
-                'message' => 'Update failed',
+                'message' => 'Update of '.$package->getName().' failed',
                 'details' => '<pre>'.$io->getOutput().'</pre>',
                 'exception' => $e,
             ];
@@ -135,7 +135,7 @@ class UpdaterWorker
 
         return [
             'status' => Job::STATUS_COMPLETED,
-            'message' => 'Update complete',
+            'message' => 'Update of '.$package->getName().' complete',
             'details' => '<pre>'.$io->getOutput().'</pre>'
         ];
     }