From 8353fc105e81edd9ebece13020a427d85cf53f9a Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Tue, 7 Mar 2023 18:11:15 +1300 Subject: [PATCH] FIX Attempt to rebuild the schema if a schema file is missing --- src/Schema/Storage/AbstractTypeRegistry.php | 21 ++++++++++++++++++++- tests/Schema/IntegrationTest.php | 6 ++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/Schema/Storage/AbstractTypeRegistry.php b/src/Schema/Storage/AbstractTypeRegistry.php index 6fe312a1..1fb662e1 100644 --- a/src/Schema/Storage/AbstractTypeRegistry.php +++ b/src/Schema/Storage/AbstractTypeRegistry.php @@ -9,6 +9,8 @@ use GraphQL\Type\Definition\ListOfType; use Exception; use SilverStripe\Core\Injector\Injector; +use SilverStripe\GraphQL\Schema\SchemaBuilder; +use SilverStripe\GraphQL\Schema\Exception\EmptySchemaException; abstract class AbstractTypeRegistry { @@ -21,7 +23,24 @@ abstract class AbstractTypeRegistry */ public static function get(string $typename) { - return static::fromCache($typename); + try { + return static::fromCache($typename); + } catch (Exception $e) { + // Try to rebuild the whole schema as fallback. + // This is to solve mysterious edge cases where schema files do not exist when they should. + // These edge cases are more likely on multi-server environments + $dirParts = explode(DIRECTORY_SEPARATOR, static::getSourceDirectory()); + $key = $dirParts[count($dirParts) - 1]; + $builder = SchemaBuilder::singleton(); + $schema = $builder->boot($key); + try { + $builder->build($schema, true); + } catch (EmptySchemaException $e) { + // noop + } + // Attempt to return again now the schema has been rebuilt. + return static::fromCache($typename); + } } abstract protected static function getSourceDirectory(): string; diff --git a/tests/Schema/IntegrationTest.php b/tests/Schema/IntegrationTest.php index f06f3be3..f42d1522 100644 --- a/tests/Schema/IntegrationTest.php +++ b/tests/Schema/IntegrationTest.php @@ -1215,6 +1215,12 @@ private function createSchema(TestSchemaBuilder $factory): Schema $factory->build($schema, true); + // Register as the default SchemaBuilder so that any calls to + // SchemaBuidler::singleton() get this TestSchemaBuilder + // This is important for the call in AbstractTypeRegisty::get() because + // otherwise a duplicate .graphql-generated folder will be created + Injector::inst()->registerService($factory, SchemaBuilder::class); + return $schema; }