Skip to content

Commit 05cae63

Browse files
committed
Code review and unit test coverage check
1 parent 573104d commit 05cae63

3 files changed

Lines changed: 89 additions & 17 deletions

File tree

temporal-sdk/src/main/java/io/temporal/internal/client/external/GenericWorkflowClient.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@ PollNexusOperationExecutionResponse pollNexusOperationExecution(
7373
CompletableFuture<PollNexusOperationExecutionResponse> pollNexusOperationExecutionAsync(
7474
@Nonnull PollNexusOperationExecutionRequest request, @Nonnull Deadline deadline);
7575

76-
ListNexusOperationExecutionsResponse listNexusOperationExecutions(
77-
@Nonnull ListNexusOperationExecutionsRequest request);
78-
7976
CompletableFuture<ListNexusOperationExecutionsResponse> listNexusOperationExecutionsAsync(
8077
@Nonnull ListNexusOperationExecutionsRequest request);
8178

temporal-sdk/src/main/java/io/temporal/internal/client/external/GenericWorkflowClientImpl.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,6 @@ public DescribeWorkflowExecutionResponse describeWorkflowExecution(
309309
grpcRetryerOptions);
310310
}
311311

312-
// TODO -- EVAN -- START
313312
@Override
314313
public StartNexusOperationExecutionResponse startNexusOperationExecution(
315314
@Nonnull StartNexusOperationExecutionRequest request) {
@@ -364,18 +363,6 @@ public CompletableFuture<PollNexusOperationExecutionResponse> pollNexusOperation
364363
new GrpcRetryer.GrpcRetryerOptions(DefaultStubLongPollRpcRetryOptions.INSTANCE, deadline));
365364
}
366365

367-
@Override
368-
public ListNexusOperationExecutionsResponse listNexusOperationExecutions(
369-
@Nonnull ListNexusOperationExecutionsRequest request) {
370-
return grpcRetryer.retryWithResult(
371-
() ->
372-
service
373-
.blockingStub()
374-
.withOption(METRICS_TAGS_CALL_OPTIONS_KEY, metricsScope)
375-
.listNexusOperationExecutions(request),
376-
grpcRetryerOptions);
377-
}
378-
379366
@Override
380367
public CompletableFuture<ListNexusOperationExecutionsResponse> listNexusOperationExecutionsAsync(
381368
@Nonnull ListNexusOperationExecutionsRequest request) {
@@ -438,7 +425,6 @@ public DeleteNexusOperationExecutionResponse deleteNexusOperationExecution(
438425
grpcRetryerOptions);
439426
}
440427

441-
// TODO -- EVAN -- END
442428
private static <T> CompletableFuture<T> toCompletableFuture(
443429
ListenableFuture<T> listenableFuture) {
444430
CompletableFuture<T> result = new CompletableFuture<>();
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package io.temporal.internal.client;
2+
3+
import static org.mockito.ArgumentMatchers.any;
4+
import static org.mockito.Mockito.mock;
5+
import static org.mockito.Mockito.when;
6+
7+
import io.grpc.Deadline;
8+
import io.temporal.api.common.v1.Payload;
9+
import io.temporal.api.enums.v1.NexusOperationWaitStage;
10+
import io.temporal.api.failure.v1.Failure;
11+
import io.temporal.api.workflowservice.v1.PollNexusOperationExecutionRequest;
12+
import io.temporal.api.workflowservice.v1.PollNexusOperationExecutionResponse;
13+
import io.temporal.client.NexusClientOptions;
14+
import io.temporal.client.NexusOperationFailedException;
15+
import io.temporal.common.converter.GlobalDataConverter;
16+
import io.temporal.common.interceptors.NexusClientCallsInterceptor.GetNexusOperationResultInput;
17+
import io.temporal.common.interceptors.NexusClientCallsInterceptor.GetNexusOperationResultOutput;
18+
import io.temporal.internal.client.external.GenericWorkflowClient;
19+
import java.util.concurrent.TimeUnit;
20+
import org.junit.Assert;
21+
import org.junit.Test;
22+
23+
/**
24+
* Server-free unit tests for {@link RootNexusClientInvoker} poll-result extraction. The end-to-end
25+
* Nexus suites are gated on an external service; these mock {@link GenericWorkflowClient} so the
26+
* outcome handling (result / failure / null-result / malformed) is covered in standard CI.
27+
*/
28+
public class RootNexusClientInvokerTest {
29+
30+
private final GenericWorkflowClient genericClient = mock(GenericWorkflowClient.class);
31+
private final RootNexusClientInvoker invoker =
32+
new RootNexusClientInvoker(genericClient, NexusClientOptions.getDefaultInstance());
33+
34+
private static GetNexusOperationResultInput<String> input() {
35+
return new GetNexusOperationResultInput<>(
36+
"op-1", null, Deadline.after(10, TimeUnit.SECONDS), String.class, String.class);
37+
}
38+
39+
private void stubClosedPoll(PollNexusOperationExecutionResponse.Builder response) {
40+
when(genericClient.pollNexusOperationExecution(
41+
any(PollNexusOperationExecutionRequest.class), any(Deadline.class)))
42+
.thenReturn(
43+
response
44+
.setWaitStage(NexusOperationWaitStage.NEXUS_OPERATION_WAIT_STAGE_CLOSED)
45+
.build());
46+
}
47+
48+
@Test
49+
public void closedWithResultReturnsDeserializedValue() throws Exception {
50+
Payload payload = GlobalDataConverter.get().toPayload("hello").get();
51+
stubClosedPoll(PollNexusOperationExecutionResponse.newBuilder().setResult(payload));
52+
53+
GetNexusOperationResultOutput<String> out = invoker.getNexusOperationResult(input());
54+
55+
Assert.assertEquals("hello", out.getResult());
56+
}
57+
58+
@Test
59+
public void closedWithNullResultPayloadReturnsNull() throws Exception {
60+
// A null / Void success arrives as a PRESENT, null-encoded result payload that deserializes to
61+
// null — distinct from the no-outcome malformed case below.
62+
Payload nullPayload = GlobalDataConverter.get().toPayload(null).get();
63+
stubClosedPoll(PollNexusOperationExecutionResponse.newBuilder().setResult(nullPayload));
64+
65+
GetNexusOperationResultOutput<String> out = invoker.getNexusOperationResult(input());
66+
67+
Assert.assertNull(out.getResult());
68+
}
69+
70+
@Test
71+
public void closedWithFailureThrows() {
72+
stubClosedPoll(
73+
PollNexusOperationExecutionResponse.newBuilder()
74+
.setFailure(Failure.newBuilder().setMessage("boom").build()));
75+
76+
Assert.assertThrows(
77+
NexusOperationFailedException.class, () -> invoker.getNexusOperationResult(input()));
78+
}
79+
80+
@Test
81+
public void closedWithNoOutcomeThrows() throws Exception {
82+
// A closed operation must carry either a result or a failure; neither set is a malformed
83+
// response and must surface as an error rather than a silent null.
84+
stubClosedPoll(PollNexusOperationExecutionResponse.newBuilder());
85+
86+
Assert.assertThrows(
87+
NexusOperationFailedException.class, () -> invoker.getNexusOperationResult(input()));
88+
}
89+
}

0 commit comments

Comments
 (0)