@temporalio/workflow 1.8.6 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/alea.js.map +1 -1
- package/lib/cancellation-scope.js.map +1 -1
- package/lib/errors.d.ts +8 -0
- package/lib/errors.js +18 -5
- package/lib/errors.js.map +1 -1
- package/lib/global-attributes.d.ts +4 -0
- package/lib/global-attributes.js +21 -1
- package/lib/global-attributes.js.map +1 -1
- package/lib/index.d.ts +19 -8
- package/lib/index.js +15 -8
- package/lib/index.js.map +1 -1
- package/lib/interceptors.d.ts +15 -0
- package/lib/interfaces.d.ts +47 -32
- package/lib/interfaces.js +4 -4
- package/lib/interfaces.js.map +1 -1
- package/lib/internals.d.ts +24 -13
- package/lib/internals.js +145 -41
- package/lib/internals.js.map +1 -1
- package/lib/logs.d.ts +50 -0
- package/lib/logs.js +84 -0
- package/lib/logs.js.map +1 -0
- package/lib/sinks.d.ts +29 -10
- package/lib/sinks.js +57 -0
- package/lib/sinks.js.map +1 -1
- package/lib/trigger.js.map +1 -1
- package/lib/worker-interface.d.ts +2 -2
- package/lib/worker-interface.js +34 -22
- package/lib/worker-interface.js.map +1 -1
- package/lib/workflow.d.ts +23 -54
- package/lib/workflow.js +156 -141
- package/lib/workflow.js.map +1 -1
- package/package.json +4 -4
- package/src/errors.ts +11 -0
- package/src/global-attributes.ts +21 -0
- package/src/index.ts +24 -8
- package/src/interceptors.ts +18 -0
- package/src/interfaces.ts +56 -36
- package/src/internals.ts +175 -37
- package/src/logs.ts +118 -0
- package/src/sinks.ts +60 -9
- package/src/worker-interface.ts +29 -16
- package/src/workflow.ts +150 -128
package/src/workflow.ts
CHANGED
|
@@ -12,10 +12,12 @@ import {
|
|
|
12
12
|
SignalDefinition,
|
|
13
13
|
toPayloads,
|
|
14
14
|
UntypedActivities,
|
|
15
|
+
UpdateDefinition,
|
|
15
16
|
WithWorkflowArgs,
|
|
16
17
|
Workflow,
|
|
17
18
|
WorkflowResultType,
|
|
18
19
|
WorkflowReturnType,
|
|
20
|
+
WorkflowUpdateValidatorType,
|
|
19
21
|
} from '@temporalio/common';
|
|
20
22
|
import { versioningIntentToProto } from '@temporalio/common/lib/versioning-intent-enum';
|
|
21
23
|
import { Duration, msOptionalToTs, msToNumber, msToTs, tsToMs } from '@temporalio/common/lib/time';
|
|
@@ -37,10 +39,11 @@ import {
|
|
|
37
39
|
DefaultSignalHandler,
|
|
38
40
|
EnhancedStackTrace,
|
|
39
41
|
Handler,
|
|
42
|
+
UpdateValidator,
|
|
40
43
|
WorkflowInfo,
|
|
41
44
|
} from './interfaces';
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
45
|
+
import { LocalActivityDoBackoff } from './errors';
|
|
46
|
+
import { assertInWorkflowContext, getActivator, maybeGetActivator } from './global-attributes';
|
|
44
47
|
import { untrackPromise } from './stack-helpers';
|
|
45
48
|
import { ChildWorkflowHandle, ExternalWorkflowHandle } from './workflow-handle';
|
|
46
49
|
|
|
@@ -165,7 +168,7 @@ function scheduleActivityNextHandler({ options, args, headers, seq, activityType
|
|
|
165
168
|
activityType,
|
|
166
169
|
arguments: toPayloads(activator.payloadConverter, ...args),
|
|
167
170
|
retryPolicy: options.retry ? compileRetryPolicy(options.retry) : undefined,
|
|
168
|
-
taskQueue: options.taskQueue || activator.info
|
|
171
|
+
taskQueue: options.taskQueue || activator.info.taskQueue,
|
|
169
172
|
heartbeatTimeout: msOptionalToTs(options.heartbeatTimeout),
|
|
170
173
|
scheduleToCloseTimeout: msOptionalToTs(options.scheduleToCloseTimeout),
|
|
171
174
|
startToCloseTimeout: msOptionalToTs(options.startToCloseTimeout),
|
|
@@ -198,7 +201,7 @@ async function scheduleLocalActivityNextHandler({
|
|
|
198
201
|
const activator = getActivator();
|
|
199
202
|
// Eagerly fail the local activity (which will in turn fail the workflow task.
|
|
200
203
|
// Do not fail on replay where the local activities may not be registered on the replay worker.
|
|
201
|
-
if (!
|
|
204
|
+
if (!activator.info.unsafe.isReplaying && !activator.registeredActivityNames.has(activityType)) {
|
|
202
205
|
throw new ReferenceError(`Local activity of type '${activityType}' not registered on worker`);
|
|
203
206
|
}
|
|
204
207
|
validateLocalActivityOptions(options);
|
|
@@ -358,11 +361,11 @@ function startChildWorkflowExecutionNextHandler({
|
|
|
358
361
|
workflowType,
|
|
359
362
|
input: toPayloads(activator.payloadConverter, ...options.args),
|
|
360
363
|
retryPolicy: options.retry ? compileRetryPolicy(options.retry) : undefined,
|
|
361
|
-
taskQueue: options.taskQueue || activator.info
|
|
364
|
+
taskQueue: options.taskQueue || activator.info.taskQueue,
|
|
362
365
|
workflowExecutionTimeout: msOptionalToTs(options.workflowExecutionTimeout),
|
|
363
366
|
workflowRunTimeout: msOptionalToTs(options.workflowRunTimeout),
|
|
364
367
|
workflowTaskTimeout: msOptionalToTs(options.workflowTaskTimeout),
|
|
365
|
-
namespace:
|
|
368
|
+
namespace: activator.info.namespace, // Not configurable
|
|
366
369
|
headers,
|
|
367
370
|
cancellationType: options.cancellationType,
|
|
368
371
|
workflowIdReusePolicy: options.workflowIdReusePolicy,
|
|
@@ -830,9 +833,11 @@ export async function executeChild<T extends Workflow>(
|
|
|
830
833
|
/**
|
|
831
834
|
* Get information about the current Workflow.
|
|
832
835
|
*
|
|
833
|
-
*
|
|
834
|
-
*
|
|
835
|
-
*
|
|
836
|
+
* WARNING: This function returns a frozen copy of WorkflowInfo, at the point where this method has been called.
|
|
837
|
+
* Changes happening at later point in workflow execution will not be reflected in the returned object.
|
|
838
|
+
*
|
|
839
|
+
* For this reason, we recommend calling `workflowInfo()` on every access to {@link WorkflowInfo}'s fields,
|
|
840
|
+
* rather than caching the `WorkflowInfo` object (or part of it) in a local variable. For example:
|
|
836
841
|
*
|
|
837
842
|
* ```ts
|
|
838
843
|
* // GOOD
|
|
@@ -843,6 +848,8 @@ export async function executeChild<T extends Workflow>(
|
|
|
843
848
|
* }
|
|
844
849
|
* ```
|
|
845
850
|
*
|
|
851
|
+
* vs
|
|
852
|
+
*
|
|
846
853
|
* ```ts
|
|
847
854
|
* // BAD
|
|
848
855
|
* function myWorkflow() {
|
|
@@ -851,6 +858,7 @@ export async function executeChild<T extends Workflow>(
|
|
|
851
858
|
* ...
|
|
852
859
|
* doSomethingElse(attributes)
|
|
853
860
|
* }
|
|
861
|
+
* ```
|
|
854
862
|
*/
|
|
855
863
|
export function workflowInfo(): WorkflowInfo {
|
|
856
864
|
const activator = assertInWorkflowContext('Workflow.workflowInfo(...) may only be used from a Workflow Execution.');
|
|
@@ -864,72 +872,6 @@ export function inWorkflowContext(): boolean {
|
|
|
864
872
|
return maybeGetActivator() !== undefined;
|
|
865
873
|
}
|
|
866
874
|
|
|
867
|
-
/**
|
|
868
|
-
* Get a reference to Sinks for exporting data out of the Workflow.
|
|
869
|
-
*
|
|
870
|
-
* These Sinks **must** be registered with the Worker in order for this
|
|
871
|
-
* mechanism to work.
|
|
872
|
-
*
|
|
873
|
-
* @example
|
|
874
|
-
* ```ts
|
|
875
|
-
* import { proxySinks, Sinks } from '@temporalio/workflow';
|
|
876
|
-
*
|
|
877
|
-
* interface MySinks extends Sinks {
|
|
878
|
-
* logger: {
|
|
879
|
-
* info(message: string): void;
|
|
880
|
-
* error(message: string): void;
|
|
881
|
-
* };
|
|
882
|
-
* }
|
|
883
|
-
*
|
|
884
|
-
* const { logger } = proxySinks<MyDependencies>();
|
|
885
|
-
* logger.info('setting up');
|
|
886
|
-
*
|
|
887
|
-
* export function myWorkflow() {
|
|
888
|
-
* return {
|
|
889
|
-
* async execute() {
|
|
890
|
-
* logger.info("hey ho");
|
|
891
|
-
* logger.error("lets go");
|
|
892
|
-
* }
|
|
893
|
-
* };
|
|
894
|
-
* }
|
|
895
|
-
* ```
|
|
896
|
-
*/
|
|
897
|
-
export function proxySinks<T extends Sinks>(): T {
|
|
898
|
-
return new Proxy(
|
|
899
|
-
{},
|
|
900
|
-
{
|
|
901
|
-
get(_, ifaceName) {
|
|
902
|
-
return new Proxy(
|
|
903
|
-
{},
|
|
904
|
-
{
|
|
905
|
-
get(_, fnName) {
|
|
906
|
-
return (...args: any[]) => {
|
|
907
|
-
const activator = assertInWorkflowContext(
|
|
908
|
-
'Proxied sinks functions may only be used from a Workflow Execution.'
|
|
909
|
-
);
|
|
910
|
-
const info = workflowInfo();
|
|
911
|
-
activator.sinkCalls.push({
|
|
912
|
-
ifaceName: ifaceName as string,
|
|
913
|
-
fnName: fnName as string,
|
|
914
|
-
// Only available from node 17.
|
|
915
|
-
args: (globalThis as any).structuredClone ? (globalThis as any).structuredClone(args) : args,
|
|
916
|
-
// Clone the workflowInfo object so that any further mutations to it does not get reflected in sink
|
|
917
|
-
workflowInfo: {
|
|
918
|
-
...info,
|
|
919
|
-
// Make sure to clone any sub-property that may get mutated during the lifespan of an activation
|
|
920
|
-
searchAttributes: { ...info.searchAttributes },
|
|
921
|
-
memo: info.memo ? { ...info.memo } : undefined,
|
|
922
|
-
},
|
|
923
|
-
});
|
|
924
|
-
};
|
|
925
|
-
},
|
|
926
|
-
}
|
|
927
|
-
);
|
|
928
|
-
},
|
|
929
|
-
}
|
|
930
|
-
) as any;
|
|
931
|
-
}
|
|
932
|
-
|
|
933
875
|
/**
|
|
934
876
|
* Returns a function `f` that will cause the current Workflow to ContinueAsNew when called.
|
|
935
877
|
*
|
|
@@ -1149,6 +1091,21 @@ function conditionInner(fn: () => boolean): Promise<void> {
|
|
|
1149
1091
|
});
|
|
1150
1092
|
}
|
|
1151
1093
|
|
|
1094
|
+
/**
|
|
1095
|
+
* Define an update method for a Workflow.
|
|
1096
|
+
*
|
|
1097
|
+
* Definitions are used to register handler in the Workflow via {@link setHandler} and to update Workflows using a {@link WorkflowHandle}, {@link ChildWorkflowHandle} or {@link ExternalWorkflowHandle}.
|
|
1098
|
+
* Definitions can be reused in multiple Workflows.
|
|
1099
|
+
*/
|
|
1100
|
+
export function defineUpdate<Ret, Args extends any[] = [], Name extends string = string>(
|
|
1101
|
+
name: Name
|
|
1102
|
+
): UpdateDefinition<Ret, Args, Name> {
|
|
1103
|
+
return {
|
|
1104
|
+
type: 'update',
|
|
1105
|
+
name,
|
|
1106
|
+
} as UpdateDefinition<Ret, Args, Name>;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1152
1109
|
/**
|
|
1153
1110
|
* Define a signal method for a Workflow.
|
|
1154
1111
|
*
|
|
@@ -1180,19 +1137,122 @@ export function defineQuery<Ret, Args extends any[] = [], Name extends string =
|
|
|
1180
1137
|
}
|
|
1181
1138
|
|
|
1182
1139
|
/**
|
|
1183
|
-
* Set a handler function for a Workflow
|
|
1140
|
+
* Set a handler function for a Workflow update, signal, or query.
|
|
1184
1141
|
*
|
|
1185
|
-
* If this function is called multiple times for a given signal or query name the last handler will overwrite any previous calls.
|
|
1142
|
+
* If this function is called multiple times for a given update, signal, or query name the last handler will overwrite any previous calls.
|
|
1186
1143
|
*
|
|
1187
|
-
* @param def
|
|
1144
|
+
* @param def an {@link UpdateDefinition}, {@link SignalDefinition}, or {@link QueryDefinition} as returned by {@link defineUpdate}, {@link defineSignal}, or {@link defineQuery} respectively.
|
|
1188
1145
|
* @param handler a compatible handler function for the given definition or `undefined` to unset the handler.
|
|
1189
1146
|
*/
|
|
1190
1147
|
export function setHandler<Ret, Args extends any[], T extends SignalDefinition<Args> | QueryDefinition<Ret, Args>>(
|
|
1191
1148
|
def: T,
|
|
1192
1149
|
handler: Handler<Ret, Args, T> | undefined
|
|
1193
|
-
): void
|
|
1150
|
+
): void;
|
|
1151
|
+
export function setHandler<Ret, Args extends any[], T extends UpdateDefinition<Ret, Args>>(
|
|
1152
|
+
def: T,
|
|
1153
|
+
handler: Handler<Ret, Args, T> | undefined,
|
|
1154
|
+
options?: { validator: UpdateValidator<Args> }
|
|
1155
|
+
): void;
|
|
1156
|
+
|
|
1157
|
+
// For Updates and Signals we want to make a public guarantee something like the
|
|
1158
|
+
// following:
|
|
1159
|
+
//
|
|
1160
|
+
// "If a WFT contains a Signal/Update, and if a handler is available for that
|
|
1161
|
+
// Signal/Update, then the handler will be executed.""
|
|
1162
|
+
//
|
|
1163
|
+
// However, that statement is not well-defined, leaving several questions open:
|
|
1164
|
+
//
|
|
1165
|
+
// 1. What does it mean for a handler to be "available"? What happens if the
|
|
1166
|
+
// handler is not present initially but is set at some point during the
|
|
1167
|
+
// Workflow code that is executed in that WFT? What happens if the handler is
|
|
1168
|
+
// set and then deleted, or replaced with a different handler?
|
|
1169
|
+
//
|
|
1170
|
+
// 2. When is the handler executed? (When it first becomes available? At the end
|
|
1171
|
+
// of the activation?) What are the execution semantics of Workflow and
|
|
1172
|
+
// Signal/Update handler code given that they are concurrent? Can the user
|
|
1173
|
+
// rely on Signal/Update side effects being reflected in the Workflow return
|
|
1174
|
+
// value, or in the value passed to Continue-As-New? If the handler is an
|
|
1175
|
+
// async function / coroutine, how much of it is executed and when is the
|
|
1176
|
+
// rest executed?
|
|
1177
|
+
//
|
|
1178
|
+
// 3. What happens if the handler is not executed? (i.e. because it wasn't
|
|
1179
|
+
// available in the sense defined by (1))
|
|
1180
|
+
//
|
|
1181
|
+
// 4. In the case of Update, when is the validation function executed?
|
|
1182
|
+
//
|
|
1183
|
+
// The implementation for Typescript is as follows:
|
|
1184
|
+
//
|
|
1185
|
+
// 1. sdk-core sorts Signal and Update jobs (and Patches) ahead of all other
|
|
1186
|
+
// jobs. Thus if the handler is available at the start of the Activation then
|
|
1187
|
+
// the Signal/Update will be executed before Workflow code is executed. If it
|
|
1188
|
+
// is not, then the Signal/Update calls is pushed to a buffer.
|
|
1189
|
+
//
|
|
1190
|
+
// 2. On each call to setHandler for a given Signal/Update, we make a pass
|
|
1191
|
+
// through the buffer list. If a buffered job is associated with the just-set
|
|
1192
|
+
// handler, then the job is removed from the buffer and the initial
|
|
1193
|
+
// synchronous portion of the handler is invoked on that input (i.e.
|
|
1194
|
+
// preempting workflow code).
|
|
1195
|
+
//
|
|
1196
|
+
// Thus in the case of Typescript the questions above are answered as follows:
|
|
1197
|
+
//
|
|
1198
|
+
// 1. A handler is "available" if it is set at the start of the Activation or
|
|
1199
|
+
// becomes set at any point during the Activation. If the handler is not set
|
|
1200
|
+
// initially then it is executed as soon as it is set. Subsequent deletion or
|
|
1201
|
+
// replacement by a different handler has no impact because the jobs it was
|
|
1202
|
+
// handling have already been handled and are no longer in the buffer.
|
|
1203
|
+
//
|
|
1204
|
+
// 2. The handler is executed as soon as it becomes available. I.e. if the
|
|
1205
|
+
// handler is set at the start of the Activation then it is executed when
|
|
1206
|
+
// first attempting to process the Signal/Update job; alternatively, if it is
|
|
1207
|
+
// set by a setHandler call made by Workflow code, then it is executed as
|
|
1208
|
+
// part of that call (preempting Workflow code). Therefore, a user can rely
|
|
1209
|
+
// on Signal/Update side effects being reflected in e.g. the Workflow return
|
|
1210
|
+
// value, and in the value passed to Continue-As-New. Activation jobs are
|
|
1211
|
+
// processed in the order supplied by sdk-core, i.e. Signals, then Updates,
|
|
1212
|
+
// then other jobs. Within each group, the order sent by the server is
|
|
1213
|
+
// preserved. If the handler is async, it is executed up to its first yield
|
|
1214
|
+
// point.
|
|
1215
|
+
//
|
|
1216
|
+
// 3. Signal case: If a handler does not become available for a Signal job then
|
|
1217
|
+
// the job remains in the buffer. If a handler for the Signal becomes
|
|
1218
|
+
// available in a subsequent Activation (of the same or a subsequent WFT)
|
|
1219
|
+
// then the handler will be executed. If not, then the Signal will never be
|
|
1220
|
+
// responded to and this causes no error.
|
|
1221
|
+
//
|
|
1222
|
+
// Update case: If a handler does not become available for an Update job then
|
|
1223
|
+
// the Update is rejected at the end of the Activation. Thus, if a user does
|
|
1224
|
+
// not want an Update to be rejected for this reason, then it is their
|
|
1225
|
+
// responsibility to ensure that their application and workflow code interact
|
|
1226
|
+
// such that a handler is available for the Update during any Activation
|
|
1227
|
+
// which might contain their Update job. (Note that the user often has
|
|
1228
|
+
// uncertainty about which WFT their Signal/Update will appear in. For
|
|
1229
|
+
// example, if they call startWorkflow() followed by startUpdate(), then they
|
|
1230
|
+
// will typically not know whether these will be delivered in one or two
|
|
1231
|
+
// WFTs. On the other hand there are situations where they would have reason
|
|
1232
|
+
// to believe they are in the same WFT, for example if they do not start
|
|
1233
|
+
// Worker polling until after they have verified that both requests have
|
|
1234
|
+
// succeeded.)
|
|
1235
|
+
//
|
|
1236
|
+
// 5. If an Update has a validation function then it is executed immediately
|
|
1237
|
+
// prior to the handler. (Note that the validation function is required to be
|
|
1238
|
+
// synchronous).
|
|
1239
|
+
export function setHandler<
|
|
1240
|
+
Ret,
|
|
1241
|
+
Args extends any[],
|
|
1242
|
+
T extends UpdateDefinition<Ret, Args> | SignalDefinition<Args> | QueryDefinition<Ret, Args>,
|
|
1243
|
+
>(def: T, handler: Handler<Ret, Args, T> | undefined, options?: { validator: UpdateValidator<Args> }): void {
|
|
1194
1244
|
const activator = assertInWorkflowContext('Workflow.setHandler(...) may only be used from a Workflow Execution.');
|
|
1195
|
-
if (def.type === '
|
|
1245
|
+
if (def.type === 'update') {
|
|
1246
|
+
if (typeof handler === 'function') {
|
|
1247
|
+
const validator = options?.validator as WorkflowUpdateValidatorType | undefined;
|
|
1248
|
+
activator.updateHandlers.set(def.name, { handler, validator });
|
|
1249
|
+
activator.dispatchBufferedUpdates();
|
|
1250
|
+
} else if (handler == null) {
|
|
1251
|
+
activator.updateHandlers.delete(def.name);
|
|
1252
|
+
} else {
|
|
1253
|
+
throw new TypeError(`Expected handler to be either a function or 'undefined'. Got: '${typeof handler}'`);
|
|
1254
|
+
}
|
|
1255
|
+
} else if (def.type === 'signal') {
|
|
1196
1256
|
if (typeof handler === 'function') {
|
|
1197
1257
|
activator.signalHandlers.set(def.name, handler as any);
|
|
1198
1258
|
activator.dispatchBufferedSignals();
|
|
@@ -1271,8 +1331,7 @@ export function upsertSearchAttributes(searchAttributes: SearchAttributes): void
|
|
|
1271
1331
|
'Workflow.upsertSearchAttributes(...) may only be used from a Workflow Execution.'
|
|
1272
1332
|
);
|
|
1273
1333
|
|
|
1274
|
-
|
|
1275
|
-
if (!mergedSearchAttributes) {
|
|
1334
|
+
if (searchAttributes == null) {
|
|
1276
1335
|
throw new Error('searchAttributes must be a non-null SearchAttributes');
|
|
1277
1336
|
}
|
|
1278
1337
|
|
|
@@ -1282,53 +1341,16 @@ export function upsertSearchAttributes(searchAttributes: SearchAttributes): void
|
|
|
1282
1341
|
},
|
|
1283
1342
|
});
|
|
1284
1343
|
|
|
1285
|
-
activator.info
|
|
1344
|
+
activator.mutateWorkflowInfo((info: WorkflowInfo): WorkflowInfo => {
|
|
1345
|
+
return {
|
|
1346
|
+
...info,
|
|
1347
|
+
searchAttributes: {
|
|
1348
|
+
...info.searchAttributes,
|
|
1349
|
+
...searchAttributes,
|
|
1350
|
+
},
|
|
1351
|
+
};
|
|
1352
|
+
});
|
|
1286
1353
|
}
|
|
1287
1354
|
|
|
1288
1355
|
export const stackTraceQuery = defineQuery<string>('__stack_trace');
|
|
1289
1356
|
export const enhancedStackTraceQuery = defineQuery<EnhancedStackTrace>('__enhanced_stack_trace');
|
|
1290
|
-
|
|
1291
|
-
const loggerSinks = proxySinks<LoggerSinks>();
|
|
1292
|
-
|
|
1293
|
-
/**
|
|
1294
|
-
* Symbol used by the SDK logger to extract a timestamp from log attributes.
|
|
1295
|
-
* Also defined in `worker/logger.ts` - intentionally not shared.
|
|
1296
|
-
*/
|
|
1297
|
-
const LogTimestamp = Symbol.for('log_timestamp');
|
|
1298
|
-
|
|
1299
|
-
/**
|
|
1300
|
-
* Default workflow logger.
|
|
1301
|
-
* This logger is replay-aware and will omit log messages on workflow replay.
|
|
1302
|
-
* The messages emitted by this logger are funnelled to the worker's `defaultSinks`, which are installed by default.
|
|
1303
|
-
*
|
|
1304
|
-
* Note that since sinks are used to power this logger, any log attributes must be transferable via the
|
|
1305
|
-
* {@link https://nodejs.org/api/worker_threads.html#worker_threads_port_postmessage_value_transferlist | postMessage}
|
|
1306
|
-
* API.
|
|
1307
|
-
*
|
|
1308
|
-
* `defaultSinks` accepts a user logger and defaults to the `Runtime`'s logger.
|
|
1309
|
-
*
|
|
1310
|
-
* See the documentation for `WorkerOptions`, `defaultSinks`, and `Runtime` for more information.
|
|
1311
|
-
*/
|
|
1312
|
-
export const log: LoggerSinks['defaultWorkerLogger'] = Object.fromEntries(
|
|
1313
|
-
(['trace', 'debug', 'info', 'warn', 'error'] as Array<keyof LoggerSinks['defaultWorkerLogger']>).map((level) => {
|
|
1314
|
-
return [
|
|
1315
|
-
level,
|
|
1316
|
-
(message: string, attrs?: Record<string, unknown>) => {
|
|
1317
|
-
const activator = assertInWorkflowContext('Workflow.log(...) may only be used from a Workflow Execution.');
|
|
1318
|
-
const getLogAttributes = composeInterceptors(activator.interceptors.outbound, 'getLogAttributes', (a) => a);
|
|
1319
|
-
return loggerSinks.defaultWorkerLogger[level](message, {
|
|
1320
|
-
// Inject the call time in nanosecond resolution as expected by the worker logger.
|
|
1321
|
-
[LogTimestamp]: activator.getTimeOfDay(),
|
|
1322
|
-
...getLogAttributes({}),
|
|
1323
|
-
...attrs,
|
|
1324
|
-
});
|
|
1325
|
-
},
|
|
1326
|
-
];
|
|
1327
|
-
})
|
|
1328
|
-
) as any;
|
|
1329
|
-
|
|
1330
|
-
function assertInWorkflowContext(message: string): Activator {
|
|
1331
|
-
const activator = maybeGetActivator();
|
|
1332
|
-
if (activator == null) throw new IllegalStateError(message);
|
|
1333
|
-
return activator;
|
|
1334
|
-
}
|