Skip to content

Commit

Permalink
Atomic compiled file write operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
serge-kvashnin committed May 24, 2024
1 parent 572bbc9 commit 2a33e42
Showing 1 changed file with 29 additions and 1 deletion.
30 changes: 29 additions & 1 deletion src/Configurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ final class Configurator
private ContainerInterface|null $container = null;
private string|null $class = null;
private string|null $filename = null;
private string|null $dir = null;
private int $state;

public function __construct(
Expand Down Expand Up @@ -94,6 +95,7 @@ public function snapshot(string $dir, string $class = 'Container'): self
}

$this->filename = $dir . DIRECTORY_SEPARATOR . $class . '.php';
$this->dir = $dir;
$this->state = !file_exists($this->filename) ? self::COMPILING : self::LOADING;
$this->class = $class;

Expand Down Expand Up @@ -152,7 +154,7 @@ public function container(): ContainerInterface

if ($this->state === self::COMPILING) {
$compiler = new ContainerCompiler($this->definitions);
file_put_contents($this->filename, $compiler->compile($this->class)); // TODO: use atomic file write
$this->write($this->dir, $this->filename, $compiler->compile($this->class));
$this->state = self::LOADING;
}

Expand Down Expand Up @@ -211,4 +213,30 @@ private function array(array $configuration): void
);
}
}

private function write(string $dir, string $filename, string $content): void
{
if (!is_dir($dir)) {
if (!mkdir($dir, recursive: true) && !is_dir($dir)) {
throw new ContainerException("Failed to create directory '{$dir}'.");
}
}

if (false === $temp = tempnam($dir, basename($filename))) {
throw new ContainerException("Failed to write temporary file to '{$dir}'.");
}

if (!chmod($temp, 0666)) {
throw new ContainerException("Cannot change permissions for '{$temp}'.");
}

if (!file_put_contents($temp, $content)) {
throw new ContainerException("Failed to write temporary file '{$temp}'.");
}

if (!rename($temp, $filename)) {
unlink($temp);
throw new ContainerException("Failed to rename temporary file '{$temp}' to '{$filename}'.");
}
}
}

0 comments on commit 2a33e42

Please sign in to comment.