@temporalio/client 1.4.4 → 1.5.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.
Files changed (57) hide show
  1. package/lib/async-completion-client.d.ts +5 -32
  2. package/lib/async-completion-client.js +6 -20
  3. package/lib/async-completion-client.js.map +1 -1
  4. package/lib/base-client.d.ts +53 -0
  5. package/lib/base-client.js +45 -0
  6. package/lib/base-client.js.map +1 -0
  7. package/lib/client.d.ts +12 -52
  8. package/lib/client.js +30 -49
  9. package/lib/client.js.map +1 -1
  10. package/lib/connection.d.ts +9 -9
  11. package/lib/connection.js +4 -3
  12. package/lib/connection.js.map +1 -1
  13. package/lib/errors.d.ts +0 -1
  14. package/lib/errors.js +1 -3
  15. package/lib/errors.js.map +1 -1
  16. package/lib/helpers.d.ts +3 -0
  17. package/lib/helpers.js +63 -0
  18. package/lib/helpers.js.map +1 -0
  19. package/lib/index.d.ts +2 -0
  20. package/lib/index.js +2 -0
  21. package/lib/index.js.map +1 -1
  22. package/lib/interceptors.d.ts +46 -10
  23. package/lib/iterators-utils.d.ts +31 -0
  24. package/lib/iterators-utils.js +80 -0
  25. package/lib/iterators-utils.js.map +1 -0
  26. package/lib/schedule-client.d.ts +175 -0
  27. package/lib/schedule-client.js +383 -0
  28. package/lib/schedule-client.js.map +1 -0
  29. package/lib/schedule-helpers.d.ts +20 -0
  30. package/lib/schedule-helpers.js +290 -0
  31. package/lib/schedule-helpers.js.map +1 -0
  32. package/lib/schedule-types.d.ts +691 -0
  33. package/lib/schedule-types.js +74 -0
  34. package/lib/schedule-types.js.map +1 -0
  35. package/lib/types.d.ts +8 -3
  36. package/lib/types.js.map +1 -1
  37. package/lib/workflow-client.d.ts +76 -59
  38. package/lib/workflow-client.js +87 -101
  39. package/lib/workflow-client.js.map +1 -1
  40. package/lib/workflow-options.d.ts +5 -1
  41. package/lib/workflow-options.js.map +1 -1
  42. package/package.json +7 -5
  43. package/src/async-completion-client.ts +16 -55
  44. package/src/base-client.ts +84 -0
  45. package/src/client.ts +41 -93
  46. package/src/connection.ts +12 -11
  47. package/src/errors.ts +0 -1
  48. package/src/helpers.ts +75 -0
  49. package/src/index.ts +2 -0
  50. package/src/interceptors.ts +54 -10
  51. package/src/iterators-utils.ts +116 -0
  52. package/src/schedule-client.ts +541 -0
  53. package/src/schedule-helpers.ts +414 -0
  54. package/src/schedule-types.ts +866 -0
  55. package/src/types.ts +12 -3
  56. package/src/workflow-client.ts +178 -180
  57. package/src/workflow-options.ts +12 -1
@@ -0,0 +1,541 @@
1
+ import { status as grpcStatus } from '@grpc/grpc-js';
2
+ import { v4 as uuid4 } from 'uuid';
3
+ import { mapToPayloads, searchAttributePayloadConverter } from '@temporalio/common';
4
+ import { composeInterceptors, Headers } from '@temporalio/common/lib/interceptors';
5
+ import {
6
+ encodeMapToPayloads,
7
+ decodeMapFromPayloads,
8
+ filterNullAndUndefined,
9
+ } from '@temporalio/common/lib/internal-non-workflow';
10
+ import { temporal } from '@temporalio/proto';
11
+ import { optionalDateToTs, optionalTsToDate, optionalTsToMs, tsToDate } from '@temporalio/common/lib/time';
12
+ import { CreateScheduleInput, CreateScheduleOutput, ScheduleClientInterceptor } from './interceptors';
13
+ import { WorkflowService } from './types';
14
+ import { isServerErrorResponse, ServiceError } from './errors';
15
+ import {
16
+ Backfill,
17
+ CompiledScheduleUpdateOptions,
18
+ ScheduleSummary,
19
+ ScheduleDescription,
20
+ ScheduleOptions,
21
+ ScheduleOverlapPolicy,
22
+ ScheduleUpdateOptions,
23
+ } from './schedule-types';
24
+ import {
25
+ compileScheduleOptions,
26
+ compileUpdatedScheduleOptions,
27
+ decodeOverlapPolicy,
28
+ decodeScheduleAction,
29
+ decodeScheduleRecentActions,
30
+ decodeScheduleRunningActions,
31
+ decodeScheduleSpec,
32
+ decodeSearchAttributes,
33
+ encodeOverlapPolicy,
34
+ encodeScheduleAction,
35
+ encodeSchedulePolicies,
36
+ encodeScheduleSpec,
37
+ encodeScheduleState,
38
+ } from './schedule-helpers';
39
+ import {
40
+ BaseClient,
41
+ BaseClientOptions,
42
+ defaultBaseClientOptions,
43
+ LoadedWithDefaults,
44
+ WithDefaults,
45
+ } from './base-client';
46
+
47
+ /**
48
+ * Handle to a single Schedule
49
+ *
50
+ * @experimental
51
+ */
52
+ export interface ScheduleHandle {
53
+ /**
54
+ * This Schedule's identifier
55
+ */
56
+ readonly scheduleId: string;
57
+
58
+ /**
59
+ * Fetch the Schedule's description from the Server
60
+ */
61
+ describe(): Promise<ScheduleDescription>;
62
+
63
+ /**
64
+ * Update the Schedule
65
+ *
66
+ * This function calls `.describe()`, provides the `Schedule` to the provided `updateFn`, and
67
+ * sends the returned `UpdatedSchedule` to the Server to update the Schedule definition. Note that,
68
+ * in the future, `updateFn` might be invoked multiple time, with identical or different input.
69
+ */
70
+ update(updateFn: (previous: ScheduleDescription) => ScheduleUpdateOptions): Promise<void>;
71
+
72
+ /**
73
+ * Delete the Schedule
74
+ */
75
+ delete(): Promise<void>;
76
+
77
+ /**
78
+ * Trigger an Action to be taken immediately
79
+ *
80
+ * @param overlap Override the Overlap Policy for this one trigger. Defaults to {@link ScheduleOverlapPolicy.ALLOW_ALL}.
81
+ */
82
+ trigger(overlap?: ScheduleOverlapPolicy): Promise<void>;
83
+
84
+ /**
85
+ * Run though the specified time period(s) and take Actions as if that time passed by right now, all at once.
86
+ * The Overlap Policy can be overridden for the scope of the Backfill.
87
+ */
88
+ backfill(options: Backfill | Backfill[]): Promise<void>;
89
+
90
+ /**
91
+ * Pause the Schedule
92
+ *
93
+ * @param note A new {@link ScheduleDescription.note}. Defaults to `"Paused via TypeScript SDK"`
94
+ */
95
+ pause(note?: string): Promise<void>;
96
+
97
+ /**
98
+ * Unpause the Schedule
99
+ *
100
+ * @param note A new {@link ScheduleDescription.note}. Defaults to `"Unpaused via TypeScript SDK"
101
+ */
102
+ unpause(note?: string): Promise<void>;
103
+
104
+ /**
105
+ * Readonly accessor to the underlying ScheduleClient
106
+ */
107
+ readonly client: ScheduleClient;
108
+ }
109
+
110
+ /**
111
+ * @experimental
112
+ */
113
+ export interface ScheduleClientOptions extends BaseClientOptions {
114
+ /**
115
+ * Used to override and extend default Connection functionality
116
+ *
117
+ * Useful for injecting auth headers and tracing Workflow executions
118
+ */
119
+ interceptors?: ScheduleClientInterceptor[];
120
+ }
121
+
122
+ /** @experimental */
123
+ export type LoadedScheduleClientOptions = LoadedWithDefaults<ScheduleClientOptions>;
124
+
125
+ function defaultScheduleClientOptions(): WithDefaults<ScheduleClientOptions> {
126
+ return {
127
+ ...defaultBaseClientOptions(),
128
+ interceptors: [],
129
+ };
130
+ }
131
+
132
+ function assertRequiredScheduleOptions(opts: ScheduleOptions, action: 'CREATE'): void;
133
+ function assertRequiredScheduleOptions(opts: ScheduleUpdateOptions, action: 'UPDATE'): void;
134
+ function assertRequiredScheduleOptions(
135
+ opts: ScheduleOptions | ScheduleUpdateOptions,
136
+ action: 'CREATE' | 'UPDATE'
137
+ ): void {
138
+ const structureName = action === 'CREATE' ? 'ScheduleOptions' : 'ScheduleUpdateOptions';
139
+ if (action === 'CREATE' && !(opts as ScheduleOptions).scheduleId) {
140
+ throw new TypeError(`Missing ${structureName}.scheduleId`);
141
+ }
142
+ if (!(opts.spec.calendars?.length || opts.spec.intervals?.length || opts.spec.cronExpressions?.length)) {
143
+ throw new TypeError(`At least one ${structureName}.spec.calendars, .intervals or .cronExpressions is required`);
144
+ }
145
+ switch (opts.action.type) {
146
+ case 'startWorkflow':
147
+ if (!opts.action.taskQueue) {
148
+ throw new TypeError(`Missing ${structureName}.action.taskQueue for 'startWorkflow' action`);
149
+ }
150
+ if (!opts.action.workflowId && action === 'UPDATE') {
151
+ throw new TypeError(`Missing ${structureName}.action.workflowId for 'startWorkflow' action`);
152
+ }
153
+ if (!opts.action.workflowType) {
154
+ throw new TypeError(`Missing ${structureName}.action.workflowType for 'startWorkflow' action`);
155
+ }
156
+ }
157
+ }
158
+
159
+ /** @experimental */
160
+ export interface ListScheduleOptions {
161
+ /**
162
+ * How many results to fetch from the Server at a time.
163
+ * @default 1000
164
+ */
165
+ pageSize?: number;
166
+ }
167
+
168
+ /**
169
+ * Client for starting Workflow executions and creating Workflow handles
170
+ *
171
+ * @experimental
172
+ */
173
+ export class ScheduleClient extends BaseClient {
174
+ public readonly options: LoadedScheduleClientOptions;
175
+
176
+ constructor(options?: ScheduleClientOptions) {
177
+ super(options);
178
+ this.options = {
179
+ ...defaultScheduleClientOptions(),
180
+ ...filterNullAndUndefined(options ?? {}),
181
+ loadedDataConverter: this.dataConverter,
182
+ };
183
+ }
184
+
185
+ /**
186
+ * Raw gRPC access to the Temporal service. Schedule-related methods are included in {@link WorkflowService}.
187
+ *
188
+ * **NOTE**: The namespace provided in {@link options} is **not** automatically set on requests made to the service.
189
+ */
190
+ get workflowService(): WorkflowService {
191
+ return this.connection.workflowService;
192
+ }
193
+
194
+ /**
195
+ * Create a new Schedule.
196
+ *
197
+ * @throws {@link ScheduleAlreadyRunning} if there's a running (not deleted) Schedule with the given `id`
198
+ * @returns a ScheduleHandle to the created Schedule
199
+ */
200
+ public async create(options: ScheduleOptions): Promise<ScheduleHandle> {
201
+ await this._createSchedule(options);
202
+ return this.getHandle(options.scheduleId);
203
+ }
204
+
205
+ /**
206
+ * Create a new Schedule.
207
+ */
208
+ protected async _createSchedule(options: ScheduleOptions): Promise<void> {
209
+ assertRequiredScheduleOptions(options, 'CREATE');
210
+ const compiledOptions = compileScheduleOptions(options);
211
+
212
+ const create = composeInterceptors(this.options.interceptors, 'create', this._createScheduleHandler.bind(this));
213
+ await create({
214
+ options: compiledOptions,
215
+ headers: {},
216
+ });
217
+ }
218
+
219
+ /**
220
+ * Create a new Schedule.
221
+ */
222
+ protected async _createScheduleHandler(input: CreateScheduleInput): Promise<CreateScheduleOutput> {
223
+ const { options: opts, headers } = input;
224
+ const { identity } = this.options;
225
+ const req: temporal.api.workflowservice.v1.ICreateScheduleRequest = {
226
+ namespace: this.options.namespace,
227
+ identity,
228
+ requestId: uuid4(),
229
+ scheduleId: opts.scheduleId,
230
+ schedule: {
231
+ spec: encodeScheduleSpec(opts.spec),
232
+ action: await encodeScheduleAction(this.dataConverter, opts.action, headers),
233
+ policies: encodeSchedulePolicies(opts.policies),
234
+ state: encodeScheduleState(opts.state),
235
+ },
236
+ memo: opts.memo ? { fields: await encodeMapToPayloads(this.dataConverter, opts.memo) } : undefined,
237
+ searchAttributes: opts.searchAttributes
238
+ ? {
239
+ indexedFields: mapToPayloads(searchAttributePayloadConverter, opts.searchAttributes),
240
+ }
241
+ : undefined,
242
+ initialPatch: {
243
+ triggerImmediately: opts.state?.triggerImmediately
244
+ ? { overlapPolicy: temporal.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_ALLOW_ALL }
245
+ : undefined,
246
+ backfillRequest: opts.state?.backfill
247
+ ? opts.state.backfill.map((x) => ({
248
+ startTime: optionalDateToTs(x.start),
249
+ endTime: optionalDateToTs(x.end),
250
+ overlapPolicy: x.overlap ? encodeOverlapPolicy(x.overlap) : undefined,
251
+ }))
252
+ : undefined,
253
+ },
254
+ };
255
+ try {
256
+ const res = await this.workflowService.createSchedule(req);
257
+ return { conflictToken: res.conflictToken };
258
+ } catch (err: any) {
259
+ if (err.code === grpcStatus.ALREADY_EXISTS) {
260
+ throw new ScheduleAlreadyRunning('Schedule already exists and is running', opts.scheduleId);
261
+ }
262
+ this.rethrowGrpcError(err, opts.scheduleId, 'Failed to create schedule');
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Describe a Schedule.
268
+ */
269
+ protected async _describeSchedule(
270
+ scheduleId: string
271
+ ): Promise<temporal.api.workflowservice.v1.IDescribeScheduleResponse> {
272
+ try {
273
+ return await this.workflowService.describeSchedule({
274
+ namespace: this.options.namespace,
275
+ scheduleId,
276
+ });
277
+ } catch (err: any) {
278
+ this.rethrowGrpcError(err, scheduleId, 'Failed to describe schedule');
279
+ }
280
+ }
281
+
282
+ /**
283
+ * Update a Schedule.
284
+ */
285
+ protected async _updateSchedule(
286
+ scheduleId: string,
287
+ opts: CompiledScheduleUpdateOptions,
288
+ header: Headers
289
+ ): Promise<temporal.api.workflowservice.v1.IUpdateScheduleResponse> {
290
+ try {
291
+ return await this.workflowService.updateSchedule({
292
+ namespace: this.options.namespace,
293
+ scheduleId,
294
+ schedule: {
295
+ spec: encodeScheduleSpec(opts.spec),
296
+ action: await encodeScheduleAction(this.dataConverter, opts.action, header),
297
+ policies: encodeSchedulePolicies(opts.policies),
298
+ state: encodeScheduleState(opts.state),
299
+ },
300
+ identity: this.options.identity,
301
+ requestId: uuid4(),
302
+ });
303
+ } catch (err: any) {
304
+ this.rethrowGrpcError(err, scheduleId, 'Failed to update schedule');
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Patch a Schedule.
310
+ */
311
+ protected async _patchSchedule(
312
+ scheduleId: string,
313
+ patch: temporal.api.schedule.v1.ISchedulePatch
314
+ ): Promise<temporal.api.workflowservice.v1.IPatchScheduleResponse> {
315
+ try {
316
+ return await this.workflowService.patchSchedule({
317
+ namespace: this.options.namespace,
318
+ scheduleId,
319
+ identity: this.options.identity,
320
+ requestId: uuid4(),
321
+ patch,
322
+ });
323
+ } catch (err: any) {
324
+ this.rethrowGrpcError(err, scheduleId, 'Failed to patch schedule');
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Delete a Schedule.
330
+ */
331
+ protected async _deleteSchedule(
332
+ scheduleId: string
333
+ ): Promise<temporal.api.workflowservice.v1.IDeleteScheduleResponse> {
334
+ try {
335
+ return await this.workflowService.deleteSchedule({
336
+ namespace: this.options.namespace,
337
+ identity: this.options.identity,
338
+ scheduleId,
339
+ });
340
+ } catch (err: any) {
341
+ this.rethrowGrpcError(err, scheduleId, 'Failed to delete schedule');
342
+ }
343
+ }
344
+
345
+ /**
346
+ * List Schedules with an `AsyncIterator`:
347
+ *
348
+ * ```ts
349
+ * for await (const schedule: Schedule of client.list()) {
350
+ * const { id, memo, searchAttributes } = schedule
351
+ * // ...
352
+ * }
353
+ * ```
354
+ *
355
+ * To list one page at a time, instead use the raw gRPC method {@link WorkflowService.listSchedules}:
356
+ *
357
+ * ```ts
358
+ * await { schedules, nextPageToken } = client.scheduleService.listSchedules()
359
+ * ```
360
+ */
361
+ public async *list(options?: ListScheduleOptions): AsyncIterable<ScheduleSummary> {
362
+ let nextPageToken: Uint8Array | undefined = undefined;
363
+ for (;;) {
364
+ const response: temporal.api.workflowservice.v1.IListSchedulesResponse = await this.workflowService.listSchedules(
365
+ {
366
+ nextPageToken,
367
+ namespace: this.options.namespace,
368
+ maximumPageSize: options?.pageSize,
369
+ }
370
+ );
371
+
372
+ for (const raw of response.schedules ?? []) {
373
+ if (!raw.info?.spec) continue;
374
+
375
+ yield <ScheduleSummary>{
376
+ scheduleId: raw.scheduleId,
377
+
378
+ spec: decodeScheduleSpec(raw.info.spec),
379
+ action: {
380
+ type: 'startWorkflow',
381
+ workflowType: raw.info.workflowType?.name,
382
+ },
383
+ memo: await decodeMapFromPayloads(this.dataConverter, raw.memo?.fields),
384
+ searchAttributes: decodeSearchAttributes(raw.searchAttributes),
385
+ state: {
386
+ paused: raw.info.paused === true,
387
+ note: raw.info.notes ?? undefined,
388
+ },
389
+ info: {
390
+ recentActions: decodeScheduleRecentActions(raw.info.recentActions),
391
+ nextActionTimes: raw.info?.futureActionTimes?.map(tsToDate) ?? [],
392
+ },
393
+ };
394
+ }
395
+
396
+ if (response.nextPageToken == null || response.nextPageToken.length === 0) break;
397
+ nextPageToken = response.nextPageToken;
398
+ }
399
+ }
400
+
401
+ /**
402
+ * Get a handle to a Schedule
403
+ *
404
+ * This method does not validate `scheduleId`. If there is no Schedule with the given `scheduleId`, handle
405
+ * methods like `handle.describe()` will throw a {@link ScheduleNotFoundError} error.
406
+ */
407
+ public getHandle(scheduleId: string): ScheduleHandle {
408
+ return {
409
+ client: this,
410
+ scheduleId,
411
+
412
+ async describe(): Promise<ScheduleDescription> {
413
+ const raw = await this.client._describeSchedule(this.scheduleId);
414
+ if (!raw.schedule?.spec || !raw.schedule.action)
415
+ throw new Error('Received invalid Schedule description from server');
416
+ return {
417
+ scheduleId,
418
+ spec: decodeScheduleSpec(raw.schedule.spec),
419
+ action: await decodeScheduleAction(this.client.dataConverter, raw.schedule.action),
420
+ memo: await decodeMapFromPayloads(this.client.dataConverter, raw.memo?.fields),
421
+ searchAttributes: decodeSearchAttributes(raw.searchAttributes),
422
+ policies: {
423
+ overlap: decodeOverlapPolicy(raw.schedule.policies?.overlapPolicy),
424
+ catchupWindow: optionalTsToMs(raw.schedule.policies?.catchupWindow) ?? 60_000,
425
+ pauseOnFailure: raw.schedule.policies?.pauseOnFailure === true,
426
+ },
427
+ state: {
428
+ paused: raw.schedule.state?.paused === true,
429
+ note: raw.schedule.state?.notes ?? undefined,
430
+ remainingActions: raw.schedule.state?.limitedActions
431
+ ? raw.schedule.state?.remainingActions?.toNumber() || 0
432
+ : undefined,
433
+ },
434
+ info: {
435
+ recentActions: decodeScheduleRecentActions(raw.info?.recentActions),
436
+ nextActionTimes: raw.info?.futureActionTimes?.map(tsToDate) ?? [],
437
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
438
+ createdAt: tsToDate(raw.info!.createTime!),
439
+ lastUpdatedAt: optionalTsToDate(raw.info?.updateTime),
440
+ runningActions: decodeScheduleRunningActions(raw.info?.runningWorkflows),
441
+ numActionsMissedCatchupWindow: raw.info?.missedCatchupWindow?.toNumber() ?? 0,
442
+ numActionsSkippedOverlap: raw.info?.overlapSkipped?.toNumber() ?? 0,
443
+ numActionsTaken: raw.info?.actionCount?.toNumber() ?? 0,
444
+ },
445
+ raw,
446
+ };
447
+ },
448
+
449
+ async update(updateFn): Promise<void> {
450
+ const current = await this.describe();
451
+ // Keep existing headers
452
+ const currentHeader: Headers = current.raw.schedule?.action?.startWorkflow?.header?.fields ?? {};
453
+ const updated = updateFn(current);
454
+ assertRequiredScheduleOptions(updated, 'UPDATE');
455
+ await this.client._updateSchedule(scheduleId, compileUpdatedScheduleOptions(updated), currentHeader);
456
+ },
457
+
458
+ async delete(): Promise<void> {
459
+ await this.client._deleteSchedule(this.scheduleId);
460
+ },
461
+
462
+ async pause(note?: string): Promise<void> {
463
+ await this.client._patchSchedule(this.scheduleId, {
464
+ pause: note ?? 'Paused via TypeScript SDK"',
465
+ });
466
+ },
467
+
468
+ async unpause(note?): Promise<void> {
469
+ await this.client._patchSchedule(this.scheduleId, {
470
+ unpause: note ?? 'Unpaused via TypeScript SDK"',
471
+ });
472
+ },
473
+
474
+ async trigger(overlap?): Promise<void> {
475
+ await this.client._patchSchedule(this.scheduleId, {
476
+ triggerImmediately: {
477
+ overlapPolicy: overlap
478
+ ? encodeOverlapPolicy(overlap)
479
+ : temporal.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_ALLOW_ALL,
480
+ },
481
+ });
482
+ },
483
+
484
+ async backfill(options): Promise<void> {
485
+ const backfills = Array.isArray(options) ? options : [options];
486
+ await this.client._patchSchedule(this.scheduleId, {
487
+ backfillRequest: backfills.map((x) => ({
488
+ startTime: optionalDateToTs(x.start),
489
+ endTime: optionalDateToTs(x.end),
490
+ overlapPolicy: x.overlap ? encodeOverlapPolicy(x.overlap) : undefined,
491
+ })),
492
+ });
493
+ },
494
+ };
495
+ }
496
+
497
+ protected rethrowGrpcError(err: unknown, scheduleId: string, fallbackMessage: string): never {
498
+ if (isServerErrorResponse(err)) {
499
+ if (err.code === grpcStatus.NOT_FOUND) {
500
+ throw new ScheduleNotFoundError(err.details ?? 'Schedule not found', scheduleId);
501
+ }
502
+ if (
503
+ err.code === grpcStatus.INVALID_ARGUMENT &&
504
+ err.message.match(/^3 INVALID_ARGUMENT: Invalid schedule spec: /)
505
+ ) {
506
+ throw new TypeError(err.message.replace(/^3 INVALID_ARGUMENT: Invalid schedule spec: /, ''));
507
+ }
508
+ throw new ServiceError(fallbackMessage, { cause: err });
509
+ }
510
+ throw new ServiceError('Unexpected error while making gRPC request');
511
+ }
512
+ }
513
+
514
+ /**
515
+ * Thrown from {@link ScheduleClient.create} if there's a running (not deleted) Schedule with the given `id`.
516
+ *
517
+ * @experimental
518
+ */
519
+ export class ScheduleAlreadyRunning extends Error {
520
+ public readonly name: string = 'ScheduleAlreadyRunning';
521
+
522
+ constructor(message: string, public readonly scheduleId: string) {
523
+ super(message);
524
+ }
525
+ }
526
+
527
+ /**
528
+ * Thrown when a Schedule with the given Id is not known to Temporal Server.
529
+ * It could be because:
530
+ * - Id passed is incorrect
531
+ * - Schedule was deleted
532
+ *
533
+ * @experimental
534
+ */
535
+ export class ScheduleNotFoundError extends Error {
536
+ public readonly name: string = 'ScheduleNotFoundError';
537
+
538
+ constructor(message: string, public readonly scheduleId: string) {
539
+ super(message);
540
+ }
541
+ }