Skip to content

Commit cdfbd22

Browse files
Respond to PR comments
1 parent 4706130 commit cdfbd22

6 files changed

Lines changed: 53 additions & 31 deletions

File tree

temporal-sdk/src/main/java/io/temporal/internal/client/RootActivityClientInvoker.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static io.temporal.internal.common.RetryOptionsUtils.toRetryPolicy;
44
import static io.temporal.internal.common.WorkflowExecutionUtils.makeUserMetaData;
55

6+
import com.google.common.base.Strings;
67
import com.google.common.collect.Iterators;
78
import io.grpc.Deadline;
89
import io.grpc.Status;
@@ -132,13 +133,15 @@ public StartActivityOutput startActivity(StartActivityInput input) {
132133
"failed to generate activity operation token",
133134
e);
134135
}
135-
Callback cb =
136-
InternalUtils.buildNexusCallback(
137-
nexusOperationMetadata.callbackUrl,
138-
nexusOperationMetadata.callbackHeaders,
139-
nexusOperationMetadata.operationToken,
140-
protoLinks);
141-
request.addCompletionCallbacks(cb);
136+
if (!Strings.isNullOrEmpty(nexusOperationMetadata.callbackUrl)) {
137+
Callback cb =
138+
InternalUtils.buildNexusCallback(
139+
nexusOperationMetadata.callbackUrl,
140+
nexusOperationMetadata.callbackHeaders,
141+
nexusOperationMetadata.operationToken,
142+
protoLinks);
143+
request.addCompletionCallbacks(cb);
144+
}
142145
}
143146

144147
StartActivityExecutionResponse response;

temporal-sdk/src/main/java/io/temporal/internal/nexus/OperationTokenType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
public enum OperationTokenType {
77
UNKNOWN(0),
88
WORKFLOW_RUN(1),
9-
// Values 2 and 3 are reserved for future token types (e.g. update-workflow, get-workflow-result).
10-
ACTIVITY_EXECUTION(4);
9+
ACTIVITY_EXECUTION(2),
10+
UPDATE_WORKFLOW(3);
1111

1212
private final int value;
1313

temporal-sdk/src/main/java/io/temporal/nexus/TemporalNexusClientImpl.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -516,16 +516,17 @@ private <R> TemporalOperationResult<R> startActivityImpl(
516516
.build());
517517
ActivityClientCallsInterceptor.StartActivityOutput out =
518518
((ActivityClientInternal) activityClient).getInvoker().startActivity(input);
519-
// The invoker generated and injected the runId-free token into the callback
520-
// headers before the start RPC fired. The header token cannot include a run ID
521-
// because the run ID isn't known until after the start RPC returns. The operation
522-
// token returned to the Nexus caller can — and should — include it, so it's
523-
// regenerated here from the same activity ID + the run ID the start RPC produced.
519+
// The invoker generated the runId-free token before the start RPC and injected it
520+
// into the callback headers when a callback URL was supplied. That token cannot
521+
// include a run ID because the run ID isn't known until after the start RPC
522+
// returns. The operation token returned to the Nexus caller can — and should —
523+
// include it, so it's regenerated here from the same activity ID + the run ID the
524+
// start RPC produced.
524525
String headerToken = nexusOperationMetadata.operationToken;
525526
if (headerToken == null) {
526527
throw new HandlerException(
527528
HandlerException.ErrorType.INTERNAL,
528-
"invoker did not return a Nexus operation token for activity start with callback",
529+
"invoker did not generate a Nexus operation token for activity start",
529530
new IllegalStateException(
530531
"operationToken is null on NexusOperationMetadata after activity start"));
531532
}

temporal-sdk/src/test/java/io/temporal/internal/client/RootActivityClientInvokerTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,28 @@ public void nexusMetadataAddsCallbackLinksAndRequestId() {
103103
Assert.assertEquals(Collections.singletonList(activityLink()), nexusContext.getResponseLinks());
104104
}
105105

106+
@Test
107+
public void nexusMetadataWithEmptyCallbackUrlOmitsCompletionCallback() {
108+
NexusOperationMetadata metadata =
109+
new NexusOperationMetadata(
110+
"nexus-request-id", "", Collections.singletonMap("Custom-Header", "value"));
111+
nexusContext.setNexusOperationMetadata(metadata);
112+
Link link = workflowEventLink();
113+
nexusContext.setRequestLinks(Collections.singletonList(link));
114+
115+
invoker.startActivity(newStartActivityInput());
116+
117+
ArgumentCaptor<StartActivityExecutionRequest> captor =
118+
ArgumentCaptor.forClass(StartActivityExecutionRequest.class);
119+
verify(genericClient).startActivity(captor.capture());
120+
StartActivityExecutionRequest request = captor.getValue();
121+
Assert.assertEquals("nexus-request-id", request.getRequestId());
122+
Assert.assertEquals(Collections.singletonList(link), request.getLinksList());
123+
Assert.assertEquals(0, request.getCompletionCallbacksCount());
124+
Assert.assertNotNull(metadata.operationToken);
125+
Assert.assertEquals(Collections.singletonList(activityLink()), nexusContext.getResponseLinks());
126+
}
127+
106128
@Test
107129
public void nexusContextWithoutMetadataStartsOrdinaryActivity() {
108130
nexusContext.setRequestLinks(Collections.singletonList(workflowEventLink()));

temporal-sdk/src/test/java/io/temporal/internal/nexus/WorkflowRunTokenTest.java renamed to temporal-sdk/src/test/java/io/temporal/internal/nexus/OperationTokenTest.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@
88
import org.junit.Assert;
99
import org.junit.Test;
1010

11-
public class WorkflowRunTokenTest {
11+
public class OperationTokenTest {
1212
private static final ObjectWriter ow =
1313
new ObjectMapper().registerModule(new Jdk8Module()).writer();
1414
private static final ObjectReader or =
1515
new ObjectMapper().registerModule(new Jdk8Module()).reader();
1616
private static final Base64.Encoder encoder = Base64.getUrlEncoder().withoutPadding();
1717

18+
@Test
19+
public void operationTokenTypeValues() {
20+
Assert.assertEquals(0, OperationTokenType.UNKNOWN.toValue());
21+
Assert.assertEquals(1, OperationTokenType.WORKFLOW_RUN.toValue());
22+
Assert.assertEquals(2, OperationTokenType.ACTIVITY_EXECUTION.toValue());
23+
Assert.assertEquals(3, OperationTokenType.UPDATE_WORKFLOW.toValue());
24+
}
25+
1826
@Test
1927
public void serializeWorkflowRunToken() throws JsonProcessingException {
2028
OperationToken token =
@@ -140,7 +148,7 @@ public void workflowRunTokenBytesByteIdenticalSnapshot() throws JsonProcessingEx
140148

141149
@Test
142150
public void malformedActivityTokenRejected() {
143-
String malformed = "{\"t\":4,\"ns\":\"ns\",\"aid\":\"\"}";
151+
String malformed = "{\"t\":2,\"ns\":\"ns\",\"aid\":\"\"}";
144152
IllegalArgumentException ex =
145153
Assert.assertThrows(
146154
IllegalArgumentException.class,

temporal-sdk/src/test/java/io/temporal/workflow/nexus/AsyncActivityOperationTest.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ protected SDKTestWorkflowRule getTestWorkflowRule() {
4545
public void testActivityOperationEndToEnd() {
4646
// The in-process test-server does not implement the StartActivityExecution RPC; the
4747
// standalone-activity Nexus path requires a real server. Unit-only token assertions stay
48-
// active in testActivityOperationTokenRoundTrip below.
48+
// active in OperationTokenTest.
4949
assumeTrue(SDKTestWorkflowRule.useExternalService);
5050
// Combined (a) caller workflow receives "hello " + input
5151
// (b) opToken loads as ACTIVITY_EXECUTION with aid="act-" + requestId
@@ -55,25 +55,13 @@ public void testActivityOperationEndToEnd() {
5555
Assert.assertEquals("hello world", result);
5656
}
5757

58-
@Test
59-
public void testActivityOperationTokenRoundTrip() throws Exception {
60-
// (c) generateActivityExecutionOperationToken then loadOperationToken round-trips equal
61-
// aid + ns.
62-
String token = OperationTokenUtil.generateActivityExecutionOperationToken("act-123", "test-ns");
63-
OperationToken loaded = OperationTokenUtil.loadOperationToken(token);
64-
Assert.assertEquals(OperationTokenType.ACTIVITY_EXECUTION, loaded.getType());
65-
Assert.assertEquals("act-123", loaded.getActivityId());
66-
Assert.assertEquals("test-ns", loaded.getNamespace());
67-
Assert.assertNull(loaded.getWorkflowId());
68-
}
69-
7058
@Test
7159
public void testDoubleStartActivityThrows() {
7260
// The first start RPC requires StartActivityExecution which is not implemented by the
7361
// in-process test server; gate this on a real server so the guard at the second call can be
7462
// observed.
7563
assumeTrue(SDKTestWorkflowRule.useExternalService);
76-
// (d) Calling startActivity twice in one handler invocation throws
64+
// (c) Calling startActivity twice in one handler invocation throws
7765
// HandlerException(BAD_REQUEST).
7866
TestDoubleStartWorkflow workflowStub =
7967
testWorkflowRule.newWorkflowStubTimeoutOptions(TestDoubleStartWorkflow.class);

0 commit comments

Comments
 (0)