Thanks to visit codestin.com
Credit goes to github.com

Skip to content

User metadata #1657

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open

User metadata #1657

wants to merge 5 commits into from

Conversation

THardy98
Copy link
Contributor

What was changed

Added functionality for users to provide staticDetails and staticSummary metadata to workflow start commands.
These can be retrieved via describe on the workflow handler and are visibile via the UI/CLI.

Users can set currentDetails - a mutable details string within the workflow - via SetCurrentDetails and retrieve it via GetCurrentDetails. This is visible via the UI/CLI and the __temporal_workflow_metadata internal query.

Users can add a summary (short string description) when setting a timer and when starting an activity.

  1. Closes [Feature Request] Support user metadata #1544

  2. How was this tested:
    Couple integration tests

  3. Any docs updates needed?
    Maybe

@THardy98 THardy98 requested a review from a team as a code owner March 21, 2025 19:51
* General fixed details for this workflow execution that may appear in UI/CLI.
* This can be in Temporal markdown format and can span multiple lines.
*
* @experimental
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a short comment on all @experimental tags (see what we did elsewhere). Benefit isn't huge, but at least, it identifies which "feature" the experimental API is linked with.

@@ -240,6 +245,7 @@ export async function encodeScheduleAction(
action: CompiledScheduleAction,
headers: Headers
): Promise<temporal.api.schedule.v1.IScheduleAction> {
const jsonConverter = new JsonPayloadConverter();
Copy link
Contributor

Choose a reason for hiding this comment

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

Use the data converters configured on the client (i.e. custom payload converter and codec).

@@ -312,6 +322,8 @@ export async function decodeScheduleAction(
pb: temporal.api.schedule.v1.IScheduleAction
): Promise<ScheduleDescriptionAction> {
if (pb.startWorkflow) {
const jsonConverter = new JsonPayloadConverter();
Copy link
Contributor

Choose a reason for hiding this comment

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

Use the data converters configured on the client (i.e. custom payload converter and codec).

@@ -1196,6 +1197,7 @@ export class WorkflowClient extends BaseClient {
protected async _signalWithStartWorkflowHandler(input: WorkflowSignalWithStartInput): Promise<string> {
const { identity } = this.options;
const { options, workflowType, signalName, signalArgs, headers } = input;
const jsonConverter = new JsonPayloadConverter();
Copy link
Contributor

Choose a reason for hiding this comment

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

Use the data converters configured on the client (i.e. custom payload converter and codec).

@@ -1225,6 +1227,10 @@ export class WorkflowClient extends BaseClient {
: undefined,
cronSchedule: options.cronSchedule,
header: { fields: headers },
userMetadata: {
summary: jsonConverter.toPayload(options?.staticSummary),
Copy link
Contributor

Choose a reason for hiding this comment

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

You will need to use await encodeToPayload(...) instead here and everything else in the client package. Not in Workflows and Worker, though.

return undefined;
}

const jsonConverter = new JsonPayloadConverter();
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't create a JSON payload converter. Use the payload converter from the activator.

@@ -80,6 +80,7 @@ export interface ActivityInput {
readonly options: ActivityOptions;
readonly headers: Headers;
readonly seq: number;
readonly cmdOpts?: WorkflowCommandOptions;
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we should have this WorkflowCommandOptions type. I even wonder if we should inline summary and details directly in ActivityInput (without the extra UserMetadata nesting). Or add these two to ActivityOptions, though that might pose some minor challenge regarding the type provided to the proxyActivities() function.

Copy link
Contributor

Choose a reason for hiding this comment

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

What did we do in other SDKs?

*/
export function sleep(ms: Duration): Promise<void> {
export function sleep(ms: Duration, summary?: string): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm worried this will evolve badly. What if we then need to add description, and then other properties? Instead, I think I'd define a TimerOptions type, and take this as a second argument here. Then, we can easily add whatever properties we need.

Copy link
Contributor

Choose a reason for hiding this comment

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

Out of curiosity, what do we do in other SDKs?

activityType: string,
args: any[],
options: ActivityOptions,
summary?: string
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah… So, looking at this one, I really feel this should be part of ActivityOptions.

* @param summaries Record mapping activity names to their summary descriptions
* @returns A new proxy with the provided summaries
*/
withSummaries(summaries: Record<string, string>): ActivityInterfaceFor<A>;
Copy link
Contributor

Choose a reason for hiding this comment

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

🤔 That feels a bit awkward, and would prevent having an activity named withSummaries (ok, that's arguably very unlikely, but still means this approach would evolve badly).

I think we could get a better DX by using something similar to this, but at the activity-level rather than at the activities-level (mind the plural). That would also allow any extra option to be set at the call site, which is a recurring request.

For example, we could have:

const { echo } = proxyActivities<MyActivities>({ startToCloseTimeout: '5m' });

// No extra options
await echo(myArg1, myArg2);

// With extra options, higher order function style
await echo.withOptions({ summary: "..." })(myArg1, myArg2);

// Some other possible variants to be considered
await echo.withOptions({ summary: "..." }, myArg1, myArg2);
await echo.withOptions({ summary: "..." }, [myArg1, myArg2]);

I'll let you think you a bit about this, but we should probably include others in this discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request] Support user metadata
2 participants