Skip to content

Commit 65e3c57

Browse files
author
Shane Myrick
committed
Implement SchemaGenerator as closeable
1 parent 2094d3b commit 65e3c57

File tree

6 files changed

+33
-15
lines changed

6 files changed

+33
-15
lines changed

graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/federation/toFederatedSchema.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,7 @@ fun toFederatedSchema(
3838
subscriptions: List<TopLevelObject> = emptyList()
3939
): GraphQLSchema {
4040
val generator = FederatedSchemaGenerator(config)
41-
return generator.generateSchema(queries, mutations, subscriptions)
41+
return generator.use {
42+
it.generateSchema(queries, mutations, subscriptions)
43+
}
4244
}

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/SchemaGenerator.kt

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import graphql.schema.GraphQLCodeRegistry
2828
import graphql.schema.GraphQLDirective
2929
import graphql.schema.GraphQLSchema
3030
import graphql.schema.GraphQLType
31+
import java.io.Closeable
3132
import java.util.concurrent.ConcurrentHashMap
3233
import kotlin.reflect.KClass
3334
import kotlin.reflect.KType
@@ -39,7 +40,7 @@ import kotlin.reflect.full.createType
3940
* This class maintains the state of the schema while generation is taking place. It is passed into the internal functions
4041
* so they can use the cache and add additional types and directives into the schema as they parse the Kotlin code.
4142
*/
42-
open class SchemaGenerator(internal val config: SchemaGeneratorConfig) {
43+
open class SchemaGenerator(internal val config: SchemaGeneratorConfig) : Closeable {
4344

4445
internal val additionalTypes = mutableSetOf<KType>()
4546
internal val classScanner = ClassScanner(config.supportedPackages)
@@ -56,20 +57,17 @@ open class SchemaGenerator(internal val config: SchemaGeneratorConfig) {
5657
subscriptions: List<TopLevelObject> = emptyList(),
5758
additionalTypes: Set<KType> = emptySet()
5859
): GraphQLSchema {
59-
6060
this.additionalTypes.addAll(additionalTypes)
61+
6162
val builder = GraphQLSchema.newSchema()
6263
builder.query(generateQueries(this, queries))
6364
builder.mutation(generateMutations(this, mutations))
6465
builder.subscription(generateSubscriptions(this, subscriptions))
6566
builder.additionalTypes(generateAdditionalTypes())
6667
builder.additionalDirectives(directives.values.toSet())
6768
builder.codeRegistry(codeRegistry.build())
68-
val schema = config.hooks.willBuildSchema(builder).build()
6969

70-
cleanUpResources()
71-
72-
return schema
70+
return config.hooks.willBuildSchema(builder).build()
7371
}
7472

7573
/**
@@ -101,9 +99,19 @@ open class SchemaGenerator(internal val config: SchemaGeneratorConfig) {
10199
return graphqlTypes.toSet()
102100
}
103101

104-
private fun cleanUpResources() {
105-
additionalTypes.clear()
102+
/**
103+
* Clear the generator type cache, reflection scan, additional types,
104+
* and the saved directives. You may want call this after you have
105+
* called [generateSchema] and performed some other actions which is why
106+
* we have a separate method to explicitly clear.
107+
*
108+
* If you use the built in [com.expediagroup.graphql.toSchema], we will handle
109+
* clean up of resources for you.
110+
*/
111+
override fun close() {
112+
classScanner.close()
106113
cache.clear()
114+
additionalTypes.clear()
107115
directives.clear()
108116
}
109117
}

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/state/ClassScanner.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ package com.expediagroup.graphql.generator.state
1919
import io.github.classgraph.ClassGraph
2020
import io.github.classgraph.ClassInfo
2121
import io.github.classgraph.ClassInfoList
22+
import java.io.Closeable
2223
import kotlin.reflect.KClass
2324
import kotlin.reflect.jvm.jvmName
2425

25-
internal class ClassScanner(supportedPackages: List<String>) {
26+
internal class ClassScanner(supportedPackages: List<String>) : Closeable {
2627

2728
@Suppress("Detekt.SpreadOperator")
2829
private val scanResult = ClassGraph()
@@ -39,6 +40,8 @@ internal class ClassScanner(supportedPackages: List<String>) {
3940
.filterNot { it.isAbstract }
4041
}
4142

43+
override fun close() = scanResult.close()
44+
4245
fun getClassesWithAnnotation(annotation: KClass<*>) = scanResult.getClassesWithAnnotation(annotation.jvmName).map { it.loadClass().kotlin }
4346

4447
@Suppress("Detekt.SwallowedException")

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/toSchema.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,7 @@ fun toSchema(
3838
subscriptions: List<TopLevelObject> = emptyList()
3939
): GraphQLSchema {
4040
val generator = SchemaGenerator(config)
41-
return generator.generateSchema(queries, mutations, subscriptions)
41+
return generator.use {
42+
it.generateSchema(queries, mutations, subscriptions)
43+
}
4244
}

graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/PolymorphicTests.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import com.expediagroup.graphql.TopLevelObject
2020
import com.expediagroup.graphql.annotations.GraphQLIgnore
2121
import com.expediagroup.graphql.annotations.GraphQLName
2222
import com.expediagroup.graphql.exceptions.InvalidInputFieldTypeException
23+
import com.expediagroup.graphql.createNewTestGenerator
2324
import com.expediagroup.graphql.testGenerator
2425
import graphql.TypeResolutionEnvironment
2526
import graphql.schema.GraphQLInterfaceType
@@ -96,7 +97,7 @@ class PolymorphicTests {
9697

9798
@Test
9899
fun `Interfaces can declare properties of their own type`() {
99-
val schema = testGenerator.generateSchema(queries = listOf(TopLevelObject(QueryWithRecursiveType())))
100+
val schema = createNewTestGenerator().generateSchema(queries = listOf(TopLevelObject(QueryWithRecursiveType())))
100101

101102
val personType = schema.getType("Person")
102103
assertNotNull(personType)
@@ -117,7 +118,7 @@ class PolymorphicTests {
117118

118119
@Test
119120
fun `Interface types can be correctly resolved`() {
120-
val schema = testGenerator.generateSchema(queries = listOf(TopLevelObject(QueryWithRenamedAbstracts())))
121+
val schema = createNewTestGenerator().generateSchema(queries = listOf(TopLevelObject(QueryWithRenamedAbstracts())))
121122

122123
val cakeInterface = schema.getType("Cake") as? GraphQLInterfaceType
123124
assertNotNull(cakeInterface)
@@ -162,7 +163,7 @@ class PolymorphicTests {
162163

163164
@Test
164165
fun `Ignored interface properties should not appear in the subtype`() {
165-
val schema = testGenerator.generateSchema(queries = listOf(TopLevelObject(QueryWithIgnoredInfo())))
166+
val schema = createNewTestGenerator().generateSchema(queries = listOf(TopLevelObject(QueryWithIgnoredInfo())))
166167
val service = schema.getType("Service") as? GraphQLInterfaceType
167168
assertNotNull(service)
168169
val interfaceIgnoredField = service.getFieldDefinition("shouldNotBeInTheSchema")

graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/testSchemaConfig.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ import com.expediagroup.graphql.hooks.SchemaGeneratorHooks
2323
import io.mockk.every
2424
import io.mockk.spyk
2525

26-
val defaultSupportedPackages = listOf("com.expediagroup")
26+
val defaultSupportedPackages = listOf("com.expediagroup.graphql")
2727
val testSchemaConfig = SchemaGeneratorConfig(defaultSupportedPackages)
2828
val testGenerator = SchemaGenerator(testSchemaConfig)
2929

30+
fun createNewTestGenerator() = SchemaGenerator(testSchemaConfig)
31+
3032
fun getTestSchemaConfigWithHooks(hooks: SchemaGeneratorHooks) = SchemaGeneratorConfig(defaultSupportedPackages, hooks = hooks)
3133

3234
fun getTestSchemaConfigWithMockedDirectives() = getTestSchemaConfigWithHooks(hooks = object : SchemaGeneratorHooks {

0 commit comments

Comments
 (0)