Skip to content

Commit f6b214f

Browse files
authored
Write schema cache to temporary file before atomically updating it (#2703)
1 parent 596cab7 commit f6b214f

File tree

2 files changed

+20
-15
lines changed

2 files changed

+20
-15
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ You can find and compare releases at the [GitHub release page](https://github.co
99

1010
## Unreleased
1111

12+
## v6.62.1
13+
14+
### Fixed
15+
16+
- Write schema cache to temporary file before atomically updating it https://github.com/nuwave/lighthouse/pull/2703
17+
1218
## v6.62.0
1319

1420
### Changed

src/Schema/AST/ASTCache.php

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Nuwave\Lighthouse\Schema\AST;
44

5-
use Illuminate\Container\Container;
65
use Illuminate\Contracts\Config\Repository as ConfigRepository;
76
use Illuminate\Filesystem\Filesystem;
87
use Nuwave\Lighthouse\Exceptions\InvalidSchemaCacheContentsException;
@@ -21,8 +20,10 @@ class ASTCache
2120

2221
protected string $path;
2322

24-
public function __construct(ConfigRepository $config)
25-
{
23+
public function __construct(
24+
ConfigRepository $config,
25+
protected Filesystem $filesystem,
26+
) {
2627
/** @var CacheConfig $cacheConfig */
2728
$cacheConfig = $config->get('lighthouse.schema_cache');
2829
$this->enable = (bool) $cacheConfig['enable'];
@@ -45,24 +46,27 @@ public function set(DocumentAST $documentAST): void
4546
value: $documentAST->toArray(),
4647
return: true,
4748
);
49+
$contents = /** @lang PHP */ "<?php return {$variable};";
4850

49-
$this->filesystem()->put(
50-
path: $this->path(),
51-
contents: /** @lang PHP */ "<?php return {$variable};",
52-
lock: true,
53-
);
51+
// Since the schema cache can be very large, we write it to a temporary file first.
52+
// This avoids issues with the filesystem not being able to write large files atomically.
53+
// Then, we move the temporary file to the final location which is an atomic operation.
54+
$path = $this->path();
55+
$partialPath = "{$path}.partial";
56+
$this->filesystem->put(path: $partialPath, contents: $contents, lock: true);
57+
$this->filesystem->move(path: $partialPath, target: $path);
5458
}
5559

5660
public function clear(): void
5761
{
58-
$this->filesystem()->delete($this->path());
62+
$this->filesystem->delete($this->path());
5963
}
6064

6165
/** @param callable(): DocumentAST $build */
6266
public function fromCacheOrBuild(callable $build): DocumentAST
6367
{
6468
$path = $this->path();
65-
if ($this->filesystem()->exists($path)) {
69+
if ($this->filesystem->exists($path)) {
6670
$ast = require $path;
6771
if (! is_array($ast)) {
6872
throw new InvalidSchemaCacheContentsException($path, $ast);
@@ -78,9 +82,4 @@ public function fromCacheOrBuild(callable $build): DocumentAST
7882

7983
return $documentAST;
8084
}
81-
82-
protected function filesystem(): Filesystem
83-
{
84-
return Container::getInstance()->make(Filesystem::class);
85-
}
8685
}

0 commit comments

Comments
 (0)