Skip to content

Commit 6573a53

Browse files
committed
Fix invoke actor after aborted flow.
Signed-off-by: Artur Souza <[email protected]>
1 parent 1d5e2b1 commit 6573a53

File tree

5 files changed

+36
-24
lines changed

5 files changed

+36
-24
lines changed

sdk-actors/src/main/java/io/dapr/actors/runtime/AbstractActor.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.io.IOException;
2121
import java.time.Duration;
2222
import java.util.UUID;
23+
import java.util.concurrent.atomic.AtomicBoolean;
2324

2425
/**
2526
* Represents the base class for actors.
@@ -28,8 +29,6 @@
2829
*/
2930
public abstract class AbstractActor {
3031

31-
private static final ActorObjectSerializer INTERNAL_SERIALIZER = new ActorObjectSerializer();
32-
3332
/**
3433
* Type of tracing messages.
3534
*/
@@ -58,7 +57,7 @@ public abstract class AbstractActor {
5857
/**
5958
* Internal control to assert method invocation on start and finish in this SDK.
6059
*/
61-
private boolean started;
60+
private final AtomicBoolean started;
6261

6362
/**
6463
* Instantiates a new Actor.
@@ -74,7 +73,7 @@ protected AbstractActor(ActorRuntimeContext runtimeContext, ActorId id) {
7473
runtimeContext.getActorTypeInformation().getName(),
7574
id);
7675
this.actorTrace = runtimeContext.getActorTrace();
77-
this.started = false;
76+
this.started = new AtomicBoolean(false);
7877
}
7978

8079
/**
@@ -250,14 +249,16 @@ protected Mono<Void> saveState() {
250249

251250
/**
252251
* Resets the cached state of this Actor.
252+
*
253+
* @param force Forces the rollback, even if not in a call.
253254
*/
254-
void rollback() {
255-
if (!this.started) {
255+
void rollback(boolean force) {
256+
if (!force && !this.started.get()) {
256257
throw new IllegalStateException("Cannot reset state before starting call.");
257258
}
258259

259260
this.resetState();
260-
this.started = false;
261+
this.started.set(false);
261262
}
262263

263264
/**
@@ -302,11 +303,12 @@ Mono<Void> onDeactivateInternal() {
302303
*/
303304
Mono<Void> onPreActorMethodInternal(ActorMethodContext actorMethodContext) {
304305
return Mono.fromRunnable(() -> {
305-
if (this.started) {
306-
throw new IllegalStateException("Cannot invoke a method before completing previous call.");
306+
if (this.started.get()) {
307+
throw new IllegalStateException(
308+
"Cannot invoke a method before completing previous call. " + getId().toString());
307309
}
308310

309-
this.started = true;
311+
this.started.set(true);
310312
}).then(this.onPreActorMethod(actorMethodContext));
311313
}
312314

@@ -318,14 +320,13 @@ Mono<Void> onPreActorMethodInternal(ActorMethodContext actorMethodContext) {
318320
*/
319321
Mono<Void> onPostActorMethodInternal(ActorMethodContext actorMethodContext) {
320322
return Mono.fromRunnable(() -> {
321-
if (!this.started) {
323+
if (!this.started.get()) {
322324
throw new IllegalStateException("Cannot complete a method before starting a call.");
323325
}
324-
}).then(this.onPostActorMethod(actorMethodContext))
325-
.then(this.saveState())
326-
.then(Mono.fromRunnable(() -> {
327-
this.started = false;
328-
}));
326+
})
327+
.then(this.onPostActorMethod(actorMethodContext))
328+
.then(this.saveState())
329+
.then(Mono.fromRunnable(() -> this.started.set(false)));
329330
}
330331

331332
/**

sdk-actors/src/main/java/io/dapr/actors/runtime/ActorManager.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -306,15 +306,16 @@ private <T> Mono<T> invoke(ActorId actorId, ActorMethodContext context, Function
306306
this.runtimeContext.getActorTypeInformation().getName()));
307307
}
308308

309-
return actor.onPreActorMethodInternal(context)
309+
return Mono.fromRunnable(() -> actor.rollback(true))
310+
.onErrorMap(throwable -> {
311+
actor.rollback(false);
312+
return throwable;
313+
})
314+
.then(actor.onPreActorMethodInternal(context))
310315
.then((Mono<Object>) func.apply(actor))
311316
.switchIfEmpty(
312317
actor.onPostActorMethodInternal(context))
313318
.flatMap(r -> actor.onPostActorMethodInternal(context).thenReturn(r))
314-
.onErrorMap(throwable -> {
315-
actor.rollback();
316-
return throwable;
317-
})
318319
.map(o -> (T) o);
319320
} catch (Exception e) {
320321
return Mono.error(e);

sdk-tests/components/mongo-statestore.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ spec:
1111
- name: databaseName
1212
value: local
1313
- name: collectionName
14-
value: testCollection
14+
value: testCollection
15+
scopes:
16+
- grpcstateclientit
17+
- httpstateclientit

sdk-tests/src/test/java/io/dapr/it/DaprRun.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public class DaprRun implements Stoppable {
3030

3131
private static final String DAPR_RUN = "dapr run --app-id %s --app-protocol %s " +
3232
"--config ./configurations/configuration.yaml " +
33-
"--components-path ./components";
33+
"--resources-path ./components";
3434

3535
// the arg in -Dexec.args is the app's port
3636
private static final String DAPR_COMMAND =

sdk-tests/src/test/java/io/dapr/it/actors/ActorSdkResiliencytIT.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
import io.dapr.actors.ActorId;
1717
import io.dapr.actors.client.ActorProxyBuilder;
18+
import io.dapr.client.DaprClient;
19+
import io.dapr.client.DaprClientBuilder;
1820
import io.dapr.client.resiliency.ResiliencyOptions;
1921
import io.dapr.it.BaseIT;
2022
import io.dapr.it.DaprRun;
@@ -23,6 +25,7 @@
2325
import io.dapr.it.actors.services.springboot.DemoActorService;
2426
import org.junit.AfterClass;
2527
import org.junit.BeforeClass;
28+
import org.junit.Ignore;
2629
import org.junit.Test;
2730

2831
import java.time.Duration;
@@ -41,7 +44,7 @@ public class ActorSdkResiliencytIT extends BaseIT {
4144

4245
private static final int NUM_ITERATIONS = 20;
4346

44-
private static final Duration TIMEOUT = Duration.ofMillis(100);
47+
private static final Duration TIMEOUT = Duration.ofMillis(1000);
4548

4649
private static final Duration LATENCY = TIMEOUT.dividedBy(2);
4750

@@ -51,6 +54,8 @@ public class ActorSdkResiliencytIT extends BaseIT {
5154

5255
private static DaprRun daprRun;
5356

57+
private static DaprClient daprClient;
58+
5459
private static DemoActor demoActor;
5560

5661
private static ToxiProxyRun toxiProxyRun;
@@ -75,6 +80,7 @@ public static void init() throws Exception {
7580
// HTTP client is deprecated, so SDK resiliency is for gRPC client only.
7681
daprRun.switchToGRPC();
7782
demoActor = buildDemoActorProxy(null);
83+
daprClient = new DaprClientBuilder().build();
7884

7985
toxiProxyRun = new ToxiProxyRun(daprRun, LATENCY, JITTER);
8086
toxiProxyRun.start();
@@ -100,6 +106,7 @@ public static void tearDown() throws Exception {
100106
}
101107

102108
@Test
109+
@Ignore("Flaky when running on GitHub actions")
103110
public void retryAndTimeout() {
104111
AtomicInteger toxiClientErrorCount = new AtomicInteger();
105112
AtomicInteger retryOneClientErrorCount = new AtomicInteger();

0 commit comments

Comments
 (0)