Skip to content

Commit

Permalink
introduce Service.useProcessIsolation (#6267)
Browse files Browse the repository at this point in the history
  • Loading branch information
martinbonnin authored Nov 21, 2024
1 parent 7734061 commit 634b606
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,17 @@ interface Service {
*/
val decapitalizeFields: Property<Boolean>

/**
* Whether to use process isolation. By default, the Apollo tasks use classloader isolation, which may leak and increase memory usage over time.
* By using process isolation, the tasks are run in a separate process and the memory is reclaimed when the process stops. This comes at a price
* of more forking time.
*
* See https://github.com/apollographql/apollo-kotlin/issues/6266
* See https://github.com/gradle/gradle/issues/18313
*/
@ApolloExperimental
val useProcessIsolation: Property<Boolean>

@Deprecated("Not supported any more, use dependsOn() instead", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(ApolloDeprecatedSince.Version.v4_0_0)
fun usedCoordinates(file: File)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ abstract class ApolloGenerateCodegenSchemaTask : ApolloTaskWithClasspath() {
@get:Optional
abstract val codegenSchemaFile: RegularFileProperty

@Inject
abstract fun getWorkerExecutor(): WorkerExecutor

@TaskAction
fun taskAction() {
if (upstreamSchemaFiles.files.isNotEmpty()) {
Expand All @@ -57,9 +54,7 @@ abstract class ApolloGenerateCodegenSchemaTask : ApolloTaskWithClasspath() {
return
}

val workQueue = getWorkerExecutor().classLoaderIsolation { workerSpec ->
workerSpec.classpath.from(classpath)
}
val workQueue = getWorkQueue()

workQueue.submit(GenerateCodegenSchema::class.java) {
it.codegenSchemaFile = codegenSchemaFile
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,10 @@ abstract class ApolloGenerateIrOperationsTask: ApolloTaskWithClasspath() {
@get:OutputFile
abstract val irOperationsFile: RegularFileProperty

@Inject
abstract fun getWorkerExecutor(): WorkerExecutor

@TaskAction
fun taskAction() {

val workQueue = getWorkerExecutor().classLoaderIsolation { workerSpec ->
workerSpec.classpath.from(classpath)
}
val workQueue = getWorkQueue()

workQueue.submit(GenerateIrOperations::class.java) {
it.codegenSchemaFiles = codegenSchemaFiles.isolate()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ abstract class ApolloGenerateSourcesBaseTask : ApolloTaskWithClasspath() {

@get:OutputDirectory
abstract val outputDir: DirectoryProperty

@Inject
abstract fun getWorkerExecutor(): WorkerExecutor
}

fun ApolloGenerateSourcesBaseTask.layout(): LayoutFactory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ abstract class ApolloGenerateSourcesFromIrTask : ApolloGenerateSourcesBaseTask()
operationOutputGenerator = operationOutputGenerator
).writeTo(outputDir.get().asFile, true, metadataOutputFile.orNull?.asFile)
} else {
val workQueue = getWorkerExecutor().classLoaderIsolation { workerSpec ->
workerSpec.classpath.from(classpath)
}
val workQueue = getWorkQueue()

workQueue.submit(GenerateSourcesFromIr::class.java) {
it.codegenSchemas.from(codegenSchemas)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ abstract class ApolloGenerateSourcesTask : ApolloGenerateSourcesBaseTask() {
operationManifestFile = operationManifestFile.orNull?.asFile
).writeTo(outputDir.get().asFile, true, null)
} else {
val workQueue = getWorkerExecutor().classLoaderIsolation { workerSpec ->
workerSpec.classpath.from(classpath)
}
val workQueue = getWorkQueue()

workQueue.submit(GenerateSources::class.java) {
it.hasPlugin = hasPlugin.get()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Classpath
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
import org.gradle.workers.WorkQueue
import org.gradle.workers.WorkerExecutor
import javax.inject.Inject

abstract class ApolloTaskWithClasspath: DefaultTask() {
@get:Classpath
Expand All @@ -16,16 +21,37 @@ abstract class ApolloTaskWithClasspath: DefaultTask() {
@get:Input
abstract val hasPlugin: Property<Boolean>

@get:Input
@get:Optional
abstract val useProcessIsolation: Property<Boolean>

@get:Input
abstract val arguments: MapProperty<String, Any?>

@get:Input
abstract val logLevel: Property<LogLevel>

@Inject
abstract fun getWorkerExecutor(): WorkerExecutor

@Internal
fun getWorkQueue(): WorkQueue {
return if (useProcessIsolation.orElse(false).get()) {
getWorkerExecutor().processIsolation { workerSpec ->
workerSpec.classpath.from(classpath)
}
} else {
getWorkerExecutor().classLoaderIsolation { workerSpec ->
workerSpec.classpath.from(classpath)
}
}
}

class Options(
val classpath: FileCollection,
val hasPlugin: Boolean,
val arguments: Map<String, Any?>,
val logLevel: LogLevel
val logLevel: LogLevel,
val useProcessIsolation: Property<Boolean>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ abstract class DefaultApolloExtension(
service.pluginDependency != null,
(service.compilerPlugin as DefaultCompilerPlugin?)?.arguments.orEmpty(),
LogLevel.entries.first { project.logger.isEnabled(it) },
service.useProcessIsolation
)

if (service.languageVersion.orNull == "1.5") {
Expand Down Expand Up @@ -859,6 +860,7 @@ abstract class DefaultApolloExtension(
task.classpath.from(classpathOptions.classpath)
task.arguments.set(classpathOptions.arguments)
task.logLevel.set(classpathOptions.logLevel)
task.useProcessIsolation.set(classpathOptions.useProcessIsolation)
}

private fun configureBaseCodegenTask(
Expand Down

0 comments on commit 634b606

Please sign in to comment.