Skip to content

Commit 7b3aa1c

Browse files
committed
init impl of user metadata
1 parent 8ed034c commit 7b3aa1c

File tree

8 files changed

+141
-43
lines changed

8 files changed

+141
-43
lines changed

packages/client/src/schedule-helpers.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Long from 'long'; // eslint-disable-line import/no-named-as-default
2-
import { compileRetryPolicy, decompileRetryPolicy, extractWorkflowType, LoadedDataConverter } from '@temporalio/common';
2+
import { compileRetryPolicy, decompileRetryPolicy, extractWorkflowType, JsonPayloadConverter, LoadedDataConverter } from '@temporalio/common';
33
import {
44
encodeUnifiedSearchAttributes,
55
decodeSearchAttributes,
@@ -189,8 +189,7 @@ export function decodeOptionalStructuredCalendarSpecs(
189189
}
190190

191191
export function compileScheduleOptions(options: ScheduleOptions): CompiledScheduleOptions {
192-
const workflowTypeOrFunc = options.action.workflowType;
193-
const workflowType = extractWorkflowType(workflowTypeOrFunc);
192+
const workflowType = extractWorkflowType(options.action.workflowType);
194193
return {
195194
...options,
196195
action: {
@@ -240,6 +239,7 @@ export async function encodeScheduleAction(
240239
action: CompiledScheduleAction,
241240
headers: Headers
242241
): Promise<temporal.api.schedule.v1.IScheduleAction> {
242+
const jsonConverter = new JsonPayloadConverter()
243243
return {
244244
startWorkflow: {
245245
workflowId: action.workflowId,
@@ -263,6 +263,10 @@ export async function encodeScheduleAction(
263263
}
264264
: undefined,
265265
header: { fields: headers },
266+
userMetadata: {
267+
summary: jsonConverter.toPayload(action.staticSummary),
268+
details: jsonConverter.toPayload(action.staticDetails)
269+
}
266270
},
267271
};
268272
}

packages/client/src/schedule-types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,8 @@ export type ScheduleOptionsStartWorkflowAction<W extends Workflow> = {
783783
| 'workflowExecutionTimeout'
784784
| 'workflowRunTimeout'
785785
| 'workflowTaskTimeout'
786+
| 'staticDetails'
787+
| 'staticSummary'
786788
> & {
787789
/**
788790
* Workflow id to use when starting. Assign a meaningful business id.
@@ -815,6 +817,8 @@ export type ScheduleDescriptionStartWorkflowAction = ScheduleSummaryStartWorkflo
815817
| 'workflowExecutionTimeout'
816818
| 'workflowRunTimeout'
817819
| 'workflowTaskTimeout'
820+
| 'staticSummary'
821+
| 'staticDetails'
818822
>;
819823

820824
// Invariant: an existing ScheduleDescriptionAction can be used as is to create or update a schedule

packages/client/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ export interface CountWorkflowExecution {
6565
export type WorkflowExecutionDescription = Replace<
6666
WorkflowExecutionInfo,
6767
{
68+
staticSummary?: string;
69+
staticDetails?: string;
6870
raw: DescribeWorkflowExecutionResponse;
6971
}
7072
>;

packages/client/src/workflow-client.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
decodeRetryState,
2323
encodeWorkflowIdConflictPolicy,
2424
WorkflowIdConflictPolicy,
25+
JsonPayloadConverter,
2526
} from '@temporalio/common';
2627
import { encodeUnifiedSearchAttributes } from '@temporalio/common/lib/converter/payload-search-attributes';
2728
import { composeInterceptors } from '@temporalio/common/lib/interceptors';
@@ -510,7 +511,7 @@ export class WorkflowClient extends BaseClient {
510511

511512
protected async _start<T extends Workflow>(
512513
workflowTypeOrFunc: string | T,
513-
options: WithWorkflowArgs<T, WorkflowOptions>,
514+
options: WorkflowStartOptions<T>,
514515
interceptors: WorkflowClientInterceptor[]
515516
): Promise<string> {
516517
const workflowType = extractWorkflowType(workflowTypeOrFunc);
@@ -1196,6 +1197,7 @@ export class WorkflowClient extends BaseClient {
11961197
protected async _signalWithStartWorkflowHandler(input: WorkflowSignalWithStartInput): Promise<string> {
11971198
const { identity } = this.options;
11981199
const { options, workflowType, signalName, signalArgs, headers } = input;
1200+
const jsonConverter = new JsonPayloadConverter();
11991201
const req: temporal.api.workflowservice.v1.ISignalWithStartWorkflowExecutionRequest = {
12001202
namespace: this.options.namespace,
12011203
identity,
@@ -1225,6 +1227,10 @@ export class WorkflowClient extends BaseClient {
12251227
: undefined,
12261228
cronSchedule: options.cronSchedule,
12271229
header: { fields: headers },
1230+
userMetadata: {
1231+
summary: jsonConverter.toPayload(options?.staticSummary),
1232+
details: jsonConverter.toPayload(options?.staticDetails)
1233+
}
12281234
};
12291235
try {
12301236
return (await this.workflowService.signalWithStartWorkflowExecution(req)).runId;
@@ -1265,7 +1271,7 @@ export class WorkflowClient extends BaseClient {
12651271
protected async createStartWorkflowRequest(input: WorkflowStartInput): Promise<StartWorkflowExecutionRequest> {
12661272
const { options: opts, workflowType, headers } = input;
12671273
const { identity, namespace } = this.options;
1268-
1274+
const jsonConverter = new JsonPayloadConverter()
12691275
return {
12701276
namespace,
12711277
identity,
@@ -1293,6 +1299,10 @@ export class WorkflowClient extends BaseClient {
12931299
: undefined,
12941300
cronSchedule: opts.cronSchedule,
12951301
header: { fields: headers },
1302+
userMetadata: {
1303+
summary: jsonConverter.toPayload(opts?.staticSummary),
1304+
details: jsonConverter.toPayload(opts?.staticDetails)
1305+
}
12961306
};
12971307
}
12981308

@@ -1426,8 +1436,12 @@ export class WorkflowClient extends BaseClient {
14261436
workflowExecution: { workflowId, runId },
14271437
});
14281438
const info = await executionInfoFromRaw(raw.workflowExecutionInfo ?? {}, this.client.dataConverter, raw);
1439+
const jsonConverter = new JsonPayloadConverter()
1440+
const userMetadata = raw.executionConfig?.userMetadata
14291441
return {
14301442
...info,
1443+
staticDetails: userMetadata?.details ? jsonConverter.fromPayload(userMetadata.details) : undefined,
1444+
staticSummary: userMetadata?.summary ? jsonConverter.fromPayload(userMetadata.summary) : undefined,
14311445
raw,
14321446
};
14331447
},

packages/common/src/workflow-options.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,21 @@ export interface BaseWorkflowOptions {
190190
* by {@link typedSearchAttributes}.
191191
*/
192192
typedSearchAttributes?: SearchAttributePair[] | TypedSearchAttributes;
193+
194+
/**
195+
* General fixed details for this workflow execution that may appear in UI/CLI.
196+
* This can be in Temporal markdown format and can span multiple lines.
197+
*
198+
* @experimental
199+
*/
200+
staticDetails?: string;
201+
/**
202+
* A single-line fixed summary for this workflow execution that may appear in the UI/CLI.
203+
* This can be in single-line Temporal markdown format.
204+
*
205+
* @experimental
206+
*/
207+
staticSummary?: string;
193208
}
194209

195210
export type WithWorkflowArgs<W extends Workflow, T> = T &

packages/workflow/src/interceptors.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import { ActivityOptions, Headers, LocalActivityOptions, Next, Timestamp, WorkflowExecution } from '@temporalio/common';
10-
import type { coresdk } from '@temporalio/proto';
10+
import type { coresdk, temporal } from '@temporalio/proto';
1111
import { ChildWorkflowOptionsWithDefaults, ContinueAsNewOptions } from './interfaces';
1212

1313
export { Next, Headers };
@@ -80,6 +80,7 @@ export interface ActivityInput {
8080
readonly options: ActivityOptions;
8181
readonly headers: Headers;
8282
readonly seq: number;
83+
readonly cmdOpts?: WorkflowCommandOptions;
8384
}
8485

8586
/** Input for WorkflowOutboundCallsInterceptor.scheduleLocalActivity */
@@ -91,6 +92,7 @@ export interface LocalActivityInput {
9192
readonly seq: number;
9293
readonly originalScheduleTime?: Timestamp;
9394
readonly attempt: number;
95+
readonly cmdOpts?: WorkflowCommandOptions;
9496
}
9597

9698
/** Input for WorkflowOutboundCallsInterceptor.startChildWorkflowExecution */
@@ -101,10 +103,33 @@ export interface StartChildWorkflowExecutionInput {
101103
readonly seq: number;
102104
}
103105

106+
/**
107+
* User metadata that can be attached to workflow commands.
108+
*
109+
* Current used for:
110+
* - startTimer, scheduleActivity/scheduleLocalActivity commands
111+
* - internal metadata query
112+
*/
113+
export interface UserMetadata {
114+
/** @experimental A single line summary of the command's purpose */
115+
summary?: string;
116+
/** @experimental Additional details about the command for longer-text description, can span multiple lines */
117+
details?: string;
118+
}
119+
120+
/**
121+
* Options that can be attached to workflow commands.
122+
*/
123+
export interface WorkflowCommandOptions {
124+
/** User metadata for the command that may be persisted to history */
125+
readonly userMetadata?: UserMetadata
126+
}
127+
104128
/** Input for WorkflowOutboundCallsInterceptor.startTimer */
105129
export interface TimerInput {
106130
readonly durationMs: number;
107131
readonly seq: number;
132+
readonly cmdOpts?: WorkflowCommandOptions;
108133
}
109134

110135
/**

packages/workflow/src/internals.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ export class Activator implements ActivationHandler {
313313
signalDefinitions,
314314
updateDefinitions,
315315
},
316+
currentDetails: this.currentDetails,
316317
};
317318
},
318319
description: 'Returns metadata associated with this workflow.',
@@ -416,6 +417,8 @@ export class Activator implements ActivationHandler {
416417

417418
public readonly registeredActivityNames: Set<string>;
418419

420+
public currentDetails: string = "";
421+
419422
constructor({
420423
info,
421424
now,

0 commit comments

Comments
 (0)