Skip to content

Commit 91b0eb5

Browse files
Carry over search attributes on continue-as-new if none are explicitly specified
1 parent b949929 commit 91b0eb5

3 files changed

Lines changed: 24 additions & 8 deletions

File tree

temporal-sdk/src/main/java/io/temporal/internal/sync/SyncWorkflowContext.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,12 @@ public void continueAsNew(ContinueAsNewInput input) {
13651365
&& options.getTypedSearchAttributes().size() > 0) {
13661366
attributes.setSearchAttributes(
13671367
SearchAttributesUtil.encodeTyped(options.getTypedSearchAttributes()));
1368+
} else {
1369+
// Carry over existing search attributes if none are specified.
1370+
SearchAttributes existing = replayContext.getSearchAttributes();
1371+
if (existing != null && !existing.getIndexedFieldsMap().isEmpty()) {
1372+
attributes.setSearchAttributes(existing);
1373+
}
13681374
}
13691375
Map<String, Object> memo = options.getMemo();
13701376
if (memo != null) {
@@ -1380,8 +1386,9 @@ public void continueAsNew(ContinueAsNewInput input) {
13801386
replayContext.getTaskQueue().equals(options.getTaskQueue())));
13811387
}
13821388
} else if (replayContext.getRetryOptions() != null) {
1383-
// Have to copy retry options as server doesn't copy them.
1389+
// Have to copy certain options as server doesn't copy them.
13841390
attributes.setRetryPolicy(toRetryPolicy(replayContext.getRetryOptions()));
1391+
attributes.setSearchAttributes(replayContext.getSearchAttributes());
13851392
}
13861393

13871394
List<ContextPropagator> propagators =

temporal-sdk/src/main/java/io/temporal/workflow/ContinueAsNewOptions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import javax.annotation.Nullable;
99

1010
/**
11-
* This class contain overrides for continueAsNew call. Every field can be null and it means that
11+
* This class contain overrides for continueAsNew call. Every field can be null, and it means that
1212
* the value of the option should be taken from the originating workflow run.
1313
*/
1414
public final class ContinueAsNewOptions {

temporal-sdk/src/test/java/io/temporal/workflow/ContinueAsNewTest.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@
1616
import org.junit.Test;
1717

1818
public class ContinueAsNewTest {
19+
static final SearchAttributeKey<String> CUSTOM_KEYWORD_SA =
20+
SearchAttributeKey.forKeyword("CustomKeywordField");
1921

2022
public static final int INITIAL_COUNT = 4;
2123

2224
@Rule
2325
public SDKTestWorkflowRule testWorkflowRule =
24-
SDKTestWorkflowRule.newBuilder().setWorkflowTypes(TestContinueAsNewImpl.class).build();
26+
SDKTestWorkflowRule.newBuilder()
27+
.setWorkflowTypes(TestContinueAsNewImpl.class)
28+
.setUseExternalService(true)
29+
.build();
2530

2631
@Test
2732
public void testContinueAsNew() {
@@ -30,6 +35,8 @@ public void testContinueAsNew() {
3035
options =
3136
WorkflowOptions.newBuilder(options)
3237
.setRetryOptions(RetryOptions.newBuilder().setMaximumAttempts(10).build())
38+
.setTypedSearchAttributes(
39+
SearchAttributes.newBuilder().set(CUSTOM_KEYWORD_SA, "foo0").build())
3340
.build();
3441
TestContinueAsNew client =
3542
testWorkflowRule.getWorkflowClient().newWorkflowStub(TestContinueAsNew.class, options);
@@ -68,8 +75,10 @@ public int execute(int count, String continueAsNewTaskQueue) {
6875
String taskQueue = Workflow.getInfo().getTaskQueue();
6976
if (count >= INITIAL_COUNT - 2) {
7077
assertEquals(10, Workflow.getInfo().getRetryOptions().getMaximumAttempts());
78+
assertEquals("foo0", Workflow.getTypedSearchAttributes().get(CUSTOM_KEYWORD_SA));
7179
} else {
7280
assertEquals(5, Workflow.getInfo().getRetryOptions().getMaximumAttempts());
81+
assertEquals("foo1", Workflow.getTypedSearchAttributes().get(CUSTOM_KEYWORD_SA));
7382
}
7483
if (count == 0) {
7584
assertEquals(continueAsNewTaskQueue, taskQueue);
@@ -78,22 +87,22 @@ public int execute(int count, String continueAsNewTaskQueue) {
7887
Map<String, Object> memo = new HashMap<>();
7988
memo.put("myKey", "MyValue");
8089
RetryOptions retryOptions = null;
90+
SearchAttributes searchAttributes = null;
8191
// don't specify ContinueAsNewOptions on the first continue-as-new to test that RetryOptions
92+
// and SearchAttributes
8293
// are copied from the previous run.
8394
if (count == INITIAL_COUNT) {
8495
TestContinueAsNew next = Workflow.newContinueAsNewStub(TestContinueAsNew.class);
8596
next.execute(count - 1, continueAsNewTaskQueue);
8697
throw new RuntimeException("unreachable");
8798
}
88-
// don't specify RetryOptions on the second continue-as-new to test that they are copied from
99+
// don't specify RetryOptions and SearchAttributes on the second continue-as-new to test that
100+
// they are copied from
89101
// the previous run.
90102
if (count < INITIAL_COUNT - 1) {
91103
retryOptions = RetryOptions.newBuilder().setMaximumAttempts(5).build();
104+
searchAttributes = SearchAttributes.newBuilder().set(CUSTOM_KEYWORD_SA, "foo1").build();
92105
}
93-
SearchAttributes searchAttributes =
94-
SearchAttributes.newBuilder()
95-
.set(SearchAttributeKey.forKeyword("CustomKeywordField"), "foo1")
96-
.build();
97106
ContinueAsNewOptions options =
98107
ContinueAsNewOptions.newBuilder()
99108
.setTaskQueue(continueAsNewTaskQueue)

0 commit comments

Comments
 (0)