Skip to content

Commit 1f0d93f

Browse files
authored
Merge pull request #29 from moufmouf/lock_cache_rebuild
Adding a lock mechanism on cache rebuild
2 parents 02a7b65 + 6b43288 commit 1f0d93f

File tree

3 files changed

+67
-15
lines changed

3 files changed

+67
-15
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"phpdocumentor/reflection-docblock": "^4.3",
2121
"phpdocumentor/type-resolver": "^0.4",
2222
"psr/http-message": "^1",
23-
"ecodev/graphql-upload": "^4.0"
23+
"ecodev/graphql-upload": "^4.0",
24+
"symfony/lock": "^3 || ^4"
2425
},
2526
"require-dev": {
2627
"phpunit/phpunit": "^6.1",

src/GlobControllerQueryProvider.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
use Mouf\Composer\ClassNameMapper;
77
use Psr\Container\ContainerInterface;
88
use Psr\SimpleCache\CacheInterface;
9+
use Symfony\Component\Lock\Store\SemaphoreStore;
910
use TheCodingMachine\ClassExplorer\Glob\GlobClassExplorer;
1011
use TheCodingMachine\GraphQLite\Mappers\RecursiveTypeMapperInterface;
12+
use Symfony\Component\Lock\Factory as LockFactory;
1113

1214
/**
1315
* Scans all the classes in a given namespace of the main project (not the vendor directory).
@@ -53,6 +55,10 @@ final class GlobControllerQueryProvider implements QueryProviderInterface
5355
* @var bool
5456
*/
5557
private $recursive;
58+
/**
59+
* @var LockFactory
60+
*/
61+
private $lockFactory;
5662

5763
/**
5864
* @param string $namespace The namespace that contains the GraphQL types (they must have a `@Type` annotation)
@@ -72,6 +78,9 @@ public function __construct(string $namespace, FieldsBuilderFactory $fieldsBuild
7278
$this->fieldsBuilderFactory = $fieldsBuilderFactory;
7379
$this->recursiveTypeMapper = $recursiveTypeMapper;
7480
$this->recursive = $recursive;
81+
$store = new SemaphoreStore();
82+
$this->lockFactory = new LockFactory($store);
83+
7584
}
7685

7786
private function getAggregateControllerQueryProvider(): AggregateControllerQueryProvider
@@ -93,13 +102,24 @@ private function getInstancesList(): array
93102
$key = 'globQueryProvider_'.str_replace('\\', '_', $this->namespace);
94103
$this->instancesList = $this->cache->get($key);
95104
if ($this->instancesList === null) {
96-
$this->instancesList = $this->buildInstancesList();
105+
$this->instancesList = $this->lockAndBuildInstanceList();
97106
$this->cache->set($key, $this->instancesList, $this->cacheTtl);
98107
}
99108
}
100109
return $this->instancesList;
101110
}
102111

112+
private function lockAndBuildInstanceList(): array
113+
{
114+
$lock = $this->lockFactory->createLock('buildInstanceList_'.$this->namespace, 5);
115+
$lock->acquire(true);
116+
try {
117+
return $this->buildInstancesList();
118+
} finally {
119+
$lock->release();
120+
}
121+
}
122+
103123
/**
104124
* @return string[]
105125
*/

src/Mappers/GlobTypeMapper.php

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use Psr\SimpleCache\CacheInterface;
1313
use ReflectionClass;
1414
use ReflectionMethod;
15+
use Symfony\Component\Lock\Factory as LockFactory;
16+
use Symfony\Component\Lock\Store\SemaphoreStore;
1517
use TheCodingMachine\ClassExplorer\Glob\GlobClassExplorer;
1618
use TheCodingMachine\GraphQLite\AnnotationReader;
1719
use TheCodingMachine\GraphQLite\Annotations\ExtendType;
@@ -119,6 +121,10 @@ final class GlobTypeMapper implements TypeMapperInterface
119121
* @var bool
120122
*/
121123
private $recursive;
124+
/**
125+
* @var LockFactory
126+
*/
127+
private $lockFactory;
122128

123129
/**
124130
* @param string $namespace The namespace that contains the GraphQL types (they must have a `@Type` annotation)
@@ -136,6 +142,8 @@ public function __construct(string $namespace, TypeGenerator $typeGenerator, Inp
136142
$this->inputTypeGenerator = $inputTypeGenerator;
137143
$this->inputTypeUtils = $inputTypeUtils;
138144
$this->recursive = $recursive;
145+
$store = new SemaphoreStore();
146+
$this->lockFactory = new LockFactory($store);
139147
}
140148

141149
/**
@@ -160,7 +168,7 @@ private function getMaps(): array
160168
$this->mapClassToFactory === null ||
161169
$this->mapInputNameToFactory
162170
) {
163-
$this->buildMap();
171+
$this->lockAndBuildMap();
164172
// This is a very short lived cache. Useful to avoid overloading a server in case of heavy load.
165173
// Defaults to 2 seconds.
166174
$this->cache->set($keyClassCache, $this->mapClassToTypeArray, $this->globTtl);
@@ -258,6 +266,17 @@ private function getClassList(): array
258266
return $this->classes;
259267
}
260268

269+
private function lockAndBuildMap(): void
270+
{
271+
$lock = $this->lockFactory->createLock('buildmap_'.$this->namespace, 5);
272+
$lock->acquire(true);
273+
try {
274+
$this->buildMap();
275+
} finally {
276+
$lock->release();
277+
}
278+
}
279+
261280
private function buildMap(): void
262281
{
263282
$this->mapClassToTypeArray = [];
@@ -303,27 +322,39 @@ private function buildMap(): void
303322

304323
private function buildMapClassToExtendTypeArray(): void
305324
{
306-
$this->mapClassToExtendTypeArray = [];
307-
$classes = $this->getClassList();
308-
foreach ($classes as $className => $refClass) {
309-
$extendType = $this->annotationReader->getExtendTypeAnnotation($refClass);
325+
$lock = $this->lockFactory->createLock('buildmapclassextend_'.$this->namespace, 5);
326+
$lock->acquire(true);
327+
try {
328+
$this->mapClassToExtendTypeArray = [];
329+
$classes = $this->getClassList();
330+
foreach ($classes as $className => $refClass) {
331+
$extendType = $this->annotationReader->getExtendTypeAnnotation($refClass);
310332

311-
if ($extendType !== null) {
312-
$this->storeExtendTypeMapperByClassInCache($className, $extendType, $refClass->getFileName());
333+
if ($extendType !== null) {
334+
$this->storeExtendTypeMapperByClassInCache($className, $extendType, $refClass->getFileName());
335+
}
313336
}
337+
} finally {
338+
$lock->release();
314339
}
315340
}
316341

317342
private function buildMapNameToExtendTypeArray(RecursiveTypeMapperInterface $recursiveTypeMapper): void
318343
{
319-
$this->mapNameToExtendType = [];
320-
$classes = $this->getClassList();
321-
foreach ($classes as $className => $refClass) {
322-
$extendType = $this->annotationReader->getExtendTypeAnnotation($refClass);
344+
$lock = $this->lockFactory->createLock('buildmapnameextend_'.$this->namespace, 5);
345+
$lock->acquire(true);
346+
try {
347+
$this->mapNameToExtendType = [];
348+
$classes = $this->getClassList();
349+
foreach ($classes as $className => $refClass) {
350+
$extendType = $this->annotationReader->getExtendTypeAnnotation($refClass);
323351

324-
if ($extendType !== null) {
325-
$this->storeExtendTypeMapperByNameInCache($className, $extendType, $refClass->getFileName(), $recursiveTypeMapper);
352+
if ($extendType !== null) {
353+
$this->storeExtendTypeMapperByNameInCache($className, $extendType, $refClass->getFileName(), $recursiveTypeMapper);
354+
}
326355
}
356+
} finally {
357+
$lock->release();
327358
}
328359
}
329360

0 commit comments

Comments
 (0)