Skip to content

Commit ae2238c

Browse files
authored
Merge pull request #30 from moufmouf/lock_cache_rebuild
Making locks not dependent on Semaphore extension
2 parents 1f0d93f + cbcfa70 commit ae2238c

8 files changed

+66
-23
lines changed

src/GlobControllerQueryProvider.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ final class GlobControllerQueryProvider implements QueryProviderInterface
6969
* @param int|null $cacheTtl
7070
* @param bool $recursive Whether subnamespaces of $namespace must be analyzed.
7171
*/
72-
public function __construct(string $namespace, FieldsBuilderFactory $fieldsBuilderFactory, RecursiveTypeMapperInterface $recursiveTypeMapper, ContainerInterface $container, CacheInterface $cache, ?int $cacheTtl = null, bool $recursive = true)
72+
public function __construct(string $namespace, FieldsBuilderFactory $fieldsBuilderFactory, RecursiveTypeMapperInterface $recursiveTypeMapper, ContainerInterface $container, LockFactory $lockFactory, CacheInterface $cache, ?int $cacheTtl = null, bool $recursive = true)
7373
{
7474
$this->namespace = $namespace;
7575
$this->container = $container;
@@ -78,9 +78,7 @@ public function __construct(string $namespace, FieldsBuilderFactory $fieldsBuild
7878
$this->fieldsBuilderFactory = $fieldsBuilderFactory;
7979
$this->recursiveTypeMapper = $recursiveTypeMapper;
8080
$this->recursive = $recursive;
81-
$store = new SemaphoreStore();
82-
$this->lockFactory = new LockFactory($store);
83-
81+
$this->lockFactory = $lockFactory;
8482
}
8583

8684
private function getAggregateControllerQueryProvider(): AggregateControllerQueryProvider

src/Mappers/GlobTypeMapper.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ final class GlobTypeMapper implements TypeMapperInterface
129129
/**
130130
* @param string $namespace The namespace that contains the GraphQL types (they must have a `@Type` annotation)
131131
*/
132-
public function __construct(string $namespace, TypeGenerator $typeGenerator, InputTypeGenerator $inputTypeGenerator, InputTypeUtils $inputTypeUtils, ContainerInterface $container, AnnotationReader $annotationReader, NamingStrategyInterface $namingStrategy, CacheInterface $cache, ?int $globTtl = 2, ?int $mapTtl = null, bool $recursive = true)
132+
public function __construct(string $namespace, TypeGenerator $typeGenerator, InputTypeGenerator $inputTypeGenerator, InputTypeUtils $inputTypeUtils, ContainerInterface $container, AnnotationReader $annotationReader, NamingStrategyInterface $namingStrategy, LockFactory $lockFactory, CacheInterface $cache, ?int $globTtl = 2, ?int $mapTtl = null, bool $recursive = true)
133133
{
134134
$this->namespace = $namespace;
135135
$this->typeGenerator = $typeGenerator;
@@ -142,8 +142,7 @@ public function __construct(string $namespace, TypeGenerator $typeGenerator, Inp
142142
$this->inputTypeGenerator = $inputTypeGenerator;
143143
$this->inputTypeUtils = $inputTypeUtils;
144144
$this->recursive = $recursive;
145-
$store = new SemaphoreStore();
146-
$this->lockFactory = new LockFactory($store);
145+
$this->lockFactory = $lockFactory;
147146
}
148147

149148
/**

src/SchemaFactory.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@
88
use Doctrine\Common\Annotations\Reader;
99
use Doctrine\Common\Annotations\AnnotationReader as DoctrineAnnotationReader;
1010
use Doctrine\Common\Cache\ApcuCache;
11+
use function extension_loaded;
1112
use GraphQL\Type\SchemaConfig;
1213
use Psr\Container\ContainerInterface;
1314
use Psr\SimpleCache\CacheInterface;
15+
use Symfony\Component\Lock\Factory as LockFactory;
16+
use Symfony\Component\Lock\Store\FlockStore;
17+
use Symfony\Component\Lock\Store\SemaphoreStore;
18+
use function sys_get_temp_dir;
1419
use TheCodingMachine\GraphQLite\Hydrators\FactoryHydrator;
1520
use TheCodingMachine\GraphQLite\Hydrators\HydratorInterface;
1621
use TheCodingMachine\GraphQLite\Mappers\CompositeTypeMapper;
@@ -72,6 +77,10 @@ class SchemaFactory
7277
* @var SchemaConfig
7378
*/
7479
private $schemaConfig;
80+
/**
81+
* @var LockFactory
82+
*/
83+
private $lockFactory;
7584

7685
public function __construct(CacheInterface $cache, ContainerInterface $container)
7786
{
@@ -181,6 +190,13 @@ public function createSchema(): Schema
181190
$namingStrategy = $this->namingStrategy ?: new NamingStrategy();
182191
$typeRegistry = new TypeRegistry();
183192

193+
if (extension_loaded('sysvsem')) {
194+
$lockStore = new SemaphoreStore();
195+
} else {
196+
$lockStore = new FlockStore(sys_get_temp_dir());
197+
}
198+
$lockFactory = new LockFactory($lockStore);
199+
184200
$fieldsBuilderFactory = new FieldsBuilderFactory($annotationReader, $hydrator, $authenticationService,
185201
$authorizationService, $typeResolver, $cachedDocBlockFactory, $namingStrategy);
186202

@@ -192,7 +208,7 @@ public function createSchema(): Schema
192208

193209
foreach ($this->typeNamespaces as $typeNamespace) {
194210
$typeMappers[] = new GlobTypeMapper($typeNamespace, $typeGenerator, $inputTypeGenerator, $inputTypeUtils,
195-
$this->container, $annotationReader, $namingStrategy, $this->cache);
211+
$this->container, $annotationReader, $namingStrategy, $lockFactory, $this->cache);
196212
}
197213

198214
foreach ($this->typeMappers as $typeMapper) {
@@ -211,7 +227,7 @@ public function createSchema(): Schema
211227
$queryProviders = [];
212228
foreach ($this->controllerNamespaces as $controllerNamespace) {
213229
$queryProviders[] = new GlobControllerQueryProvider($controllerNamespace, $fieldsBuilderFactory, $recursiveTypeMapper,
214-
$this->container, $this->cache);
230+
$this->container, $lockFactory, $this->cache);
215231
}
216232

217233
foreach ($this->queryProviders as $queryProvider) {

tests/AbstractQueryProviderTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
use PHPUnit\Framework\TestCase;
1616
use Psr\Container\ContainerInterface;
1717
use Symfony\Component\Cache\Simple\ArrayCache;
18+
use Symfony\Component\Lock\Factory as LockFactory;
19+
use Symfony\Component\Lock\Store\FlockStore;
20+
use Symfony\Component\Lock\Store\SemaphoreStore;
1821
use TheCodingMachine\GraphQLite\Fixtures\TestObject;
1922
use TheCodingMachine\GraphQLite\Fixtures\TestObject2;
2023
use TheCodingMachine\GraphQLite\Fixtures\TestObjectWithRecursiveList;
@@ -50,6 +53,7 @@ abstract class AbstractQueryProviderTest extends TestCase
5053
private $annotationReader;
5154
private $typeResolver;
5255
private $typeRegistry;
56+
private $lockFactory;
5357

5458
protected function getTestObjectType(): MutableObjectType
5559
{
@@ -318,4 +322,17 @@ protected function getTypeRegistry(): TypeRegistry
318322
}
319323
return $this->typeRegistry;
320324
}
325+
326+
protected function getLockFactory(): LockFactory
327+
{
328+
if ($this->lockFactory === null) {
329+
if (extension_loaded('sysvsem')) {
330+
$lockStore = new SemaphoreStore();
331+
} else {
332+
$lockStore = new FlockStore(sys_get_temp_dir());
333+
}
334+
$this->lockFactory = new LockFactory($lockStore);
335+
}
336+
return $this->lockFactory;
337+
}
321338
}

tests/GlobControllerQueryProviderTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function has($id)
3434
}
3535
};
3636

37-
$globControllerQueryProvider = new GlobControllerQueryProvider('TheCodingMachine\\GraphQLite', $this->getControllerQueryProviderFactory(), $this->getTypeMapper(), $container, new NullCache());
37+
$globControllerQueryProvider = new GlobControllerQueryProvider('TheCodingMachine\\GraphQLite', $this->getControllerQueryProviderFactory(), $this->getTypeMapper(), $container, $this->getLockFactory(), new NullCache());
3838

3939
$queries = $globControllerQueryProvider->getQueries();
4040
$this->assertCount(6, $queries);

tests/Integration/EndToEndTest.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
use Psr\Container\ContainerInterface;
1717
use Psr\Container\NotFoundExceptionInterface;
1818
use Symfony\Component\Cache\Simple\ArrayCache;
19+
use Symfony\Component\Lock\Factory as LockFactory;
20+
use Symfony\Component\Lock\Store\FlockStore;
21+
use Symfony\Component\Lock\Store\SemaphoreStore;
1922
use TheCodingMachine\GraphQLite\AnnotationReader;
2023
use TheCodingMachine\GraphQLite\FieldsBuilderFactory;
2124
use TheCodingMachine\GraphQLite\Fixtures\Integration\Models\Contact;
@@ -62,7 +65,7 @@ public function setUp()
6265
},
6366
QueryProviderInterface::class => function(ContainerInterface $container) {
6467
return new GlobControllerQueryProvider('TheCodingMachine\\GraphQLite\\Fixtures\\Integration\\Controllers', $container->get(FieldsBuilderFactory::class),
65-
$container->get(RecursiveTypeMapperInterface::class), $container->get(BasicAutoWiringContainer::class), new ArrayCache());
68+
$container->get(RecursiveTypeMapperInterface::class), $container->get(BasicAutoWiringContainer::class), $container->get(LockFactory::class), new ArrayCache());
6669
},
6770
FieldsBuilderFactory::class => function(ContainerInterface $container) {
6871
return new FieldsBuilderFactory(
@@ -110,6 +113,7 @@ public function setUp()
110113
$container->get(BasicAutoWiringContainer::class),
111114
$container->get(AnnotationReader::class),
112115
$container->get(NamingStrategyInterface::class),
116+
$container->get(LockFactory::class),
113117
new ArrayCache()
114118
);
115119
},
@@ -121,6 +125,7 @@ public function setUp()
121125
$container->get(BasicAutoWiringContainer::class),
122126
$container->get(AnnotationReader::class),
123127
$container->get(NamingStrategyInterface::class),
128+
$container->get(LockFactory::class),
124129
new ArrayCache()
125130
);
126131
},
@@ -163,6 +168,14 @@ public function setUp()
163168
},
164169
CachedDocBlockFactory::class => function() {
165170
return new CachedDocBlockFactory(new ArrayCache());
171+
},
172+
LockFactory::class => function() {
173+
if (extension_loaded('sysvsem')) {
174+
$lockStore = new SemaphoreStore();
175+
} else {
176+
$lockStore = new FlockStore(sys_get_temp_dir());
177+
}
178+
return new LockFactory($lockStore);
166179
}
167180
]);
168181

tests/Mappers/GlobTypeMapperTest.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function testGlobTypeMapper()
3333

3434
$cache = new ArrayCache();
3535

36-
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $inputTypeGenerator, $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $cache);
36+
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $inputTypeGenerator, $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), $cache);
3737

3838
$this->assertSame([TestObject::class], $mapper->getSupportedClasses());
3939
$this->assertTrue($mapper->canMapClassToType(TestObject::class));
@@ -43,7 +43,7 @@ public function testGlobTypeMapper()
4343
$this->assertFalse($mapper->canMapNameToType('NotExists'));
4444

4545
// Again to test cache
46-
$anotherMapperSameCache = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $cache);
46+
$anotherMapperSameCache = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), $cache);
4747
$this->assertTrue($anotherMapperSameCache->canMapClassToType(TestObject::class));
4848
$this->assertTrue($anotherMapperSameCache->canMapNameToType('Foo'));
4949

@@ -61,7 +61,7 @@ public function testGlobTypeMapperDuplicateTypesException()
6161

6262
$typeGenerator = $this->getTypeGenerator();
6363

64-
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\DuplicateTypes', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), new NullCache());
64+
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\DuplicateTypes', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), new NullCache());
6565

6666
$this->expectException(DuplicateMappingException::class);
6767
$mapper->canMapClassToType(TestType::class);
@@ -77,7 +77,7 @@ public function testGlobTypeMapperDuplicateInputTypesException()
7777

7878
$typeGenerator = $this->getTypeGenerator();
7979

80-
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\DuplicateInputTypes', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), new NullCache());
80+
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\DuplicateInputTypes', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), new NullCache());
8181

8282
$this->expectException(DuplicateMappingException::class);
8383
$this->expectExceptionMessage('The class \'TheCodingMachine\GraphQLite\Fixtures\TestObject\' should be mapped to only one GraphQL Input type. Two methods are pointing via the @Factory annotation to this class: \'TheCodingMachine\GraphQLite\Fixtures\DuplicateInputTypes\TestFactory::myFactory\' and \'TheCodingMachine\GraphQLite\Fixtures\DuplicateInputTypes\TestFactory2::myFactory\'');
@@ -94,7 +94,7 @@ public function testGlobTypeMapperClassNotFoundException()
9494

9595
$typeGenerator = $this->getTypeGenerator();
9696

97-
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\BadClassType', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), new NullCache());
97+
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\BadClassType', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), new NullCache());
9898

9999
$this->expectException(ClassNotFoundException::class);
100100
$this->expectExceptionMessage("Could not autoload class 'Foobar' defined in @Type annotation of class 'TheCodingMachine\\GraphQLite\\Fixtures\\BadClassType\\TestType'");
@@ -111,7 +111,7 @@ public function testGlobTypeMapperNameNotFoundException()
111111

112112
$typeGenerator = $this->getTypeGenerator();
113113

114-
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), new NullCache());
114+
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), new NullCache());
115115

116116
$this->expectException(CannotMapTypeException::class);
117117
$mapper->mapNameToType('NotExists', $this->getTypeMapper());
@@ -132,7 +132,7 @@ public function testGlobTypeMapperInputType()
132132

133133
$cache = new ArrayCache();
134134

135-
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $cache);
135+
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), $cache);
136136

137137
$this->assertTrue($mapper->canMapClassToInputType(TestObject::class));
138138

@@ -141,7 +141,7 @@ public function testGlobTypeMapperInputType()
141141
$this->assertSame('TestObjectInput', $inputType->name);
142142

143143
// Again to test cache
144-
$anotherMapperSameCache = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $cache);
144+
$anotherMapperSameCache = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), $cache);
145145

146146
$this->assertTrue($anotherMapperSameCache->canMapClassToInputType(TestObject::class));
147147
$this->assertSame('TestObjectInput', $anotherMapperSameCache->mapClassToInputType(TestObject::class, $this->getTypeMapper())->name);
@@ -167,7 +167,7 @@ public function testGlobTypeMapperExtend()
167167

168168
$cache = new ArrayCache();
169169

170-
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $inputTypeGenerator, $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $cache);
170+
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $inputTypeGenerator, $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), $cache);
171171

172172
$type = $mapper->mapClassToType(TestObject::class, null, $this->getTypeMapper());
173173

@@ -178,7 +178,7 @@ public function testGlobTypeMapperExtend()
178178
$this->assertFalse($mapper->canExtendTypeForName('NotExists', $type, $this->getTypeMapper()));
179179

180180
// Again to test cache
181-
$anotherMapperSameCache = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $cache);
181+
$anotherMapperSameCache = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Types', $typeGenerator, $this->getInputTypeGenerator(), $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), $cache);
182182
$this->assertTrue($anotherMapperSameCache->canExtendTypeForClass(TestObject::class, $type, $this->getTypeMapper()));
183183
$this->assertTrue($anotherMapperSameCache->canExtendTypeForName('TestObject', $type, $this->getTypeMapper()));
184184

@@ -195,7 +195,7 @@ public function testEmptyGlobTypeMapper()
195195

196196
$cache = new ArrayCache();
197197

198-
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Integration\Controllers', $typeGenerator, $inputTypeGenerator, $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $cache);
198+
$mapper = new GlobTypeMapper('TheCodingMachine\GraphQLite\Fixtures\Integration\Controllers', $typeGenerator, $inputTypeGenerator, $this->getInputTypeUtils(), $container, new \TheCodingMachine\GraphQLite\AnnotationReader(new AnnotationReader()), new NamingStrategy(), $this->getLockFactory(), $cache);
199199

200200
$this->assertSame([], $mapper->getSupportedClasses());
201201
}

0 commit comments

Comments
 (0)