Skip to content

Commit f9a5d74

Browse files
authored
fix: set type metadata on search attribute payloads in test server (#2677)
1 parent 6239adb commit f9a5d74

File tree

2 files changed

+121
-2
lines changed

2 files changed

+121
-2
lines changed

temporal-test-server/src/main/java/io/temporal/internal/testservice/TestVisibilityStoreImpl.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.temporal.internal.testservice;
22

33
import com.google.common.collect.ImmutableMap;
4+
import com.google.protobuf.ByteString;
45
import io.grpc.Status;
56
import io.temporal.api.common.v1.Payload;
67
import io.temporal.api.common.v1.SearchAttributes;
@@ -14,6 +15,7 @@
1415

1516
class TestVisibilityStoreImpl implements TestVisibilityStore {
1617

18+
private static final String METADATA_TYPE_KEY = "type";
1719
private static final String DEFAULT_KEY_STRING = "CustomStringField";
1820
private static final String DEFAULT_KEY_TEXT = "CustomTextField";
1921
private static final String DEFAULT_KEY_KEYWORD = "CustomKeywordField";
@@ -76,13 +78,38 @@ public SearchAttributes getSearchAttributesForExecution(ExecutionId executionId)
7678
public SearchAttributes upsertSearchAttributesForExecution(
7779
ExecutionId executionId, @Nonnull SearchAttributes searchAttributes) {
7880
validateSearchAttributes(searchAttributes);
81+
82+
SearchAttributes.Builder searchAttributesWithType = SearchAttributes.newBuilder();
83+
Map<String, IndexedValueType> registeredAttributes = getRegisteredSearchAttributes();
84+
85+
for (Map.Entry<String, Payload> entry : searchAttributes.getIndexedFieldsMap().entrySet()) {
86+
String attributeName = entry.getKey();
87+
Payload payload = entry.getValue();
88+
IndexedValueType expectedType = registeredAttributes.get(attributeName);
89+
90+
if (expectedType != null && !payload.getMetadataMap().containsKey(METADATA_TYPE_KEY)) {
91+
// Add type metadata if it's missing
92+
payload =
93+
payload.toBuilder()
94+
.putMetadata(
95+
METADATA_TYPE_KEY,
96+
ByteString.copyFromUtf8(
97+
ProtoEnumNameUtils.uniqueToSimplifiedName(expectedType)))
98+
.build();
99+
}
100+
101+
searchAttributesWithType.putIndexedFields(attributeName, payload);
102+
}
103+
104+
SearchAttributes searchAttributesWithMetadata = searchAttributesWithType.build();
105+
79106
return executionSearchAttributes.compute(
80107
executionId,
81108
(key, value) ->
82109
value == null
83-
? searchAttributes
110+
? searchAttributesWithMetadata
84111
: value.toBuilder()
85-
.putAllIndexedFields(searchAttributes.getIndexedFieldsMap())
112+
.putAllIndexedFields(searchAttributesWithMetadata.getIndexedFieldsMap())
86113
.build());
87114
}
88115

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package io.temporal.internal.testservice;
2+
3+
import static org.junit.Assert.*;
4+
5+
import com.google.protobuf.ByteString;
6+
import io.temporal.api.common.v1.Payload;
7+
import io.temporal.api.common.v1.SearchAttributes;
8+
import io.temporal.api.enums.v1.IndexedValueType;
9+
import io.temporal.internal.common.ProtoEnumNameUtils;
10+
import org.junit.Test;
11+
12+
public class TestVisibilityStoreImplTest {
13+
private static final String METADATA_TYPE_KEY = "type";
14+
private static final String DEFAULT_KEY_INTEGER = "CustomIntField";
15+
16+
@Test
17+
public void testTypeMetadataIsAddedToPayloads() {
18+
TestVisibilityStoreImpl visibilityStore = new TestVisibilityStoreImpl();
19+
Payload payloadWithoutType =
20+
Payload.newBuilder().setData(ByteString.copyFromUtf8("test data")).build();
21+
22+
assertFalse(
23+
"Payload should not have type metadata initially",
24+
payloadWithoutType.getMetadataMap().containsKey(METADATA_TYPE_KEY));
25+
26+
SearchAttributes.Builder searchAttributesBuilder = SearchAttributes.newBuilder();
27+
searchAttributesBuilder.putIndexedFields(DEFAULT_KEY_INTEGER, payloadWithoutType);
28+
SearchAttributes searchAttributes = searchAttributesBuilder.build();
29+
ExecutionId executionId = new ExecutionId("test-namespace", "test-workflow-id", "test-run-id");
30+
try {
31+
SearchAttributes result =
32+
visibilityStore.upsertSearchAttributesForExecution(executionId, searchAttributes);
33+
assertNotNull("Result should not be null", result);
34+
35+
if (result.containsIndexedFields(DEFAULT_KEY_INTEGER)) {
36+
Payload resultPayload = result.getIndexedFieldsOrThrow(DEFAULT_KEY_INTEGER);
37+
assertTrue(
38+
"Type metadata should be present",
39+
resultPayload.getMetadataMap().containsKey(METADATA_TYPE_KEY));
40+
41+
ByteString typeMetadata = resultPayload.getMetadataMap().get(METADATA_TYPE_KEY);
42+
String typeString = typeMetadata.toStringUtf8();
43+
String expectedTypeString =
44+
ProtoEnumNameUtils.uniqueToSimplifiedName(IndexedValueType.INDEXED_VALUE_TYPE_INT);
45+
46+
assertEquals("Type metadata should match expected type", expectedTypeString, typeString);
47+
}
48+
} catch (Exception e) {
49+
assertTrue("Should be a validation error", e.getMessage().contains("invalid value"));
50+
}
51+
}
52+
53+
@Test
54+
public void testExistingTypeMetadataIsPreserved() {
55+
TestVisibilityStoreImpl visibilityStore = new TestVisibilityStoreImpl();
56+
Payload payloadWithType =
57+
Payload.newBuilder()
58+
.setData(ByteString.copyFromUtf8("test data"))
59+
.putMetadata(METADATA_TYPE_KEY, ByteString.copyFromUtf8("Int"))
60+
.build();
61+
62+
assertTrue(
63+
"Payload should have type metadata initially",
64+
payloadWithType.getMetadataMap().containsKey(METADATA_TYPE_KEY));
65+
66+
SearchAttributes.Builder searchAttributesBuilder = SearchAttributes.newBuilder();
67+
searchAttributesBuilder.putIndexedFields(DEFAULT_KEY_INTEGER, payloadWithType);
68+
SearchAttributes searchAttributes = searchAttributesBuilder.build();
69+
ExecutionId executionId = new ExecutionId("test-namespace", "test-workflow-id", "test-run-id");
70+
71+
try {
72+
SearchAttributes result =
73+
visibilityStore.upsertSearchAttributesForExecution(executionId, searchAttributes);
74+
75+
assertNotNull("Result should not be null", result);
76+
77+
if (result.containsIndexedFields(DEFAULT_KEY_INTEGER)) {
78+
Payload resultPayload = result.getIndexedFieldsOrThrow(DEFAULT_KEY_INTEGER);
79+
assertTrue(
80+
"Type metadata should be present",
81+
resultPayload.getMetadataMap().containsKey(METADATA_TYPE_KEY));
82+
83+
ByteString typeMetadata = resultPayload.getMetadataMap().get(METADATA_TYPE_KEY);
84+
String typeString = typeMetadata.toStringUtf8();
85+
86+
assertEquals("Existing type metadata should be preserved", "Int", typeString);
87+
}
88+
} catch (Exception e) {
89+
assertTrue("Should be a validation error", e.getMessage().contains("invalid value"));
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)