-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bulk Load CDK: Task Runner Refactor and Tests (#45912)
- Loading branch information
1 parent
95aaf8a
commit 8ecebea
Showing
3 changed files
with
103 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
airbyte-cdk/bulk/core/load/src/test/kotlin/io/airbyte/cdk/task/TaskRunnerTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright (c) 2024 Airbyte, Inc., all rights reserved. | ||
*/ | ||
|
||
package io.airbyte.cdk.task | ||
|
||
import java.util.concurrent.atomic.AtomicBoolean | ||
import kotlinx.coroutines.channels.Channel | ||
import kotlinx.coroutines.channels.ClosedSendChannelException | ||
import kotlinx.coroutines.launch | ||
import kotlinx.coroutines.test.runTest | ||
import org.junit.jupiter.api.Assertions | ||
import org.junit.jupiter.api.Test | ||
|
||
class TaskRunnerTest { | ||
@Test | ||
fun testTasksCompleteAfterClose() = runTest { | ||
val task1Completed = AtomicBoolean(false) | ||
val task2Completed = AtomicBoolean(false) | ||
val task3Completed = AtomicBoolean(false) | ||
|
||
val innerTaskCompleted = AtomicBoolean(false) | ||
val innerTaskEnqueueFailed = AtomicBoolean(false) | ||
|
||
val task1ReportingChannel = Channel<Unit>() | ||
val task2ReportingChannel = Channel<Unit>() | ||
val task3ReportingChannel = Channel<Unit>() | ||
|
||
val task2BlockingChannel = Channel<Unit>() | ||
|
||
// Make 3 tasks. | ||
// - the first one should complete right away | ||
// - the second one will block until we send a message to it | ||
// - BUT the third one will not be blocked by the second | ||
// - AND the second one should still run after we close the runner | ||
// - BUT the second one tried to enqueue another after close, which throws | ||
val runner = TaskRunner() | ||
val task1 = | ||
object : Task { | ||
override suspend fun execute() { | ||
task1Completed.set(true) | ||
task1ReportingChannel.send(Unit) | ||
} | ||
} | ||
val task2 = | ||
object : Task { | ||
override suspend fun execute() { | ||
task2BlockingChannel.receive() | ||
task2Completed.set(true) | ||
try { | ||
runner.enqueue( | ||
object : Task { | ||
override suspend fun execute() { | ||
innerTaskCompleted.set(true) | ||
} | ||
} | ||
) | ||
} catch (e: ClosedSendChannelException) { | ||
innerTaskEnqueueFailed.set(true) | ||
} | ||
task2ReportingChannel.send(Unit) | ||
} | ||
} | ||
val task3 = | ||
object : Task { | ||
override suspend fun execute() { | ||
task3Completed.set(true) | ||
task3ReportingChannel.send(Unit) | ||
} | ||
} | ||
|
||
runner.enqueue(task1) | ||
runner.enqueue(task2) | ||
runner.enqueue(task3) | ||
|
||
launch { runner.run() } | ||
|
||
task1ReportingChannel.receive() // wait for task1 to complete | ||
Assertions.assertTrue(task1Completed.get()) | ||
Assertions.assertFalse(task2Completed.get()) | ||
|
||
task3ReportingChannel.receive() // wait for task3 to complete | ||
Assertions.assertTrue(task3Completed.get()) | ||
Assertions.assertFalse(task2Completed.get()) | ||
|
||
runner.close() | ||
task2BlockingChannel.send(Unit) | ||
task2ReportingChannel.receive() // wait for task2 to complete | ||
Assertions.assertTrue(task2Completed.get()) | ||
|
||
Assertions.assertTrue(innerTaskEnqueueFailed.get()) | ||
Assertions.assertFalse(innerTaskCompleted.get()) | ||
} | ||
} |