@convex-dev/workpool 0.2.20-alpha.0 → 0.3.1-alpha.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 (59) hide show
  1. package/README.md +77 -68
  2. package/dist/client/index.d.ts +3 -3
  3. package/dist/client/index.d.ts.map +1 -1
  4. package/dist/client/index.js.map +1 -1
  5. package/dist/client/utils.d.ts +1 -8
  6. package/dist/client/utils.d.ts.map +1 -1
  7. package/dist/client/utils.js.map +1 -1
  8. package/dist/component/_generated/api.d.ts +27 -124
  9. package/dist/component/_generated/api.d.ts.map +1 -1
  10. package/dist/component/_generated/api.js +10 -1
  11. package/dist/component/_generated/api.js.map +1 -1
  12. package/dist/component/_generated/component.d.ts +98 -0
  13. package/dist/component/_generated/component.d.ts.map +1 -0
  14. package/dist/component/_generated/component.js +11 -0
  15. package/dist/component/_generated/component.js.map +1 -0
  16. package/dist/component/_generated/dataModel.d.ts +4 -18
  17. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  18. package/dist/component/_generated/dataModel.js +11 -0
  19. package/dist/component/_generated/dataModel.js.map +1 -0
  20. package/dist/component/_generated/server.d.ts +10 -38
  21. package/dist/component/_generated/server.d.ts.map +1 -1
  22. package/dist/component/_generated/server.js +9 -5
  23. package/dist/component/_generated/server.js.map +1 -1
  24. package/dist/component/danger.d.ts +2 -2
  25. package/dist/component/lib.d.ts +9 -9
  26. package/dist/component/lib.js +2 -2
  27. package/dist/component/lib.js.map +1 -1
  28. package/dist/component/schema.d.ts +15 -15
  29. package/dist/component/shared.d.ts +3 -3
  30. package/dist/component/stats.d.ts +2 -2
  31. package/dist/component/worker.d.ts +3 -3
  32. package/package.json +30 -29
  33. package/src/client/index.ts +19 -20
  34. package/src/client/utils.ts +3 -30
  35. package/src/component/README.md +6 -6
  36. package/src/component/_generated/api.ts +70 -0
  37. package/src/component/_generated/component.ts +117 -0
  38. package/src/component/_generated/{server.d.ts → server.ts} +33 -21
  39. package/src/component/complete.test.ts +1 -1
  40. package/src/component/complete.ts +6 -6
  41. package/src/component/danger.ts +3 -3
  42. package/src/component/kick.test.ts +5 -5
  43. package/src/component/kick.ts +6 -6
  44. package/src/component/lib.test.ts +5 -5
  45. package/src/component/lib.ts +10 -10
  46. package/src/component/logging.ts +2 -2
  47. package/src/component/loop.test.ts +9 -9
  48. package/src/component/loop.ts +33 -33
  49. package/src/component/recovery.test.ts +7 -7
  50. package/src/component/recovery.ts +2 -2
  51. package/src/component/schema.ts +2 -2
  52. package/src/component/shared.ts +5 -5
  53. package/src/component/stats.test.ts +3 -3
  54. package/src/component/stats.ts +6 -6
  55. package/src/test.ts +10 -3
  56. package/src/component/_generated/api.d.ts +0 -151
  57. package/src/component/_generated/api.js +0 -23
  58. package/src/component/_generated/server.js +0 -90
  59. /package/src/component/_generated/{dataModel.d.ts → dataModel.ts} +0 -0
@@ -8,9 +8,8 @@
8
8
  * @module
9
9
  */
10
10
 
11
- import {
11
+ import type {
12
12
  ActionBuilder,
13
- AnyComponents,
14
13
  HttpActionBuilder,
15
14
  MutationBuilder,
16
15
  QueryBuilder,
@@ -19,15 +18,18 @@ import {
19
18
  GenericQueryCtx,
20
19
  GenericDatabaseReader,
21
20
  GenericDatabaseWriter,
22
- FunctionReference,
21
+ } from "convex/server";
22
+ import {
23
+ actionGeneric,
24
+ httpActionGeneric,
25
+ queryGeneric,
26
+ mutationGeneric,
27
+ internalActionGeneric,
28
+ internalMutationGeneric,
29
+ internalQueryGeneric,
23
30
  } from "convex/server";
24
31
  import type { DataModel } from "./dataModel.js";
25
32
 
26
- type GenericCtx =
27
- | GenericActionCtx<DataModel>
28
- | GenericMutationCtx<DataModel>
29
- | GenericQueryCtx<DataModel>;
30
-
31
33
  /**
32
34
  * Define a query in this Convex app's public API.
33
35
  *
@@ -36,7 +38,7 @@ type GenericCtx =
36
38
  * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
37
39
  * @returns The wrapped query. Include this as an `export` to name it and make it accessible.
38
40
  */
39
- export declare const query: QueryBuilder<DataModel, "public">;
41
+ export const query: QueryBuilder<DataModel, "public"> = queryGeneric;
40
42
 
41
43
  /**
42
44
  * Define a query that is only accessible from other Convex functions (but not from the client).
@@ -46,7 +48,8 @@ export declare const query: QueryBuilder<DataModel, "public">;
46
48
  * @param func - The query function. It receives a {@link QueryCtx} as its first argument.
47
49
  * @returns The wrapped query. Include this as an `export` to name it and make it accessible.
48
50
  */
49
- export declare const internalQuery: QueryBuilder<DataModel, "internal">;
51
+ export const internalQuery: QueryBuilder<DataModel, "internal"> =
52
+ internalQueryGeneric;
50
53
 
51
54
  /**
52
55
  * Define a mutation in this Convex app's public API.
@@ -56,7 +59,7 @@ export declare const internalQuery: QueryBuilder<DataModel, "internal">;
56
59
  * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
57
60
  * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
58
61
  */
59
- export declare const mutation: MutationBuilder<DataModel, "public">;
62
+ export const mutation: MutationBuilder<DataModel, "public"> = mutationGeneric;
60
63
 
61
64
  /**
62
65
  * Define a mutation that is only accessible from other Convex functions (but not from the client).
@@ -66,7 +69,8 @@ export declare const mutation: MutationBuilder<DataModel, "public">;
66
69
  * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
67
70
  * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
68
71
  */
69
- export declare const internalMutation: MutationBuilder<DataModel, "internal">;
72
+ export const internalMutation: MutationBuilder<DataModel, "internal"> =
73
+ internalMutationGeneric;
70
74
 
71
75
  /**
72
76
  * Define an action in this Convex app's public API.
@@ -79,7 +83,7 @@ export declare const internalMutation: MutationBuilder<DataModel, "internal">;
79
83
  * @param func - The action. It receives an {@link ActionCtx} as its first argument.
80
84
  * @returns The wrapped action. Include this as an `export` to name it and make it accessible.
81
85
  */
82
- export declare const action: ActionBuilder<DataModel, "public">;
86
+ export const action: ActionBuilder<DataModel, "public"> = actionGeneric;
83
87
 
84
88
  /**
85
89
  * Define an action that is only accessible from other Convex functions (but not from the client).
@@ -87,19 +91,26 @@ export declare const action: ActionBuilder<DataModel, "public">;
87
91
  * @param func - The function. It receives an {@link ActionCtx} as its first argument.
88
92
  * @returns The wrapped function. Include this as an `export` to name it and make it accessible.
89
93
  */
90
- export declare const internalAction: ActionBuilder<DataModel, "internal">;
94
+ export const internalAction: ActionBuilder<DataModel, "internal"> =
95
+ internalActionGeneric;
91
96
 
92
97
  /**
93
98
  * Define an HTTP action.
94
99
  *
95
- * This function will be used to respond to HTTP requests received by a Convex
96
- * deployment if the requests matches the path and method where this action
97
- * is routed. Be sure to route your action in `convex/http.js`.
100
+ * The wrapped function will be used to respond to HTTP requests received
101
+ * by a Convex deployment if the requests matches the path and method where
102
+ * this action is routed. Be sure to route your httpAction in `convex/http.js`.
98
103
  *
99
- * @param func - The function. It receives an {@link ActionCtx} as its first argument.
104
+ * @param func - The function. It receives an {@link ActionCtx} as its first argument
105
+ * and a Fetch API `Request` object as its second.
100
106
  * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up.
101
107
  */
102
- export declare const httpAction: HttpActionBuilder;
108
+ export const httpAction: HttpActionBuilder = httpActionGeneric;
109
+
110
+ type GenericCtx =
111
+ | GenericActionCtx<DataModel>
112
+ | GenericMutationCtx<DataModel>
113
+ | GenericQueryCtx<DataModel>;
103
114
 
104
115
  /**
105
116
  * A set of services for use within Convex query functions.
@@ -107,8 +118,7 @@ export declare const httpAction: HttpActionBuilder;
107
118
  * The query context is passed as the first argument to any Convex query
108
119
  * function run on the server.
109
120
  *
110
- * This differs from the {@link MutationCtx} because all of the services are
111
- * read-only.
121
+ * If you're using code generation, use the `QueryCtx` type in `convex/_generated/server.d.ts` instead.
112
122
  */
113
123
  export type QueryCtx = GenericQueryCtx<DataModel>;
114
124
 
@@ -117,6 +127,8 @@ export type QueryCtx = GenericQueryCtx<DataModel>;
117
127
  *
118
128
  * The mutation context is passed as the first argument to any Convex mutation
119
129
  * function run on the server.
130
+ *
131
+ * If you're using code generation, use the `MutationCtx` type in `convex/_generated/server.d.ts` instead.
120
132
  */
121
133
  export type MutationCtx = GenericMutationCtx<DataModel>;
122
134
 
@@ -283,7 +283,7 @@ describe("complete", () => {
283
283
  workId,
284
284
  context: { someContext: "value" },
285
285
  result: { kind: "success", returnValue: "test result" },
286
- })
286
+ }),
287
287
  );
288
288
  });
289
289
  });
@@ -19,12 +19,12 @@ export const completeArgs = v.object({
19
19
  runResult: vResultValidator,
20
20
  workId: v.id("work"),
21
21
  attempt: v.number(),
22
- })
22
+ }),
23
23
  ),
24
24
  });
25
25
  export async function completeHandler(
26
26
  ctx: MutationCtx,
27
- args: Infer<typeof completeArgs>
27
+ args: Infer<typeof completeArgs>,
28
28
  ) {
29
29
  const globals = await ctx.db.query("globals").unique();
30
30
  const console = createLogger(globals?.logLevel);
@@ -76,7 +76,7 @@ export async function completeHandler(
76
76
  } catch (e) {
77
77
  console.error(
78
78
  `[complete] error running onComplete for ${job.workId}`,
79
- e
79
+ e,
80
80
  );
81
81
  // TODO: store failures in a table for later debugging
82
82
  }
@@ -92,7 +92,7 @@ export async function completeHandler(
92
92
  retry,
93
93
  });
94
94
  }
95
- })
95
+ }),
96
96
  );
97
97
  if (pendingCompletions.length > 0) {
98
98
  const segment = await kickMainLoop(ctx, "complete");
@@ -101,8 +101,8 @@ export async function completeHandler(
101
101
  ctx.db.insert("pendingCompletion", {
102
102
  ...completion,
103
103
  segment,
104
- })
105
- )
104
+ }),
105
+ ),
106
106
  );
107
107
  }
108
108
  }
@@ -29,7 +29,7 @@ export const clearPending = internalMutation({
29
29
  if (work) {
30
30
  await ctx.db.delete(work._id);
31
31
  }
32
- })
32
+ }),
33
33
  );
34
34
  if (!entries.isDone) {
35
35
  await ctx.scheduler.runAfter(0, internal.danger.clearPending, {
@@ -87,10 +87,10 @@ export const clearOldWork = internalMutation({
87
87
  })
88
88
  .filter(([_, v]) => v !== null)
89
89
  .map(([name]) => name)
90
- .join(", ")})`
90
+ .join(", ")})`,
91
91
  );
92
92
  await ctx.db.delete(entry._id);
93
- })
93
+ }),
94
94
  );
95
95
  if (!entries.isDone) {
96
96
  await ctx.scheduler.runAfter(0, internal.danger.clearOldWork, {
@@ -107,7 +107,7 @@ describe("kickMainLoop", () => {
107
107
  {
108
108
  generation: 0n,
109
109
  segment: futureSegment,
110
- }
110
+ },
111
111
  );
112
112
  await ctx.db.patch(runStatus._id, {
113
113
  state: {
@@ -149,7 +149,7 @@ describe("kickMainLoop", () => {
149
149
  {
150
150
  generation: 0n,
151
151
  segment: nearFutureSegment,
152
- }
152
+ },
153
153
  );
154
154
  await ctx.db.patch(runStatus._id, {
155
155
  state: {
@@ -221,8 +221,8 @@ describe("kickMainLoop", () => {
221
221
  t.run(async (ctx) => {
222
222
  const segment = await kickMainLoop(ctx, "enqueue");
223
223
  return segment;
224
- })
225
- )
224
+ }),
225
+ ),
226
226
  );
227
227
  expect(segments.filter((s) => s === getCurrentSegment())).toHaveLength(1);
228
228
 
@@ -278,7 +278,7 @@ describe("kickMainLoop", () => {
278
278
  const scheduledId = await ctx.scheduler.runAfter(
279
279
  10_000,
280
280
  internal.loop.main,
281
- { generation: 0n, segment }
281
+ { generation: 0n, segment },
282
282
  );
283
283
  await ctx.db.patch(runStatus._id, {
284
284
  state: {
@@ -20,7 +20,7 @@ import {
20
20
  export async function kickMainLoop(
21
21
  ctx: MutationCtx,
22
22
  source: "enqueue" | "cancel" | "complete" | "kick",
23
- config?: Partial<Config>
23
+ config?: Partial<Config>,
24
24
  ): Promise<bigint> {
25
25
  const globals = await getOrUpdateGlobals(ctx, config);
26
26
  const console = createLogger(globals.logLevel);
@@ -30,7 +30,7 @@ export async function kickMainLoop(
30
30
  // Only kick to run now if we're scheduled or idle.
31
31
  if (runStatus.state.kind === "running") {
32
32
  console.debug(
33
- `[${source}] main is actively running, so we don't need to kick it`
33
+ `[${source}] main is actively running, so we don't need to kick it`,
34
34
  );
35
35
  return next;
36
36
  }
@@ -38,25 +38,25 @@ export async function kickMainLoop(
38
38
  if (runStatus.state.kind === "scheduled") {
39
39
  if (source === "enqueue" && runStatus.state.saturated) {
40
40
  console.debug(
41
- `[${source}] main is saturated, so we don't need to kick it`
41
+ `[${source}] main is saturated, so we don't need to kick it`,
42
42
  );
43
43
  return next;
44
44
  }
45
45
  if (runStatus.state.segment <= toSegment(Date.now() + SECOND)) {
46
46
  console.debug(
47
- `[${source}] main is scheduled to run soon enough, so we don't need to kick it`
47
+ `[${source}] main is scheduled to run soon enough, so we don't need to kick it`,
48
48
  );
49
49
  return next;
50
50
  }
51
51
  console.debug(
52
- `[${source}] main is scheduled to run later, so reschedule it to run now`
52
+ `[${source}] main is scheduled to run later, so reschedule it to run now`,
53
53
  );
54
54
  const scheduled = await ctx.db.system.get(runStatus.state.scheduledId);
55
55
  if (scheduled && scheduled.state.kind === "pending") {
56
56
  await ctx.scheduler.cancel(runStatus.state.scheduledId);
57
57
  } else {
58
58
  console.warn(
59
- `[${source}] main is marked as scheduled, but it's status is ${scheduled?.state.kind}`
59
+ `[${source}] main is marked as scheduled, but it's status is ${scheduled?.state.kind}`,
60
60
  );
61
61
  }
62
62
  } else if (runStatus.state.kind === "idle") {
@@ -62,11 +62,11 @@ describe("lib", () => {
62
62
  fnType: "mutation",
63
63
  runAt: Date.now(),
64
64
  config: {
65
- maxParallelism: 101, // More than MAX_POSSIBLE_PARALLELISM
65
+ maxParallelism: 500, // More than MAX_POSSIBLE_PARALLELISM
66
66
  logLevel: "WARN",
67
67
  },
68
- })
69
- ).rejects.toThrow("maxParallelism must be <= 50");
68
+ }),
69
+ ).rejects.toThrow("maxParallelism must be <= 100");
70
70
  });
71
71
 
72
72
  it("should throw error if maxParallelism is too low", async () => {
@@ -81,7 +81,7 @@ describe("lib", () => {
81
81
  maxParallelism: 0, // Less than minimum
82
82
  logLevel: "WARN",
83
83
  },
84
- })
84
+ }),
85
85
  ).rejects.toThrow("maxParallelism must be >= 1");
86
86
  });
87
87
  });
@@ -249,7 +249,7 @@ describe("lib", () => {
249
249
  expect(scheduledFunctions.length).toBeGreaterThan(0);
250
250
  // check that one of the scheduled functions is cancelAll
251
251
  const cancelAllScheduledFunction = scheduledFunctions.find(
252
- (sf) => sf.name === "lib:cancelAll"
252
+ (sf) => sf.name === "lib:cancelAll",
253
253
  );
254
254
  expect(cancelAllScheduledFunction).toBeDefined();
255
255
  assert(cancelAllScheduledFunction);
@@ -27,8 +27,8 @@ import {
27
27
  } from "./shared.js";
28
28
  import { recordEnqueued } from "./stats.js";
29
29
 
30
- const MAX_POSSIBLE_PARALLELISM = 100;
31
- const MAX_PARALLELISM_SOFT_LIMIT = 50;
30
+ const MAX_POSSIBLE_PARALLELISM = 200;
31
+ const MAX_PARALLELISM_SOFT_LIMIT = 100;
32
32
 
33
33
  const itemArgs = {
34
34
  fnHandle: v.string(),
@@ -58,7 +58,7 @@ async function enqueueHandler(
58
58
  ctx: MutationCtx,
59
59
  console: Logger,
60
60
  kickSegment: bigint,
61
- { runAt, ...workArgs }: ObjectType<typeof itemArgs>
61
+ { runAt, ...workArgs }: ObjectType<typeof itemArgs>,
62
62
  ) {
63
63
  runAt = boundScheduledTime(runAt, console);
64
64
  const workId = await ctx.db.insert("work", {
@@ -79,7 +79,7 @@ function validateConfig(config: Config) {
79
79
  throw new Error(`maxParallelism must be <= ${MAX_PARALLELISM_SOFT_LIMIT}`);
80
80
  } else if (config.maxParallelism > MAX_PARALLELISM_SOFT_LIMIT) {
81
81
  createLogger(config.logLevel).warn(
82
- `maxParallelism should be <= ${MAX_PARALLELISM_SOFT_LIMIT}, but is set to ${config.maxParallelism}. This will be an error in a future version.`
82
+ `maxParallelism should be <= ${MAX_PARALLELISM_SOFT_LIMIT}, but is set to ${config.maxParallelism}. This will be an error in a future version.`,
83
83
  );
84
84
  } else if (config.maxParallelism < 1) {
85
85
  throw new Error("maxParallelism must be >= 1");
@@ -97,7 +97,7 @@ export const enqueueBatch = mutation({
97
97
  const console = createLogger(config.logLevel);
98
98
  const kickSegment = await kickMainLoop(ctx, "enqueue", config);
99
99
  return Promise.all(
100
- items.map((item) => enqueueHandler(ctx, console, kickSegment, item))
100
+ items.map((item) => enqueueHandler(ctx, console, kickSegment, item)),
101
101
  );
102
102
  },
103
103
  });
@@ -136,8 +136,8 @@ export const cancelAll = mutation({
136
136
  .take(pageSize);
137
137
  const shouldCancel = await Promise.all(
138
138
  pageOfWork.map(async ({ _id }) =>
139
- shouldCancelWorkItem(ctx, _id, logLevel)
140
- )
139
+ shouldCancelWorkItem(ctx, _id, logLevel),
140
+ ),
141
141
  );
142
142
  let segment = getNextSegment();
143
143
  if (shouldCancel.some((c) => c)) {
@@ -151,7 +151,7 @@ export const cancelAll = mutation({
151
151
  segment,
152
152
  });
153
153
  }
154
- })
154
+ }),
155
155
  );
156
156
  if (pageOfWork.length === pageSize) {
157
157
  await ctx.scheduler.runAfter(0, api.lib.cancelAll, {
@@ -196,7 +196,7 @@ export const statusBatch = query({
196
196
  returns: v.array(statusValidator),
197
197
  handler: async (ctx, { ids }) => {
198
198
  return await Promise.all(
199
- ids.map(async (id) => await statusHandler(ctx, { id }))
199
+ ids.map(async (id) => await statusHandler(ctx, { id })),
200
200
  );
201
201
  },
202
202
  });
@@ -204,7 +204,7 @@ export const statusBatch = query({
204
204
  async function shouldCancelWorkItem(
205
205
  ctx: MutationCtx,
206
206
  workId: Id<"work">,
207
- logLevel: LogLevel
207
+ logLevel: LogLevel,
208
208
  ) {
209
209
  const console = createLogger(logLevel);
210
210
  // No-op if the work doesn't exist or has completed.
@@ -10,7 +10,7 @@ export const logLevel = v.union(
10
10
  v.literal("INFO"),
11
11
  v.literal("REPORT"),
12
12
  v.literal("WARN"),
13
- v.literal("ERROR")
13
+ v.literal("ERROR"),
14
14
  );
15
15
  export type LogLevel = Infer<typeof logLevel>;
16
16
 
@@ -30,7 +30,7 @@ const logLevelByName = logLevelOrder.reduce(
30
30
  acc[l] = i;
31
31
  return acc;
32
32
  },
33
- {} as Record<LogLevel, number>
33
+ {} as Record<LogLevel, number>,
34
34
  );
35
35
  export function shouldLog(config: LogLevel, level: LogLevel) {
36
36
  return logLevelByName[config] <= logLevelByName[level];
@@ -49,7 +49,7 @@ describe("loop", () => {
49
49
 
50
50
  async function makeDummyWork(
51
51
  ctx: MutationCtx,
52
- overrides: Partial<WithoutSystemFields<Doc<"work">>> = {}
52
+ overrides: Partial<WithoutSystemFields<Doc<"work">>> = {},
53
53
  ) {
54
54
  return ctx.db.insert("work", {
55
55
  fnType: "action",
@@ -63,7 +63,7 @@ describe("loop", () => {
63
63
 
64
64
  async function makeDummyScheduledFunction(
65
65
  ctx: MutationCtx,
66
- workId: Id<"work">
66
+ workId: Id<"work">,
67
67
  ) {
68
68
  return ctx.scheduler.runAfter(0, internal.worker.runActionWrapper, {
69
69
  workId,
@@ -76,7 +76,7 @@ describe("loop", () => {
76
76
 
77
77
  async function insertInternalState(
78
78
  ctx: MutationCtx,
79
- overrides: Partial<WithoutSystemFields<Doc<"internalState">>> = {}
79
+ overrides: Partial<WithoutSystemFields<Doc<"internalState">>> = {},
80
80
  ) {
81
81
  await ctx.db.insert("internalState", {
82
82
  generation: 1n,
@@ -450,7 +450,7 @@ describe("loop", () => {
450
450
  const scheduledId = await ctx.scheduler.runAfter(
451
451
  1000,
452
452
  internal.loop.main,
453
- { generation: 1n, segment: getNextSegment() + 10n }
453
+ { generation: 1n, segment: getNextSegment() + 10n },
454
454
  );
455
455
 
456
456
  // Create scheduled runStatus
@@ -553,7 +553,7 @@ describe("loop", () => {
553
553
  const scheduledId = await ctx.scheduler.runAfter(
554
554
  1000,
555
555
  internal.loop.main,
556
- { generation: 1n, segment }
556
+ { generation: 1n, segment },
557
557
  );
558
558
 
559
559
  await ctx.db.insert("runStatus", {
@@ -588,7 +588,7 @@ describe("loop", () => {
588
588
 
589
589
  // Call main with mismatched generation
590
590
  await expect(
591
- t.mutation(internal.loop.main, { generation: 1n, segment: 1n })
591
+ t.mutation(internal.loop.main, { generation: 1n, segment: 1n }),
592
592
  ).rejects.toThrow("generation mismatch");
593
593
  });
594
594
 
@@ -707,7 +707,7 @@ describe("loop", () => {
707
707
  // Schedule a function and get its ID
708
708
  const scheduledId = await makeDummyScheduledFunction(
709
709
  ctx,
710
- runningWorkId
710
+ runningWorkId,
711
711
  );
712
712
 
713
713
  // Create internal state
@@ -848,7 +848,7 @@ describe("loop", () => {
848
848
  t.mutation(internal.loop.updateRunStatus, {
849
849
  generation: 1n,
850
850
  segment: 1n,
851
- })
851
+ }),
852
852
  ).rejects.toThrow("generation mismatch");
853
853
  });
854
854
 
@@ -935,7 +935,7 @@ describe("loop", () => {
935
935
  const scheduledId = await makeDummyScheduledFunction(ctx, workId);
936
936
 
937
937
  return { workId, scheduledId, started: Date.now() };
938
- })
938
+ }),
939
939
  );
940
940
 
941
941
  // Create internal state with max running jobs