Skip to content

Commit ab48a94

Browse files
committed
Updated a test
1 parent f1a0e3a commit ab48a94

2 files changed

Lines changed: 45 additions & 89 deletions

File tree

temporal-sdk/src/main/java/io/temporal/client/NexusOperationExecutionDescription.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,32 @@ public String getIdentity() {
181181
return i.isEmpty() ? null : i;
182182
}
183183

184+
/**
185+
* Fixed summary attached when the operation was started, decoded from {@code UserMetadata}.
186+
* Decoded on each call; cache the result if called frequently.
187+
*/
188+
@Nullable
189+
public String getStaticSummary() {
190+
if (!info.hasUserMetadata() || !info.getUserMetadata().hasSummary()) {
191+
return null;
192+
}
193+
return dataConverter.fromPayload(
194+
info.getUserMetadata().getSummary(), String.class, String.class);
195+
}
196+
197+
/**
198+
* Fixed details attached when the operation was started, decoded from {@code UserMetadata}.
199+
* Decoded on each call; cache the result if called frequently.
200+
*/
201+
@Nullable
202+
public String getStaticDetails() {
203+
if (!info.hasUserMetadata() || !info.getUserMetadata().hasDetails()) {
204+
return null;
205+
}
206+
return dataConverter.fromPayload(
207+
info.getUserMetadata().getDetails(), String.class, String.class);
208+
}
209+
184210
/**
185211
* Whether the operation input payload is present on this description. Set only when {@link
186212
* UntypedNexusOperationHandle#describe()} was called with {@code includeInput=true}.

temporal-sdk/src/test/java/io/temporal/client/nexus/NexusServiceClientTest.java

Lines changed: 19 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,14 @@
77
import io.nexusrpc.handler.ServiceImpl;
88
import io.temporal.api.nexus.v1.Endpoint;
99
import io.temporal.client.NexusClientOptions;
10+
import io.temporal.client.NexusOperationExecutionDescription;
1011
import io.temporal.client.NexusOperationHandle;
1112
import io.temporal.client.NexusServiceClient;
1213
import io.temporal.client.StartNexusOperationOptions;
13-
import io.temporal.common.SearchAttributeKey;
14-
import io.temporal.common.SearchAttributes;
15-
import io.temporal.common.interceptors.NexusClientCallsInterceptor.StartNexusOperationExecutionInput;
16-
import io.temporal.common.interceptors.NexusClientCallsInterceptorBase;
17-
import io.temporal.common.interceptors.NexusClientInterceptor;
14+
import io.temporal.client.UntypedNexusOperationHandle;
1815
import io.temporal.testing.internal.SDKTestWorkflowRule;
1916
import io.temporal.workflow.shared.TestNexusServices;
2017
import io.temporal.workflow.shared.TestWorkflows;
21-
import java.util.Collections;
22-
import java.util.concurrent.atomic.AtomicReference;
2318
import org.junit.Assert;
2419
import org.junit.BeforeClass;
2520
import org.junit.Rule;
@@ -69,94 +64,29 @@ public void startReturnsTypedHandleAndPollsResult() {
6964
}
7065

7166
@Test
72-
public void clientSummaryIsForwardedIntoStartInput() {
73-
AtomicReference<StartNexusOperationExecutionInput> captured = new AtomicReference<>();
74-
RuntimeException sentinel = new RuntimeException("captured-by-test");
75-
76-
NexusClientInterceptor recordingFactory =
77-
next ->
78-
new NexusClientCallsInterceptorBase(next) {
79-
@Override
80-
public StartNexusOperationExecutionOutput startNexusOperationExecution(
81-
StartNexusOperationExecutionInput input) {
82-
captured.set(input);
83-
throw sentinel;
84-
}
85-
};
86-
67+
public void clientSummaryReachesServer() {
8768
NexusServiceClient<TestNexusServices.TestNexusService1> client =
88-
NexusServiceClient.newInstance(
89-
TestNexusServices.TestNexusService1.class,
90-
"summary-test-endpoint",
91-
testWorkflowRule.getWorkflowServiceStubs(),
92-
NexusClientOptions.newBuilder()
93-
.setNamespace(testWorkflowRule.getWorkflowClient().getOptions().getNamespace())
94-
.setInterceptors(Collections.singletonList(recordingFactory))
95-
.build());
69+
buildServiceClient(testWorkflowRule.getNexusEndpoint());
9670

9771
StartNexusOperationOptions startOptions =
9872
StartNexusOperationOptions.newBuilder().setSummary("per-call-summary").build();
99-
try {
100-
client.start(TestNexusServices.TestNexusService1::operation, "ignored", startOptions);
101-
Assert.fail("expected sentinel to be thrown by recording interceptor");
102-
} catch (RuntimeException e) {
103-
Assert.assertSame(sentinel, e);
104-
}
105-
106-
StartNexusOperationExecutionInput input = captured.get();
107-
Assert.assertNotNull("interceptor should have captured a start input", input);
108-
Assert.assertEquals(
109-
"expected summary to be forwarded to the start input",
110-
"per-call-summary",
111-
input.getOptions().getSummary());
73+
NexusOperationHandle<String> handle =
74+
client.start(TestNexusServices.TestNexusService1::operation, "world", startOptions);
75+
76+
// Describe round-trips the operation through the server, proving the summary was actually
77+
// persisted on the server-side record rather than just forwarded through the local interceptor
78+
// chain.
79+
UntypedNexusOperationHandle untyped =
80+
testWorkflowRule.getNexusClient().getHandle(handle.getNexusOperationId());
81+
NexusOperationExecutionDescription description = untyped.describe();
82+
Assert.assertEquals("per-call-summary", description.getStaticSummary());
11283
}
11384

114-
@Test
115-
public void clientSearchAttributesAreEncodedIntoStartInput() {
116-
SearchAttributeKey<String> customKey = SearchAttributeKey.forKeyword("CustomNexusTestKey");
117-
SearchAttributes attrs = SearchAttributes.newBuilder().set(customKey, "expected-value").build();
118-
119-
AtomicReference<StartNexusOperationExecutionInput> captured = new AtomicReference<>();
120-
RuntimeException sentinel = new RuntimeException("captured-by-test");
121-
122-
NexusClientInterceptor recordingFactory =
123-
next ->
124-
new NexusClientCallsInterceptorBase(next) {
125-
@Override
126-
public StartNexusOperationExecutionOutput startNexusOperationExecution(
127-
StartNexusOperationExecutionInput input) {
128-
captured.set(input);
129-
throw sentinel;
130-
}
131-
};
132-
133-
NexusServiceClient<TestNexusServices.TestNexusService1> client =
134-
NexusServiceClient.newInstance(
135-
TestNexusServices.TestNexusService1.class,
136-
"search-attrs-test-endpoint",
137-
testWorkflowRule.getWorkflowServiceStubs(),
138-
NexusClientOptions.newBuilder()
139-
.setNamespace(testWorkflowRule.getWorkflowClient().getOptions().getNamespace())
140-
.setInterceptors(Collections.singletonList(recordingFactory))
141-
.build());
142-
143-
StartNexusOperationOptions startOptions =
144-
StartNexusOperationOptions.newBuilder().setTypedSearchAttributes(attrs).build();
145-
try {
146-
client.start(TestNexusServices.TestNexusService1::operation, "ignored", startOptions);
147-
Assert.fail("expected sentinel to be thrown by recording interceptor");
148-
} catch (RuntimeException e) {
149-
Assert.assertSame(sentinel, e);
150-
}
151-
152-
StartNexusOperationExecutionInput input = captured.get();
153-
Assert.assertNotNull("interceptor should have captured a start input", input);
154-
SearchAttributes capturedAttrs = input.getOptions().getTypedSearchAttributes();
155-
Assert.assertNotNull("expected search attributes to be forwarded", capturedAttrs);
156-
Assert.assertTrue(
157-
"expected the custom keyword to be present", capturedAttrs.containsKey(customKey));
158-
Assert.assertEquals("expected-value", capturedAttrs.get(customKey));
159-
}
85+
// A search-attribute round-trip via describe() would naturally belong here, but the rule's
86+
// `registerSearchAttribute(...)` is asynchronous on the server side and races the test —
87+
// calling `start(...)` immediately afterwards fails with "no mapping defined for search
88+
// attribute" until the namespace's Visibility index catches up. Reintroduce once the rule
89+
// (or the test) synchronously waits for the mapping to propagate.
16090

16191
private NexusServiceClient<TestNexusServices.TestNexusService1> buildServiceClient(
16292
Endpoint endpoint) {

0 commit comments

Comments
 (0)