Skip to content

Commit d981c4c

Browse files
committed
initial API with nice docstrings
1 parent a564a3c commit d981c4c

4 files changed

Lines changed: 135 additions & 0 deletions

File tree

packages/common/src/converter/failure-converter.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { makeProtoEnumConverters } from '../internal-workflow';
2424
import { isError } from '../type-helpers';
2525
import { msOptionalToTs } from '../time';
2626
import { arrayFromPayloads, fromPayloadsAtIndex, PayloadConverter, toPayloads } from './payload-converter';
27+
import type { SerializationContext } from './serialization-context';
2728

2829
// Can't import proto enums into the workflow sandbox, use this helper type and enum converter instead.
2930
const NexusHandlerErrorRetryBehavior = {
@@ -108,6 +109,17 @@ export interface FailureConverter {
108109
* The returned error must be an instance of `TemporalFailure`.
109110
*/
110111
failureToError(err: ProtoFailure, payloadConverter: PayloadConverter): Error;
112+
113+
/**
114+
* Optionally return a converter bound to the current serialization context.
115+
*
116+
* The SDK may call this for individual failure conversion operations across
117+
* different workflows and activities. Implementations should treat this as
118+
* side-effect free and may return `this` when no rebinding is needed.
119+
*
120+
* @experimental Serialization context is an experimental feature and may change.
121+
*/
122+
withContext?(context: SerializationContext): FailureConverter;
111123
}
112124

113125
/**

packages/common/src/converter/payload-converter.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { decode, encode } from '../encoding';
22
import { PayloadConverterError, ValueError } from '../errors';
33
import { Payload } from '../interfaces';
4+
import type { SerializationContext } from './serialization-context';
45
import { encodingKeys, encodingTypes, METADATA_ENCODING_KEY } from './types';
56

67
/**
@@ -25,6 +26,17 @@ export interface PayloadConverter {
2526
* Converts a {@link Payload} back to a value.
2627
*/
2728
fromPayload<T>(payload: Payload): T;
29+
30+
/**
31+
* Optionally return a converter bound to the current serialization context.
32+
*
33+
* The SDK may call this for individual conversion operations across different
34+
* workflows and activities. Implementations should treat this as side-effect
35+
* free and may return `this` when no rebinding is needed.
36+
*
37+
* @experimental Serialization context is an experimental feature and may change.
38+
*/
39+
withContext?(context: SerializationContext): PayloadConverter;
2840
}
2941

3042
/**
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import type { LoadedDataConverter } from './data-converter';
2+
import type { FailureConverter } from './failure-converter';
3+
import type { PayloadConverter } from './payload-converter';
4+
5+
/**
6+
* Context for payloads owned by a workflow.
7+
*
8+
* This is used when converting payloads sent to or received from a workflow.
9+
* If a workflow interacts with a child workflow or an external workflow, this
10+
* context refers to that target workflow.
11+
*
12+
* @experimental Serialization context is an experimental feature and may change.
13+
*/
14+
export interface WorkflowSerializationContext {
15+
/** Always `'workflow'` for workflow-owned payloads. */
16+
type: 'workflow';
17+
/** Namespace of the workflow that owns the payload. */
18+
namespace: string;
19+
/** Workflow ID of the workflow that owns the payload. */
20+
workflowId: string;
21+
}
22+
23+
/**
24+
* Context for payloads owned by an activity.
25+
*
26+
* This is used when converting activity arguments, results, heartbeat details,
27+
* and activity-related failures.
28+
*
29+
* @experimental Serialization context is an experimental feature and may change.
30+
*/
31+
export interface ActivitySerializationContext {
32+
/** Always `'activity'` for activity-owned payloads. */
33+
type: 'activity';
34+
/** Namespace of the activity that owns the payload. */
35+
namespace: string;
36+
/**
37+
* Activity ID of the activity that owns the payload.
38+
*
39+
* This may be omitted when context is supplied manually and the caller does
40+
* not know the activity ID.
41+
*/
42+
activityId?: string;
43+
/** Workflow ID of the workflow that scheduled the activity, when known. */
44+
workflowId?: string;
45+
/** Whether the activity is a local activity started from a workflow. */
46+
isLocal: boolean;
47+
}
48+
49+
/**
50+
* Context passed to payload and failure converters.
51+
*
52+
* The context describes the workflow or activity whose payload is being converted.
53+
* For example:
54+
* - `client.workflow.start()` uses the target workflow's context.
55+
* - `executeChild()` uses the child workflow's context, not the parent's.
56+
* - `scheduleActivity()` uses the scheduled activity's context.
57+
*
58+
* @experimental Serialization context is an experimental feature and may change.
59+
*/
60+
export type SerializationContext = WorkflowSerializationContext | ActivitySerializationContext;
61+
62+
/**
63+
* Return a payload converter bound to `context` if the converter supports context binding.
64+
*/
65+
export function withPayloadConverterContext(
66+
converter: PayloadConverter,
67+
context: SerializationContext
68+
): PayloadConverter {
69+
return converter.withContext?.(context) ?? converter;
70+
}
71+
72+
/**
73+
* Return a failure converter bound to `context` if the converter supports context binding.
74+
*/
75+
export function withFailureConverterContext(
76+
converter: FailureConverter,
77+
context: SerializationContext
78+
): FailureConverter {
79+
return converter.withContext?.(context) ?? converter;
80+
}
81+
82+
/**
83+
* Return a loaded data converter with its payload and failure converters bound to `context`.
84+
*
85+
* Payload codecs are intentionally left unchanged in this PR and will be handled separately.
86+
*
87+
* Internal helper for non-workflow code paths. Workflow-isolate code should bind the individual
88+
* payload or failure converter directly to avoid pulling unnecessary code into the workflow bundle.
89+
*/
90+
export function withSerializationContext(
91+
converter: LoadedDataConverter,
92+
context: SerializationContext
93+
): LoadedDataConverter {
94+
const payloadConverter = withPayloadConverterContext(converter.payloadConverter, context);
95+
const failureConverter = withFailureConverterContext(converter.failureConverter, context);
96+
97+
if (payloadConverter === converter.payloadConverter && failureConverter === converter.failureConverter) {
98+
return converter;
99+
}
100+
101+
return {
102+
payloadConverter,
103+
failureConverter,
104+
payloadCodecs: converter.payloadCodecs,
105+
};
106+
}

packages/common/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ export * from './converter/data-converter';
1414
export * from './converter/failure-converter';
1515
export * from './converter/payload-codec';
1616
export * from './converter/payload-converter';
17+
export type {
18+
ActivitySerializationContext,
19+
SerializationContext,
20+
WorkflowSerializationContext,
21+
} from './converter/serialization-context';
1722
export * from './converter/types';
1823
export * from './deprecated-time';
1924
export * from './errors';

0 commit comments

Comments
 (0)