Skip to content

Commit bc9c5a0

Browse files
committed
Optimize fetching of remaining package names in security advisories API endpoint to do less redis round trips
1 parent c8f763d commit bc9c5a0

File tree

7 files changed

+62
-5
lines changed

7 files changed

+62
-5
lines changed

config/packages/snc_redis.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ snc_redis:
1818
commands:
1919
fetchVersionIds: 'App\Redis\FetchVersionIds'
2020
downloadsIncr: 'App\Redis\DownloadsIncr'
21+
packagesExist: 'App\Redis\PackagesExist'
2122

2223
cache:
2324
type: predis

src/Controller/ApiController.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,11 @@ public function securityAdvisoryAction(Request $request, ProviderManager $provid
366366

367367
// Ensure known packages are returned even if no advisory is present to ensure they do not get retried by composer in lower prio repos
368368
// Do a max of 1000 packages to prevent abuse
369-
foreach (array_slice($packageNames, 0, 1000) as $name) {
370-
if (!isset($response['advisories'][$name]) && $providerManager->packageExists($name)) {
369+
$packagesToCheck = array_slice($packageNames, 0, 1000);
370+
$packageExists = $providerManager->packagesExist($packagesToCheck);
371+
372+
foreach ($packagesToCheck as $name) {
373+
if (!isset($response['advisories'][$name]) && ($packageExists[strtolower($name)] ?? false)) {
371374
$response['advisories'][$name] = [];
372375
}
373376
}

src/Model/DownloadManager.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ public function addDownloads(array $jobs, string $ip, string $phpMinor, string $
186186
$args[] = $month;
187187
$args[] = $throttleExpiry;
188188

189-
/** @phpstan-ignore-next-line */
189+
/** @phpstan-ignore-next-line method.notFound */
190190
$this->redis->downloadsIncr(...$args);
191191
}
192192

src/Model/ProviderManager.php

+24
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,30 @@ public function packageExists(string $name): bool
2929
return (bool) $this->redis->sismember('set:packages', strtolower($name));
3030
}
3131

32+
/**
33+
* Check if multiple packages exist in the registry
34+
*
35+
* @param string[] $names Package names to check
36+
* @return array<string, bool> Associative array of package name => exists
37+
*/
38+
public function packagesExist(array $names): array
39+
{
40+
if (0 === count($names)) {
41+
return [];
42+
}
43+
44+
$names = array_map('strtolower', $names);
45+
/** @phpstan-ignore-next-line method.notFound */
46+
$results = $this->redis->packagesExist(...$names);
47+
48+
$exists = [];
49+
foreach ($results as $i => $result) {
50+
$exists[$names[$i]] = (bool) $result;
51+
}
52+
53+
return $exists;
54+
}
55+
3256
public function packageIsProvided(string $name): bool
3357
{
3458
if (false === $this->initializedProviders) {

src/Model/VersionIdCache.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function augmentDownloadPayloadWithIds(array $payload): array
3333
$args[] = 'ids:'.strtolower($package['name']);
3434
$args[] = strtolower($package['version']);
3535
}
36-
/** @phpstan-ignore-next-line */
36+
/** @phpstan-ignore-next-line method.notFound */
3737
$results = $this->redis->fetchVersionIds(...$args);
3838

3939
foreach ($results as $key => $result) {

src/Redis/PackagesExist.php

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of Packagist.
5+
*
6+
* (c) Jordi Boggiano <[email protected]>
7+
* Nils Adermann <[email protected]>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace App\Redis;
14+
15+
class PackagesExist extends \Predis\Command\ScriptCommand
16+
{
17+
public function getScript(): string
18+
{
19+
return <<<LUA
20+
local results = {};
21+
for i, packageName in ipairs(ARGV) do
22+
local exists = redis.call("SISMEMBER", "set:packages", packageName);
23+
table.insert(results, exists);
24+
end
25+
26+
return results;
27+
LUA;
28+
}
29+
}

src/Security/RecaptchaHelper.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public function increaseCounter(RecaptchaContext $context): void
7070
return;
7171
}
7272

73-
/** @phpstan-ignore-next-line */
73+
/** @phpstan-ignore-next-line method.notFound */
7474
$this->redisCache->incrFailedLoginCounter(...$context->getRedisKeys());
7575
}
7676

0 commit comments

Comments
 (0)