Skip to content

Commit

Permalink
Add RunRetry test (#10)
Browse files Browse the repository at this point in the history
Rename SideEffect test to RunFlush
  • Loading branch information
slinkydeveloper authored Aug 28, 2024
1 parent f812dc0 commit 8172e1c
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 48 deletions.
27 changes: 25 additions & 2 deletions src/main/kotlin/dev/restate/sdktesting/contracts/Failing.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,30 @@ interface Failing {

@Handler suspend fun failingCallWithEventualSuccess(context: ObjectContext): Int

@Handler suspend fun failingSideEffectWithEventualSuccess(context: ObjectContext): Int

@Handler suspend fun terminallyFailingSideEffect(context: ObjectContext, errorMessage: String)

/**
* `minimumAttempts` should be used to check when to succeed. The retry policy should be
* configured to be infinite.
*
* @return the number of executed attempts. In order to implement this count, an atomic counter in
* the service should be used.
*/
@Handler
suspend fun sideEffectSucceedsAfterGivenAttempts(
context: ObjectContext,
minimumAttempts: Int
): Int

/**
* `retryPolicyMaxRetryCount` should be used to configure the retry policy.
*
* @return the number of executed attempts. In order to implement this count, an atomic counter in
* the service should be used.
*/
@Handler
suspend fun sideEffectFailsAfterGivenAttempts(
context: ObjectContext,
retryPolicyMaxRetryCount: Int
): Int
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import dev.restate.sdktesting.contracts.TestUtilsServiceDefinitions
import dev.restate.sdktesting.infra.InjectClient
import dev.restate.sdktesting.infra.RestateDeployerExtension
import dev.restate.sdktesting.infra.ServiceSpec
import java.util.*
import kotlinx.coroutines.test.runTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.DisplayName
Expand All @@ -24,7 +25,7 @@ import org.junit.jupiter.api.parallel.Execution
import org.junit.jupiter.api.parallel.ExecutionMode

@Tag("only-always-suspending")
class SideEffect {
class RunFlush {
companion object {
@RegisterExtension
val deployerExt: RestateDeployerExtension = RestateDeployerExtension {
Expand All @@ -33,10 +34,10 @@ class SideEffect {
}
}

@DisplayName("Side effect should wait on acknowledgements")
@DisplayName("Run should wait on acknowledgements")
@Test
@Execution(ExecutionMode.CONCURRENT)
fun sideEffectFlush(@InjectClient ingressClient: Client) = runTest {
fun flush(@InjectClient ingressClient: Client) = runTest {
assertThat(TestUtilsServiceClient.fromClient(ingressClient).countExecutedSideEffects(3))
.isEqualTo(0)
}
Expand Down
59 changes: 59 additions & 0 deletions src/main/kotlin/dev/restate/sdktesting/tests/RunRetry.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
//
// This file is part of the Restate SDK Test suite tool,
// which is released under the MIT license.
//
// You can find a copy of the license in file LICENSE in the root
// directory of this repository or package, or at
// https://github.com/restatedev/sdk-test-suite/blob/main/LICENSE
package dev.restate.sdktesting.tests

import dev.restate.sdk.client.Client
import dev.restate.sdktesting.contracts.FailingClient
import dev.restate.sdktesting.contracts.FailingDefinitions
import dev.restate.sdktesting.infra.InjectClient
import dev.restate.sdktesting.infra.RestateDeployerExtension
import dev.restate.sdktesting.infra.ServiceSpec
import java.util.*
import kotlinx.coroutines.test.runTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension
import org.junit.jupiter.api.parallel.Execution
import org.junit.jupiter.api.parallel.ExecutionMode

@Tag("always-suspending")
class RunRetry {
companion object {
@RegisterExtension
val deployerExt: RestateDeployerExtension = RestateDeployerExtension {
withServiceSpec(ServiceSpec.defaultBuilder().withServices(FailingDefinitions.SERVICE_NAME))
}
}

@DisplayName("Run is retried until it succeeds")
@Test
@Execution(ExecutionMode.CONCURRENT)
fun withSuccess(@InjectClient ingressClient: Client) = runTest {
val attempts = 3

assertThat(
FailingClient.fromClient(ingressClient, UUID.randomUUID().toString())
.sideEffectSucceedsAfterGivenAttempts(attempts))
.isGreaterThanOrEqualTo(attempts)
}

@DisplayName("Run is retried until it exhausts the retry attempts")
@Test
@Execution(ExecutionMode.CONCURRENT)
fun withExhaustedAttempts(@InjectClient ingressClient: Client) = runTest {
val attempts = 3

assertThat(
FailingClient.fromClient(ingressClient, UUID.randomUUID().toString())
.sideEffectFailsAfterGivenAttempts(attempts))
.isGreaterThanOrEqualTo(attempts)
}
}
43 changes: 0 additions & 43 deletions src/main/kotlin/dev/restate/sdktesting/tests/UserErrors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,39 +40,6 @@ class UserErrors {
}
}

// @DisplayName("Test terminal error of failing side effect with finite retry policy is
// propagated")
// @Test
// @Execution(ExecutionMode.CONCURRENT)
// fun failingSideEffectWithFiniteRetryPolicy(@InjectBlockingStub stub:
// FailingServiceBlockingStub) {
// val errorMessage = "some error message"
//
// assertThatThrownBy {
// stub.failingSideEffectWithFiniteRetryPolicy(
// ErrorMessage.newBuilder()
// .setKey(UUID.randomUUID().toString())
// .setErrorMessage(errorMessage)
// .build())
// }
// .asInstanceOf(type(StatusRuntimeException::class.java))
// .extracting(StatusRuntimeException::getStatus)
// .extracting(Status::getDescription, InstanceOfAssertFactories.STRING)
// .contains("failing side effect action")
// }

// @DisplayName("Test propagate failure from sideEffect and internal invoke")
// @Test
// @Execution(ExecutionMode.CONCURRENT)
// fun sideEffectFailurePropagation(@InjectClient ingressClient: Client) {
// assertThat(
// FailingClient.fromClient(ingressClient, UUID.randomUUID().toString())
// .invokeExternalAndHandleFailure())
// // We match on this regex because there might be additional parts of the string injected
// // by runtime/sdk in the error message strings
// .matches("begin.*external_call.*internal_call")
// }

@DisplayName("Test calling method that fails terminally")
@Test
@Execution(ExecutionMode.CONCURRENT)
Expand Down Expand Up @@ -122,16 +89,6 @@ class UserErrors {
.hasMessageContaining(errorMessage)
}

@DisplayName("Test side effects are retried until they succeed")
@Test
@Execution(ExecutionMode.CONCURRENT)
fun sideEffectWithEventualSuccess(@InjectClient ingressClient: Client) = runTest {
assertThat(
FailingClient.fromClient(ingressClient, UUID.randomUUID().toString())
.failingCallWithEventualSuccess())
.isEqualTo(SUCCESS_ATTEMPT)
}

@DisplayName("Test invocations are retried until they succeed")
@Test
@Execution(ExecutionMode.CONCURRENT)
Expand Down

0 comments on commit 8172e1c

Please sign in to comment.