From 891043e28d1e19680e2f45d949f67f15f550841b Mon Sep 17 00:00:00 2001 From: Sergey Chelombitko Date: Mon, 30 Dec 2024 14:47:46 +0000 Subject: [PATCH] Get rid of ExecutorService --- .../marathon/worker/WorkerContext.kt | 59 ++++++++----------- .../marathon/worker/WorkerRunnable.kt | 32 ---------- 2 files changed, 23 insertions(+), 68 deletions(-) delete mode 100644 marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/worker/WorkerRunnable.kt diff --git a/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/worker/WorkerContext.kt b/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/worker/WorkerContext.kt index 3a9388f7d..d74859107 100644 --- a/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/worker/WorkerContext.kt +++ b/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/worker/WorkerContext.kt @@ -1,64 +1,51 @@ package com.malinskiy.marathon.worker import com.malinskiy.marathon.Marathon +import com.malinskiy.marathon.actor.unboundedChannel import com.malinskiy.marathon.di.marathonStartKoin import com.malinskiy.marathon.execution.ComponentInfo import com.malinskiy.marathon.execution.Configuration -import kotlinx.coroutines.channels.Channel -import java.util.concurrent.CountDownLatch -import java.util.concurrent.Executors -import java.util.concurrent.Future -import java.util.concurrent.TimeUnit -import java.util.concurrent.atomic.AtomicBoolean - -internal class WorkerContext(configuration: Configuration) : WorkerHandler { - private val executor = Executors.newSingleThreadExecutor() - private val componentsChannel: Channel = Channel(capacity = Channel.UNLIMITED) - +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.cancel +import kotlinx.coroutines.runBlocking +import org.gradle.api.tasks.testing.TestExecutionException + +internal class WorkerContext(private val configuration: Configuration) : WorkerHandler { private val application = marathonStartKoin(configuration) private val marathon = application.koin.get() - private val isRunning = AtomicBoolean(false) - private val startedLatch = CountDownLatch(1) - - private lateinit var finishFuture: Future<*> + private val coroutineScope = CoroutineScope(Dispatchers.IO.limitedParallelism(1, "WorkerContext")) + private val componentsChannel = unboundedChannel() + private val runResult = coroutineScope.async { runMarathon() } override fun scheduleTests(componentInfo: ComponentInfo) { - ensureStarted() - componentsChannel.trySend(componentInfo) + componentsChannel.trySend(componentInfo).getOrThrow() } override fun await() { - if (!isRunning.getAndSet(false)) return - - startedLatch.await(WAITING_FOR_START_TIMEOUT_MINUTES, TimeUnit.MINUTES) componentsChannel.close() - try { - // Use future to propagate all exceptions from runnable - finishFuture.get() - } finally { - executor.shutdown() + val success = runBlocking { runResult.await() } + if (!success && !configuration.ignoreFailures) { + throw TestExecutionException("Tests failed! See ${configuration.outputDir}/html/index.html") } } override fun close() { - isRunning.set(false) componentsChannel.close() - executor.shutdownNow() + coroutineScope.cancel() marathon.close() application.close() } - private fun ensureStarted() { - if (isRunning.getAndSet(true)) return + private suspend fun runMarathon(): Boolean { + marathon.start() - val runnable = WorkerRunnable(marathon, componentsChannel) - finishFuture = executor.submit(runnable) - - startedLatch.countDown() - } + for (component in componentsChannel) { + marathon.scheduleTests(component) + } - private companion object { - private const val WAITING_FOR_START_TIMEOUT_MINUTES = 1L + return marathon.stopAndWaitForCompletion() } } diff --git a/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/worker/WorkerRunnable.kt b/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/worker/WorkerRunnable.kt deleted file mode 100644 index 003ecf947..000000000 --- a/marathon-gradle-plugin/src/main/kotlin/com/malinskiy/marathon/worker/WorkerRunnable.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.malinskiy.marathon.worker - -import com.malinskiy.marathon.Marathon -import com.malinskiy.marathon.execution.ComponentInfo -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.runBlocking -import org.gradle.api.GradleException - -internal class WorkerRunnable( - private val marathon: Marathon, - private val componentsChannel: Channel -) : Runnable { - - override fun run() = runBlocking { - marathon.start() - - for (component in componentsChannel) { - marathon.scheduleTests(component) - } - - stopAndWaitForCompletion(marathon) - } - - private suspend fun stopAndWaitForCompletion(marathon: Marathon) { - val success = marathon.stopAndWaitForCompletion() - - val shouldReportFailure = !marathon.configuration.ignoreFailures - if (!success && shouldReportFailure) { - throw GradleException("Tests failed! See ${marathon.configuration.outputDir}/html/index.html") - } - } -}