Skip to content

Add support for metadata to test server #2441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,70 @@
package io.temporal.client;

import io.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse;
import io.temporal.common.Experimental;
import io.temporal.common.converter.DataConverter;
import io.temporal.payload.context.WorkflowSerializationContext;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/** Contains information about a workflow execution. */
public class WorkflowExecutionDescription extends WorkflowExecutionMetadata {
private final @Nonnull DataConverter dataConverter;
private final @Nonnull DescribeWorkflowExecutionResponse response;

public WorkflowExecutionDescription(
@Nonnull DescribeWorkflowExecutionResponse response, @Nonnull DataConverter dataConverter) {
super(response.getWorkflowExecutionInfo(), dataConverter);
this.dataConverter = dataConverter;
this.response = response;
}

/**
* Get the fixed summary for this workflow execution.
*
* @apiNote Will be decoded on each invocation, so it is recommended to cache the result if it is
* used multiple times.
*/
@Experimental
@Nullable
public String getStaticSummary() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might consider memoizing this (e.g. backed by an AtomicReference). If not, at least worth clarifying in the javadoc each invocation does data conversion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally don't ever memoize conversion for these type of things, same for memo. I'll note in the docs

if (!response.getExecutionConfig().getUserMetadata().hasSummary()) {
return null;
}
return dataConverter
.withContext(
new WorkflowSerializationContext(
response.getWorkflowExecutionInfo().getParentNamespaceId(),
response.getWorkflowExecutionInfo().getExecution().getWorkflowId()))
.fromPayload(
response.getExecutionConfig().getUserMetadata().getSummary(),
String.class,
String.class);
}

/**
* Get the details summary for this workflow execution.
*
* @apiNote Will be decoded on each invocation, so it is recommended to cache the result if it is
* used multiple times.
*/
@Experimental
@Nullable
public String getStaticDetails() {
if (!response.getExecutionConfig().getUserMetadata().hasDetails()) {
return null;
}
return dataConverter
.withContext(
new WorkflowSerializationContext(
response.getWorkflowExecutionInfo().getParentNamespaceId(),
response.getWorkflowExecutionInfo().getExecution().getWorkflowId()))
.fromPayload(
response.getExecutionConfig().getUserMetadata().getDetails(),
String.class,
String.class);
}

/** Returns the raw response from the Temporal service. */
public DescribeWorkflowExecutionResponse getRawDescription() {
return response;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import io.temporal.internal.common.SearchAttributesUtil;
import io.temporal.payload.context.WorkflowSerializationContext;
import java.lang.reflect.Type;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -98,6 +99,23 @@ public WorkflowExecution getParentExecution() {
return info.hasParentExecution() ? info.getParentExecution() : null;
}

@Nullable
public WorkflowExecution getRootExecution() {
return info.hasRootExecution() ? info.getRootExecution() : null;
}

@Nullable
public String getFirstRunId() {
return info.getFirstRunId();
}

@Nullable
public Duration getExecutionDuration() {
return info.hasExecutionDuration()
? ProtobufTimeUtils.toJavaDuration(info.getExecutionDuration())
: null;
}

/**
* @deprecated use {@link #getTypedSearchAttributes} instead.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ WorkflowExecution getParentWorkflowExecution() {
: null;
}

WorkflowExecution getRootWorkflowExecution() {
return startedAttributes.hasRootWorkflowExecution()
? startedAttributes.getRootWorkflowExecution()
: null;
}

Duration getWorkflowRunTimeout() {
return ProtobufTimeUtils.toJavaDuration(startedAttributes.getWorkflowRunTimeout());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ public Functions.Proc1<Exception> getCancellationHandle() {

WorkflowExecution getParentWorkflowExecution();

WorkflowExecution getRootWorkflowExecution();

WorkflowType getWorkflowType();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ public WorkflowExecution getParentWorkflowExecution() {
return basicWorkflowContext.getParentWorkflowExecution();
}

@Override
public WorkflowExecution getRootWorkflowExecution() {
return basicWorkflowContext.getRootWorkflowExecution();
}

@Override
public String getFirstExecutionRunId() {
return basicWorkflowContext.getFirstExecutionRunId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@ public Optional<String> getParentRunId() {
: Optional.of(parentWorkflowExecution.getRunId());
}

public String getRootWorkflowId() {
WorkflowExecution rootWorkflowExecution = context.getRootWorkflowExecution();
return rootWorkflowExecution == null ? null : rootWorkflowExecution.getWorkflowId();
}

@Override
public String getRootRunId() {
WorkflowExecution rootWorkflowExecution = context.getRootWorkflowExecution();
return rootWorkflowExecution == null ? null : rootWorkflowExecution.getRunId();
}

@Override
public int getAttempt() {
return context.getAttempt();
Expand Down Expand Up @@ -183,6 +194,10 @@ public String toString() {
+ getParentWorkflowId()
+ ", parentRunId="
+ getParentRunId()
+ ", rootWorkflowId="
+ getRootWorkflowId()
+ ", rootRunId="
+ getRootRunId()
+ ", attempt="
+ getAttempt()
+ ", cronSchedule="
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,10 +507,12 @@ public VersioningIntent getVersioningIntent() {
return versioningIntent;
}

@Experimental
public String getStaticSummary() {
return staticSummary;
}

@Experimental
public String getStaticDetails() {
return staticDetails;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,22 @@ public interface WorkflowInfo {
*/
Optional<String> getParentRunId();

/**
* @return Workflow ID of the root Workflow
* @apiNote On server versions prior to v1.27.0, this method will return null. Otherwise, it will
* always return a non-null value.
*/
@Nullable
String getRootWorkflowId();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit awkward since this can only be null on old servers that didn't have this value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, may be worth documenting that here in the javadoc. I do appreciate that this is not using Optional.


/**
* @return Run ID of the root Workflow
* @apiNote On server versions prior to v1.27.0, this method will return null. Otherwise, it will
* always return a non-null value.
*/
@Nullable
String getRootRunId();

/**
* @return Workflow retry attempt handled by this Workflow code execution. Starts on "1".
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
package io.temporal.workflow.activityTests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

import io.temporal.activity.ActivityOptions;
import io.temporal.api.common.v1.WorkflowExecution;
Expand All @@ -36,7 +35,6 @@
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

Expand All @@ -51,11 +49,6 @@ public class ActivityMetadataTest {

static final String activitySummary = "activity-summary";

@Before
public void checkRealServer() {
assumeTrue("skipping for test server", SDKTestWorkflowRule.useExternalService);
}

@Test
public void testActivityWithMetaData() {
TestWorkflow1 stub = testWorkflowRule.newWorkflowStubTimeoutOptions(TestWorkflow1.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
package io.temporal.workflow.activityTests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

import io.temporal.activity.LocalActivityOptions;
import io.temporal.api.common.v1.WorkflowExecution;
Expand All @@ -36,7 +35,6 @@
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

Expand All @@ -51,11 +49,6 @@ public class LocalActivityMetadataTest {

static final String localActivitySummary = "local-activity-summary";

@Before
public void checkRealServer() {
assumeTrue("skipping for test server", SDKTestWorkflowRule.useExternalService);
}

@Test
public void testLocalActivityWithMetaData() {
TestWorkflow1 stub = testWorkflowRule.newWorkflowStubTimeoutOptions(TestWorkflow1.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,10 @@
package io.temporal.workflow.childWorkflowTests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

import io.temporal.api.common.v1.WorkflowExecution;
import io.temporal.api.history.v1.HistoryEvent;
import io.temporal.api.workflowservice.v1.DescribeWorkflowExecutionRequest;
import io.temporal.api.workflowservice.v1.DescribeWorkflowExecutionResponse;
import io.temporal.client.WorkflowExecutionDescription;
import io.temporal.client.WorkflowOptions;
import io.temporal.client.WorkflowStub;
import io.temporal.common.WorkflowExecutionHistory;
Expand All @@ -39,7 +37,6 @@
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

Expand All @@ -57,11 +54,6 @@ public class ChildWorkflowMetadataTest {
static final String childDetails = "child-details";
static final String childTimerSummary = "child-timer-summary";

@Before
public void checkRealServer() {
assumeTrue("skipping for test server", SDKTestWorkflowRule.useExternalService);
}

@Test
public void testChildWorkflowWithMetaData() {
WorkflowOptions options =
Expand Down Expand Up @@ -90,28 +82,10 @@ public void testChildWorkflowWithMetaData() {
}

private void assertWorkflowMetadata(String workflowId, String summary, String details) {
DescribeWorkflowExecutionResponse describe =
testWorkflowRule
.getWorkflowClient()
.getWorkflowServiceStubs()
.blockingStub()
.describeWorkflowExecution(
DescribeWorkflowExecutionRequest.newBuilder()
.setNamespace(testWorkflowRule.getWorkflowClient().getOptions().getNamespace())
.setExecution(WorkflowExecution.newBuilder().setWorkflowId(workflowId).build())
.build());
String describedSummary =
DefaultDataConverter.STANDARD_INSTANCE.fromPayload(
describe.getExecutionConfig().getUserMetadata().getSummary(),
String.class,
String.class);
String describedDetails =
DefaultDataConverter.STANDARD_INSTANCE.fromPayload(
describe.getExecutionConfig().getUserMetadata().getDetails(),
String.class,
String.class);
assertEquals(summary, describedSummary);
assertEquals(details, describedDetails);
WorkflowExecutionDescription describe =
testWorkflowRule.getWorkflowClient().newUntypedWorkflowStub(workflowId).describe();
assertEquals(summary, describe.getStaticSummary());
assertEquals(details, describe.getStaticDetails());
}

private void assertEventMetadata(HistoryEvent event, String summary, String details) {
Expand Down
Loading
Loading