-
-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathBrefKernelTrait.php
More file actions
152 lines (129 loc) · 4.37 KB
/
BrefKernelTrait.php
File metadata and controls
152 lines (129 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<?php declare(strict_types=1);
namespace Bref\SymfonyBridge;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\HttpKernelInterface;
trait BrefKernelTrait
{
public function isLambda(): bool
{
return getenv('LAMBDA_TASK_ROOT') !== false;
}
/**
* {@inheritDoc}
*/
public function getCacheDir()
{
if ($this->isLambda()) {
return '/tmp/cache/' . $this->environment;
}
return parent::getCacheDir();
}
/**
* {@inheritDoc}
*/
public function getLogDir()
{
if ($this->isLambda()) {
return '/tmp/log/';
}
return parent::getLogDir();
}
/**
* {@inheritDoc}
*
* When on the lambda, copy the cache dir over to /tmp where it is writable
* We have to do this before Symfony does anything else with the Kernel
* otherwise it might prematurely warm the cache before we can copy it
*
* @see https://github.com/brefphp/symfony-bridge/pull/37
*/
public function handle($request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
$this->prepareCacheDir(parent::getCacheDir(), $this->getCacheDir());
return parent::handle($request, $type, $catch);
}
/**
* {@inheritdoc}
*
* We also need to prepare the Cache dir in Kernel::boot in case we are in a Console or worker context
* in which Kernel::handle is not called.
*/
public function boot()
{
$this->prepareCacheDir(parent::getCacheDir(), $this->getCacheDir());
$this->ensureLogDir($this->getLogDir());
parent::boot();
}
/**
* Return the pre-warmed directories in var/cache/[env] that should be copied to
* a writable directory in the Lambda environment.
*
* For optimal performance one should prewarm the cache folder and override this
* function to return an empty array.
*/
protected function getWritableCacheDirectories(): array
{
return ['pools'];
}
protected function prepareCacheDir(string $readOnlyDir, string $writeDir): void
{
if (! $this->isLambda() || is_dir($writeDir) || ! is_dir($readOnlyDir)) {
return;
}
$startTime = microtime(true);
$cacheDirectoriesToCopy = $this->getWritableCacheDirectories();
$filesystem = new Filesystem;
$filesystem->mkdir($writeDir);
$scandir = scandir($readOnlyDir, SCANDIR_SORT_NONE);
if ($scandir === false) {
return;
}
foreach ($scandir as $item) {
if (in_array($item, ['.', '..'])) {
continue;
}
// Copy directories to a writable space on Lambda.
if (in_array($item, $cacheDirectoriesToCopy)) {
$filesystem->mirror("$readOnlyDir/$item", "$writeDir/$item");
continue;
}
// Symlink all other directories
// This is especially important with the Container* directories since it uses require_once statements
if (is_dir("$readOnlyDir/$item")) {
$filesystem->symlink("$readOnlyDir/$item", "$writeDir/$item");
continue;
}
// Copy all other files.
$filesystem->copy("$readOnlyDir/$item", "$writeDir/$item");
}
$this->logToStderr(sprintf(
'Symfony cache directory prepared in %s ms.',
number_format((microtime(true) - $startTime) * 1000, 2)
));
}
/**
* Even though applications should never write into it on Lambda, there are parts of Symfony
* (like "about" CLI command) that expect the log dir exists, so we have to make sure of it.
*
* @see https://github.com/brefphp/symfony-bridge/issues/42
*/
private function ensureLogDir(string $writeLogDir): void
{
if (! $this->isLambda() || is_dir($writeLogDir)) {
return;
}
$filesystem = new Filesystem;
$filesystem->mkdir($writeLogDir);
}
/**
* This method logs to stderr.
*
* It must only be used in a lambda environment since all error output will be logged.
*
* @param string $message The message to log
*/
protected function logToStderr(string $message): void
{
file_put_contents('php://stderr', date('[c] ') . $message . PHP_EOL, FILE_APPEND);
}
}