diff options
author | Côme Chilliet <come.chilliet@nextcloud.com> | 2025-05-06 17:19:30 +0200 |
---|---|---|
committer | Côme Chilliet <come.chilliet@nextcloud.com> | 2025-06-05 17:58:46 +0200 |
commit | ee3abdd81bc75aa6b373dcc6eec0bdd6aeda0c5a (patch) | |
tree | 4c9db7f3902bc003125245b07f980bcaacb611e9 | |
parent | 5488f7e8b1e2676352edfcd0cf445144b8134db2 (diff) | |
download | nextcloud-server-ee3abdd81bc75aa6b373dcc6eec0bdd6aeda0c5a.tar.gz nextcloud-server-ee3abdd81bc75aa6b373dcc6eec0bdd6aeda0c5a.zip |
feat(router): Cache routes in local cache if possible
This is not ideal because serializing the routecollection is not easy.
It seems Symfony has its own way of doing things by dumping routes to a
PHP file, maybe that would be better, but it would mean pulling a new
symfony dependency and maybe refactor our Router.
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
-rw-r--r-- | lib/private/Route/CachingRouter.php | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/lib/private/Route/CachingRouter.php b/lib/private/Route/CachingRouter.php index 7dd26827d3c..9ceb08b61e2 100644 --- a/lib/private/Route/CachingRouter.php +++ b/lib/private/Route/CachingRouter.php @@ -15,6 +15,7 @@ use OCP\IConfig; use OCP\IRequest; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; +use Symfony\Component\Routing\RouteCollection; class CachingRouter extends Router { protected ICache $cache; @@ -54,4 +55,62 @@ class CachingRouter extends Router { return $url; } } + + private function serializeRouteCollection(RouteCollection $collection): array { + return array_map( + fn (Route $route) => [$route->getPath(), $route->getDefaults(), $route->getRequirements(), $route->getOptions(), $route->getHost(), $route->getSchemes(), $route->getMethods(), $route->getCondition()], + $collection->all(), + ); + } + + private function unserializeRouteCollection(array $data): RouteCollection { + $collection = new RouteCollection(); + foreach ($data as $name => $details) { + $route = new Route(...$details); + $collection->add($name, $route); + } + return $collection; + } + + /** + * Loads the routes + * + * @param null|string $app + */ + public function loadRoutes($app = null): void { + $this->eventLogger->start('cacheroute:load:' . $app, 'Loading Routes (using cache) for ' . $app); + if (is_string($app)) { + $app = $this->appManager->cleanAppId($app); + } + + $requestedApp = $app; + if ($this->loaded) { + $this->eventLogger->end('cacheroute:load:' . $app); + return; + } + if (is_null($app)) { + $cachedRoutes = $this->cache->get('root:'); + if ($cachedRoutes) { + $this->root = $this->unserializeRouteCollection($cachedRoutes); + $this->loaded = true; + $this->eventLogger->end('cacheroute:load:' . $app); + return; + } + } else { + if (isset($this->loadedApps[$app])) { + $this->eventLogger->end('cacheroute:load:' . $app); + return; + } + $cachedRoutes = $this->cache->get('root:' . $requestedApp); + if ($cachedRoutes) { + $this->root = $this->unserializeRouteCollection($cachedRoutes); + $this->loadedApps[$app] = true; + $this->eventLogger->end('cacheroute:load:' . $app); + return; + } + } + parent::loadRoutes($app); + $this->cache->set('root:' . $requestedApp, $this->serializeRouteCollection($this->root), 3600); + $this->eventLogger->end('cacheroute:load:' . $app); + } } |