Skip to content

Commit 6a429bc

Browse files
authored
Merge pull request #35 from studio-design/refactor/spec-loader-cache-optimization
refactor: add cache management to OpenApiSpecLoader
2 parents 6dcfb2c + a97e22b commit 6a429bc

3 files changed

Lines changed: 60 additions & 0 deletions

File tree

src/OpenApiSpecLoader.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,22 @@ public static function load(string $specName): array
7979
return $decoded;
8080
}
8181

82+
/**
83+
* Clear only the cached specs, keeping basePath and stripPrefixes intact.
84+
*/
85+
public static function clearCache(): void
86+
{
87+
self::$cache = [];
88+
}
89+
90+
/**
91+
* Remove a single spec from the cache.
92+
*/
93+
public static function evict(string $specName): void
94+
{
95+
unset(self::$cache[$specName]);
96+
}
97+
8298
public static function reset(): void
8399
{
84100
self::$basePath = null;

src/PHPUnit/OpenApiCoverageExtension.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ public function notify(ExecutionFinished $event): void
7979
{
8080
$results = $this->computeAllResults();
8181

82+
// Free cached spec data now that coverage has been computed
83+
OpenApiSpecLoader::clearCache();
84+
8285
if ($results === []) {
8386
return;
8487
}

tests/Unit/OpenApiSpecLoaderTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,45 @@ public function reset_clears_all_state(): void
105105
$this->expectException(RuntimeException::class);
106106
OpenApiSpecLoader::getBasePath();
107107
}
108+
109+
#[Test]
110+
public function clear_cache_keeps_config(): void
111+
{
112+
$fixturesPath = __DIR__ . '/../fixtures/specs';
113+
OpenApiSpecLoader::configure($fixturesPath, ['/api']);
114+
115+
// Load to populate cache
116+
OpenApiSpecLoader::load('petstore-3.0');
117+
118+
OpenApiSpecLoader::clearCache();
119+
120+
// Config is preserved
121+
$this->assertSame($fixturesPath, OpenApiSpecLoader::getBasePath());
122+
$this->assertSame(['/api'], OpenApiSpecLoader::getStripPrefixes());
123+
124+
// Cache is cleared — next load reads from disk again
125+
$spec = OpenApiSpecLoader::load('petstore-3.0');
126+
$this->assertSame('3.0.3', $spec['openapi']);
127+
}
128+
129+
#[Test]
130+
public function evict_removes_single_spec_from_cache(): void
131+
{
132+
$fixturesPath = __DIR__ . '/../fixtures/specs';
133+
OpenApiSpecLoader::configure($fixturesPath);
134+
135+
// Load two specs
136+
$first30 = OpenApiSpecLoader::load('petstore-3.0');
137+
$first31 = OpenApiSpecLoader::load('petstore-3.1');
138+
139+
// Evict only 3.0
140+
OpenApiSpecLoader::evict('petstore-3.0');
141+
142+
// 3.1 still cached (same reference)
143+
$this->assertSame($first31, OpenApiSpecLoader::load('petstore-3.1'));
144+
145+
// 3.0 reloaded from disk (equal but fresh instance)
146+
$reloaded30 = OpenApiSpecLoader::load('petstore-3.0');
147+
$this->assertSame($first30, $reloaded30);
148+
}
108149
}

0 commit comments

Comments
 (0)