Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
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 <[email protected]>
  • Loading branch information
come-nc committed Jun 5, 2025
commit ee3abdd81bc75aa6b373dcc6eec0bdd6aeda0c5a
59 changes: 59 additions & 0 deletions lib/private/Route/CachingRouter.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use OCP\IRequest;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Routing\RouteCollection;

class CachingRouter extends Router {
protected ICache $cache;
Expand Down Expand Up @@ -54,4 +55,62 @@ public function generate($name, $parameters = [], $absolute = false) {
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);
}
}