فهرست منبع

Remove usage of apcu storage for the list of packages

Jordi Boggiano 8 سال پیش
والد
کامیت
d4dd041ee0

+ 5 - 1
src/Packagist/WebBundle/Controller/PackageController.php

@@ -91,7 +91,7 @@ class PackageController extends Controller
         } elseif ($req->query->get('vendor')) {
             $names = $repo->getPackageNamesByVendor($req->query->get('vendor'));
         } else {
-            $names = $repo->getPackageNames();
+            $names = $this->get('packagist.provider_manager')->getPackageNames();
         }
 
         return new JsonResponse(array('packageNames' => $names));
@@ -119,6 +119,8 @@ class PackageController extends Controller
                 $em->persist($package);
                 $em->flush();
 
+                $this->get('packagist.provider_manager')->insertPackage($package);
+
                 $this->get('session')->getFlashBag()->set('success', $package->getName().' has been added to the package list, the repository will now be crawled.');
 
                 return new RedirectResponse($this->generateUrl('view_package', array('name' => $package->getName())));
@@ -626,6 +628,8 @@ class PackageController extends Controller
             $em->remove($package);
             $em->flush();
 
+            $this->get('packagist.provider_manager')->deletePackage($package);
+
             // attempt solr cleanup
             try {
                 /** @var \Solarium_Client $solarium */

+ 24 - 88
src/Packagist/WebBundle/Entity/PackageRepository.php

@@ -21,94 +21,6 @@ use Doctrine\DBAL\Cache\QueryCacheProfile;
  */
 class PackageRepository extends EntityRepository
 {
-    /**
-     * Lists all package names array(name => true)
-     *
-     * @var array
-     */
-    private $packageNames;
-
-    /**
-     * Lists all provided names array(name => true)
-     *
-     * @var array
-     */
-    private $providedNames;
-
-    public function packageExists($name)
-    {
-        $packages = $this->getRawPackageNames();
-
-        return isset($packages[$name]) || in_array(strtolower($name), $packages, true);
-    }
-
-    public function packageIsProvided($name)
-    {
-        $packages = $this->getProvidedNames();
-
-        return isset($packages[$name]) || in_array(strtolower($name), $packages, true);
-    }
-
-    public function getPackageNames($fields = array())
-    {
-        return array_keys($this->getRawPackageNames());
-    }
-
-    public function getRawPackageNames()
-    {
-        if (null !== $this->packageNames) {
-            return $this->packageNames;
-        }
-
-        $names = null;
-        $apc = extension_loaded('apcu');
-
-        if ($apc) {
-            $names = apcu_fetch('packagist_package_names');
-        }
-
-        if (!is_array($names)) {
-            $query = $this->getEntityManager()
-                ->createQuery("SELECT p.name FROM Packagist\WebBundle\Entity\Package p");
-
-            $names = $this->getPackageNamesForQuery($query);
-            $names = array_combine($names, array_map('strtolower', $names));
-            if ($apc) {
-                apcu_store('packagist_package_names', $names, 3600);
-            }
-        }
-
-        return $this->packageNames = $names;
-    }
-
-    public function getProvidedNames()
-    {
-        if (null !== $this->providedNames) {
-            return $this->providedNames;
-        }
-
-        $names = null;
-        $apc = extension_loaded('apcu');
-
-        // TODO use container to set caching key and ttl
-        if ($apc) {
-            $names = apcu_fetch('packagist_provided_names');
-        }
-
-        if (!is_array($names)) {
-            $query = $this->getEntityManager()
-                ->createQuery("SELECT p.packageName AS name FROM Packagist\WebBundle\Entity\ProvideLink p GROUP BY p.packageName");
-
-            $names = $this->getPackageNamesForQuery($query);
-            $names = array_combine($names, array_map('strtolower', $names));
-            if ($apc) {
-                apcu_store('packagist_provided_names', $names, 3600);
-            }
-        }
-
-        return $this->providedNames = $names;
-    }
-
     public function findProviders($name)
     {
         $query = $this->createQueryBuilder('p')
@@ -124,6 +36,30 @@ class PackageRepository extends EntityRepository
         return $query->getResult();
     }
 
+    public function getPackageNames()
+    {
+        $query = $this->getEntityManager()
+            ->createQuery("SELECT p.name FROM Packagist\WebBundle\Entity\Package p");
+
+        $names = $this->getPackageNamesForQuery($query);
+
+        return array_map('strtolower', $names);
+    }
+
+    public function getProvidedNames()
+    {
+        $query = $this->getEntityManager()
+            ->createQuery("SELECT p.packageName AS name
+                FROM Packagist\WebBundle\Entity\ProvideLink p
+                LEFT JOIN p.version v
+                WHERE v.development = true
+                GROUP BY p.packageName");
+
+        $names = $this->getPackageNamesForQuery($query);
+
+        return array_map('strtolower', $names);
+    }
+
     public function getPackageNamesByType($type)
     {
         $query = $this->getEntityManager()

+ 84 - 0
src/Packagist/WebBundle/Model/ProviderManager.php

@@ -0,0 +1,84 @@
+<?php
+
+/*
+ * This file is part of Packagist.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *     Nils Adermann <naderman@naderman.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Model;
+
+use Packagist\WebBundle\Entity\PackageRepository;
+use Packagist\WebBundle\Entity\Package;
+use Predis\Client;
+
+class ProviderManager
+{
+    protected $redis;
+    protected $repo;
+    protected $initializedProviders = false;
+
+    public function __construct(Client $redis, PackageRepository $repo)
+    {
+        $this->redis = $redis;
+        $this->repo = $repo;
+    }
+
+    public function packageExists($name)
+    {
+        return (bool) $this->redis->sismember('set:packages', strtolower($name));
+    }
+
+    public function packageIsProvided($name)
+    {
+        if (false === $this->initializedProviders) {
+            if (!$this->redis->scard('set:providers')) {
+                $this->populateProviders();
+            }
+            $this->initializedProviders = true;
+        }
+
+        return (bool) $this->redis->sismember('set:providers', strtolower($name));
+    }
+
+    public function getPackageNames()
+    {
+        if (!$this->redis->scard('set:packages')) {
+            $names = $this->repo->getPackageNames();
+            while ($names) {
+                $nameSlice = array_splice($names, 0, 1000);
+                $this->redis->sadd('set:packages', $nameSlice);
+            }
+        }
+
+        $names = $this->redis->smembers('set:packages');
+        sort($names, SORT_STRING);
+
+        return $names;
+    }
+
+    public function insertPackage(Package $package)
+    {
+        $this->redis->sadd('set:packages', strtolower($package->getName()));
+    }
+
+    public function deletePackage(Package $package)
+    {
+        $this->redis->srem('set:packages', strtolower($package->getName()));
+    }
+
+    private function populateProviders()
+    {
+        $names = $this->repo->getProvidedNames();
+        while ($names) {
+            $nameSlice = array_splice($names, 0, 1000);
+            $this->redis->sadd('set:providers', $nameSlice);
+        }
+
+        $this->redis->expire('set:providers', 3600);
+    }
+}

+ 7 - 1
src/Packagist/WebBundle/Resources/config/services.yml

@@ -1,7 +1,7 @@
 services:
     packagist.twig.extension:
         class: Packagist\WebBundle\Twig\PackagistExtension
-        arguments: [ '@doctrine' ]
+        arguments: [ '@packagist.provider_manager' ]
         tags:
             - { name: twig.extension }
 
@@ -75,6 +75,12 @@ services:
         arguments:
             - '@snc_redis.default_client'
 
+    packagist.provider_manager:
+        class: Packagist\WebBundle\Model\ProviderManager
+        arguments:
+            - '@snc_redis.default_client'
+            - '@packagist.package_repository'
+
     packagist.favorite_manager:
         class: Packagist\WebBundle\Model\FavoriteManager
         arguments:

+ 3 - 1
src/Packagist/WebBundle/Resources/views/macros.html.twig

@@ -63,10 +63,12 @@
 {% endmacro %}
 
 {% macro packageLink(packageName, type) %}
-    {%- if type == 'provide' and (packageName is existing_provider or packageName is existing_package) -%}
+    {%- if type == 'provide' -%}
         <a href="{{ path('view_providers', { 'name': packageName }) }}">{{ packageName }}</a>
     {%- elseif packageName is existing_package -%}
         <a href="{{ path('view_package', { 'name': packageName }) }}">{{ packageName }}</a>
+    {%- elseif packageName is existing_provider -%}
+        <a href="{{ path('view_providers', { 'name': packageName }) }}">{{ packageName }}</a>
     {%- else -%}
         {{ packageName }}
     {%- endif -%}

+ 7 - 11
src/Packagist/WebBundle/Twig/PackagistExtension.php

@@ -2,18 +2,18 @@
 
 namespace Packagist\WebBundle\Twig;
 
-use Symfony\Bridge\Doctrine\RegistryInterface;
+use Packagist\WebBundle\Model\ProviderManager;
 
 class PackagistExtension extends \Twig_Extension
 {
     /**
-     * @var \Symfony\Bridge\Doctrine\RegistryInterface
+     * @var ProviderManager
      */
-    private $doctrine;
+    private $providerManager;
 
-    public function __construct(RegistryInterface $doctrine)
+    public function __construct(providerManager $providerManager)
     {
-        $this->doctrine = $doctrine;
+        $this->providerManager = $providerManager;
     }
 
     public function getTests()
@@ -49,16 +49,12 @@ class PackagistExtension extends \Twig_Extension
             return false;
         }
 
-        $repo = $this->doctrine->getRepository('PackagistWebBundle:Package');
-
-        return $repo->packageExists($package);
+        return $this->providerManager->packageExists($package);
     }
 
     public function providerExistsTest($package)
     {
-        $repo = $this->doctrine->getRepository('PackagistWebBundle:Package');
-
-        return $repo->packageIsProvided($package);
+        return $this->providerManager->packageIsProvided($package);
     }
 
     public function prettifySourceReference($sourceReference)