@convex-dev/workpool 0.2.16 → 0.2.17-alpha.1

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/README.md CHANGED
@@ -280,6 +280,7 @@ See more example usage in [example.ts](./example/convex/example.ts).
280
280
  Check out the [docstrings](./src/client/index.ts), but notable options include:
281
281
 
282
282
  - `maxParallelism`: How many actions/mutations can run at once within this pool.
283
+ Avoid exceeding 100 on Pro, 20 on the free plan, across all workpools and workflows.
283
284
  - `retryActionsByDefault`: Whether to retry actions that fail by default.
284
285
  - `defaultRetryBehavior`: The default retry behavior for enqueued actions.
285
286
 
@@ -229,7 +229,7 @@ export type RetryOption = {
229
229
  };
230
230
  export type WorkpoolOptions = {
231
231
  /** How many actions/mutations can be running at once within this pool.
232
- * Min 1, Max 300.
232
+ * Min 1, Suggested max: 100 on Pro, 20 on the free plan.
233
233
  */
234
234
  maxParallelism?: number;
235
235
  /** How much to log. This is updated on each call to `enqueue*`,
@@ -0,0 +1,11 @@
1
+ export declare const clearPending: import("convex/server").RegisteredMutation<"internal", {
2
+ olderThan?: number | undefined;
3
+ before?: number | undefined;
4
+ cursor?: string | undefined;
5
+ }, Promise<void>>;
6
+ export declare const clearOldWork: import("convex/server").RegisteredMutation<"internal", {
7
+ olderThan?: number | undefined;
8
+ before?: number | undefined;
9
+ cursor?: string | undefined;
10
+ }, Promise<void>>;
11
+ //# sourceMappingURL=danger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"danger.d.ts","sourceRoot":"","sources":["../../../src/component/danger.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,YAAY;;;;iBAgCvB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;iBA2DvB,CAAC"}
@@ -0,0 +1,92 @@
1
+ import { v } from "convex/values";
2
+ import { internal } from "./_generated/api.js";
3
+ import { internalMutation, } from "./_generated/server.js";
4
+ import { paginator } from "convex-helpers/server/pagination";
5
+ import schema from "./schema.js";
6
+ const DEFAULT_OLDER_THAN = 1000 * 60 * 60 * 24;
7
+ export const clearPending = internalMutation({
8
+ args: {
9
+ olderThan: v.optional(v.number()),
10
+ before: v.optional(v.number()),
11
+ cursor: v.optional(v.string()),
12
+ },
13
+ handler: async (ctx, args) => {
14
+ const time = args.before ?? Date.now() - (args.olderThan ?? DEFAULT_OLDER_THAN);
15
+ const entries = await paginator(ctx.db, schema)
16
+ .query("pendingStart")
17
+ .withIndex("by_creation_time", (q) => q.lt("_creationTime", time))
18
+ .paginate({
19
+ cursor: args.cursor ?? null,
20
+ numItems: 100,
21
+ });
22
+ await Promise.all(entries.page.map(async (entry) => {
23
+ await ctx.db.delete(entry._id);
24
+ const work = await ctx.db.get(entry.workId);
25
+ if (work) {
26
+ await ctx.db.delete(work._id);
27
+ }
28
+ }));
29
+ if (!entries.isDone) {
30
+ await ctx.scheduler.runAfter(0, internal.danger.clearPending, {
31
+ before: time,
32
+ cursor: entries.continueCursor,
33
+ });
34
+ }
35
+ },
36
+ });
37
+ export const clearOldWork = internalMutation({
38
+ args: {
39
+ olderThan: v.optional(v.number()),
40
+ before: v.optional(v.number()),
41
+ cursor: v.optional(v.string()),
42
+ },
43
+ handler: async (ctx, args) => {
44
+ const time = args.before ?? Date.now() - (args.olderThan ?? DEFAULT_OLDER_THAN);
45
+ const entries = await paginator(ctx.db, schema)
46
+ .query("work")
47
+ .withIndex("by_creation_time", (q) => q.lt("_creationTime", time))
48
+ .paginate({
49
+ cursor: args.cursor ?? null,
50
+ numItems: 100,
51
+ });
52
+ await Promise.all(entries.page.map(async (entry) => {
53
+ const pendingStart = await ctx.db
54
+ .query("pendingStart")
55
+ .withIndex("workId", (q) => q.eq("workId", entry._id))
56
+ .unique();
57
+ if (pendingStart) {
58
+ await ctx.db.delete(pendingStart._id);
59
+ }
60
+ const pendingCompletion = await ctx.db
61
+ .query("pendingCompletion")
62
+ .withIndex("workId", (q) => q.eq("workId", entry._id))
63
+ .unique();
64
+ if (pendingCompletion) {
65
+ await ctx.db.delete(pendingCompletion._id);
66
+ }
67
+ const pendingCancelation = await ctx.db
68
+ .query("pendingCancelation")
69
+ .withIndex("workId", (q) => q.eq("workId", entry._id))
70
+ .unique();
71
+ if (pendingCancelation) {
72
+ await ctx.db.delete(pendingCancelation._id);
73
+ }
74
+ console.debug(`cleared ${entry.fnName}: ${entry.fnArgs} (${Object.entries({
75
+ pendingStart,
76
+ pendingCompletion,
77
+ pendingCancelation,
78
+ })
79
+ .filter(([_, v]) => v !== null)
80
+ .map(([name]) => name)
81
+ .join(", ")})`);
82
+ await ctx.db.delete(entry._id);
83
+ }));
84
+ if (!entries.isDone) {
85
+ await ctx.scheduler.runAfter(0, internal.danger.clearOldWork, {
86
+ before: time,
87
+ cursor: entries.continueCursor,
88
+ });
89
+ }
90
+ },
91
+ });
92
+ //# sourceMappingURL=danger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"danger.js","sourceRoot":"","sources":["../../../src/component/danger.ts"],"names":[],"mappings":"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"}
@@ -25,9 +25,9 @@ export declare const calculateBacklogAndReport: import("convex/server").Register
25
25
  };
26
26
  logLevel: "DEBUG" | "TRACE" | "INFO" | "REPORT" | "WARN" | "ERROR";
27
27
  running: number;
28
+ cursor: string;
28
29
  startSegment: bigint;
29
30
  endSegment: bigint;
30
- cursor: string;
31
31
  }, Promise<void>>;
32
32
  /**
33
33
  * Warning: this should not be used from a mutation, as it will cause conflicts.
@@ -229,7 +229,7 @@ export type RetryOption = {
229
229
  };
230
230
  export type WorkpoolOptions = {
231
231
  /** How many actions/mutations can be running at once within this pool.
232
- * Min 1, Max 300.
232
+ * Min 1, Suggested max: 100 on Pro, 20 on the free plan.
233
233
  */
234
234
  maxParallelism?: number;
235
235
  /** How much to log. This is updated on each call to `enqueue*`,
@@ -0,0 +1,11 @@
1
+ export declare const clearPending: import("convex/server").RegisteredMutation<"internal", {
2
+ olderThan?: number | undefined;
3
+ before?: number | undefined;
4
+ cursor?: string | undefined;
5
+ }, Promise<void>>;
6
+ export declare const clearOldWork: import("convex/server").RegisteredMutation<"internal", {
7
+ olderThan?: number | undefined;
8
+ before?: number | undefined;
9
+ cursor?: string | undefined;
10
+ }, Promise<void>>;
11
+ //# sourceMappingURL=danger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"danger.d.ts","sourceRoot":"","sources":["../../../src/component/danger.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,YAAY;;;;iBAgCvB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;iBA2DvB,CAAC"}
@@ -0,0 +1,92 @@
1
+ import { v } from "convex/values";
2
+ import { internal } from "./_generated/api.js";
3
+ import { internalMutation, } from "./_generated/server.js";
4
+ import { paginator } from "convex-helpers/server/pagination";
5
+ import schema from "./schema.js";
6
+ const DEFAULT_OLDER_THAN = 1000 * 60 * 60 * 24;
7
+ export const clearPending = internalMutation({
8
+ args: {
9
+ olderThan: v.optional(v.number()),
10
+ before: v.optional(v.number()),
11
+ cursor: v.optional(v.string()),
12
+ },
13
+ handler: async (ctx, args) => {
14
+ const time = args.before ?? Date.now() - (args.olderThan ?? DEFAULT_OLDER_THAN);
15
+ const entries = await paginator(ctx.db, schema)
16
+ .query("pendingStart")
17
+ .withIndex("by_creation_time", (q) => q.lt("_creationTime", time))
18
+ .paginate({
19
+ cursor: args.cursor ?? null,
20
+ numItems: 100,
21
+ });
22
+ await Promise.all(entries.page.map(async (entry) => {
23
+ await ctx.db.delete(entry._id);
24
+ const work = await ctx.db.get(entry.workId);
25
+ if (work) {
26
+ await ctx.db.delete(work._id);
27
+ }
28
+ }));
29
+ if (!entries.isDone) {
30
+ await ctx.scheduler.runAfter(0, internal.danger.clearPending, {
31
+ before: time,
32
+ cursor: entries.continueCursor,
33
+ });
34
+ }
35
+ },
36
+ });
37
+ export const clearOldWork = internalMutation({
38
+ args: {
39
+ olderThan: v.optional(v.number()),
40
+ before: v.optional(v.number()),
41
+ cursor: v.optional(v.string()),
42
+ },
43
+ handler: async (ctx, args) => {
44
+ const time = args.before ?? Date.now() - (args.olderThan ?? DEFAULT_OLDER_THAN);
45
+ const entries = await paginator(ctx.db, schema)
46
+ .query("work")
47
+ .withIndex("by_creation_time", (q) => q.lt("_creationTime", time))
48
+ .paginate({
49
+ cursor: args.cursor ?? null,
50
+ numItems: 100,
51
+ });
52
+ await Promise.all(entries.page.map(async (entry) => {
53
+ const pendingStart = await ctx.db
54
+ .query("pendingStart")
55
+ .withIndex("workId", (q) => q.eq("workId", entry._id))
56
+ .unique();
57
+ if (pendingStart) {
58
+ await ctx.db.delete(pendingStart._id);
59
+ }
60
+ const pendingCompletion = await ctx.db
61
+ .query("pendingCompletion")
62
+ .withIndex("workId", (q) => q.eq("workId", entry._id))
63
+ .unique();
64
+ if (pendingCompletion) {
65
+ await ctx.db.delete(pendingCompletion._id);
66
+ }
67
+ const pendingCancelation = await ctx.db
68
+ .query("pendingCancelation")
69
+ .withIndex("workId", (q) => q.eq("workId", entry._id))
70
+ .unique();
71
+ if (pendingCancelation) {
72
+ await ctx.db.delete(pendingCancelation._id);
73
+ }
74
+ console.debug(`cleared ${entry.fnName}: ${entry.fnArgs} (${Object.entries({
75
+ pendingStart,
76
+ pendingCompletion,
77
+ pendingCancelation,
78
+ })
79
+ .filter(([_, v]) => v !== null)
80
+ .map(([name]) => name)
81
+ .join(", ")})`);
82
+ await ctx.db.delete(entry._id);
83
+ }));
84
+ if (!entries.isDone) {
85
+ await ctx.scheduler.runAfter(0, internal.danger.clearOldWork, {
86
+ before: time,
87
+ cursor: entries.continueCursor,
88
+ });
89
+ }
90
+ },
91
+ });
92
+ //# sourceMappingURL=danger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"danger.js","sourceRoot":"","sources":["../../../src/component/danger.ts"],"names":[],"mappings":"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"}
@@ -25,9 +25,9 @@ export declare const calculateBacklogAndReport: import("convex/server").Register
25
25
  };
26
26
  logLevel: "DEBUG" | "TRACE" | "INFO" | "REPORT" | "WARN" | "ERROR";
27
27
  running: number;
28
+ cursor: string;
28
29
  startSegment: bigint;
29
30
  endSegment: bigint;
30
- cursor: string;
31
31
  }, Promise<void>>;
32
32
  /**
33
33
  * Warning: this should not be used from a mutation, as it will cause conflicts.
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "email": "support@convex.dev",
8
8
  "url": "https://github.com/get-convex/workpool/issues"
9
9
  },
10
- "version": "0.2.16",
10
+ "version": "0.2.17-alpha.1",
11
11
  "license": "Apache-2.0",
12
12
  "keywords": [
13
13
  "convex",
@@ -64,22 +64,22 @@
64
64
  }
65
65
  },
66
66
  "peerDependencies": {
67
- "convex": ">=1.17.0 <1.35.0",
67
+ "convex": ">=1.25.0 <1.35.0",
68
68
  "convex-helpers": "^0.1.94"
69
69
  },
70
70
  "devDependencies": {
71
- "@edge-runtime/vm": "^4.0.4",
72
- "@eslint/js": "^9.9.1",
73
- "@types/node": "^18.17.0",
74
- "@vitest/coverage-v8": "^2.1.9",
75
- "convex-test": "^0.0.38-alpha.0",
76
- "eslint": "^9.9.1",
77
- "globals": "^15.9.0",
78
- "pkg-pr-new": "^0.0.54",
79
- "prettier": "3.2.5",
80
- "typescript": "^5.8.3",
81
- "typescript-eslint": "^8.4.0",
82
- "vitest": "^2.1.9"
71
+ "@edge-runtime/vm": "5.0.0",
72
+ "@eslint/js": "9.31.0",
73
+ "@types/node": "22.16.3",
74
+ "@vitest/coverage-v8": "3.2.4",
75
+ "convex-test": "0.0.38",
76
+ "eslint": "9.31.0",
77
+ "globals": "16.3.0",
78
+ "pkg-pr-new": "0.0.54",
79
+ "prettier": "3.6.2",
80
+ "typescript": "5.8.3",
81
+ "typescript-eslint": "8.36.0",
82
+ "vitest": "3.2.4"
83
83
  },
84
84
  "main": "./dist/commonjs/client/index.js",
85
85
  "types": "./dist/commonjs/client/index.d.ts",
@@ -289,7 +289,7 @@ export type RetryOption = {
289
289
 
290
290
  export type WorkpoolOptions = {
291
291
  /** How many actions/mutations can be running at once within this pool.
292
- * Min 1, Max 300.
292
+ * Min 1, Suggested max: 100 on Pro, 20 on the free plan.
293
293
  */
294
294
  maxParallelism?: number;
295
295
  /** How much to log. This is updated on each call to `enqueue*`,
@@ -10,6 +10,7 @@
10
10
 
11
11
  import type * as complete from "../complete.js";
12
12
  import type * as crons from "../crons.js";
13
+ import type * as danger from "../danger.js";
13
14
  import type * as kick from "../kick.js";
14
15
  import type * as lib from "../lib.js";
15
16
  import type * as logging from "../logging.js";
@@ -36,6 +37,7 @@ import type {
36
37
  declare const fullApi: ApiFromModules<{
37
38
  complete: typeof complete;
38
39
  crons: typeof crons;
40
+ danger: typeof danger;
39
41
  kick: typeof kick;
40
42
  lib: typeof lib;
41
43
  logging: typeof logging;
@@ -0,0 +1,110 @@
1
+ import { v } from "convex/values";
2
+ import { api, internal } from "./_generated/api.js";
3
+ import type { Doc, Id } from "./_generated/dataModel.js";
4
+ import {
5
+ action,
6
+ internalAction,
7
+ internalMutation,
8
+ internalQuery,
9
+ mutation,
10
+ query,
11
+ } from "./_generated/server.js";
12
+ import { paginator } from "convex-helpers/server/pagination";
13
+ import schema from "./schema.js";
14
+
15
+ const DEFAULT_OLDER_THAN = 1000 * 60 * 60 * 24;
16
+
17
+ export const clearPending = internalMutation({
18
+ args: {
19
+ olderThan: v.optional(v.number()),
20
+ before: v.optional(v.number()),
21
+ cursor: v.optional(v.string()),
22
+ },
23
+ handler: async (ctx, args) => {
24
+ const time =
25
+ args.before ?? Date.now() - (args.olderThan ?? DEFAULT_OLDER_THAN);
26
+ const entries = await paginator(ctx.db, schema)
27
+ .query("pendingStart")
28
+ .withIndex("by_creation_time", (q) => q.lt("_creationTime", time))
29
+ .paginate({
30
+ cursor: args.cursor ?? null,
31
+ numItems: 100,
32
+ });
33
+ await Promise.all(
34
+ entries.page.map(async (entry) => {
35
+ await ctx.db.delete(entry._id);
36
+ const work = await ctx.db.get(entry.workId);
37
+ if (work) {
38
+ await ctx.db.delete(work._id);
39
+ }
40
+ })
41
+ );
42
+ if (!entries.isDone) {
43
+ await ctx.scheduler.runAfter(0, internal.danger.clearPending, {
44
+ before: time,
45
+ cursor: entries.continueCursor,
46
+ });
47
+ }
48
+ },
49
+ });
50
+
51
+ export const clearOldWork = internalMutation({
52
+ args: {
53
+ olderThan: v.optional(v.number()),
54
+ before: v.optional(v.number()),
55
+ cursor: v.optional(v.string()),
56
+ },
57
+ handler: async (ctx, args) => {
58
+ const time =
59
+ args.before ?? Date.now() - (args.olderThan ?? DEFAULT_OLDER_THAN);
60
+ const entries = await paginator(ctx.db, schema)
61
+ .query("work")
62
+ .withIndex("by_creation_time", (q) => q.lt("_creationTime", time))
63
+ .paginate({
64
+ cursor: args.cursor ?? null,
65
+ numItems: 100,
66
+ });
67
+ await Promise.all(
68
+ entries.page.map(async (entry) => {
69
+ const pendingStart = await ctx.db
70
+ .query("pendingStart")
71
+ .withIndex("workId", (q) => q.eq("workId", entry._id))
72
+ .unique();
73
+ if (pendingStart) {
74
+ await ctx.db.delete(pendingStart._id);
75
+ }
76
+ const pendingCompletion = await ctx.db
77
+ .query("pendingCompletion")
78
+ .withIndex("workId", (q) => q.eq("workId", entry._id))
79
+ .unique();
80
+ if (pendingCompletion) {
81
+ await ctx.db.delete(pendingCompletion._id);
82
+ }
83
+ const pendingCancelation = await ctx.db
84
+ .query("pendingCancelation")
85
+ .withIndex("workId", (q) => q.eq("workId", entry._id))
86
+ .unique();
87
+ if (pendingCancelation) {
88
+ await ctx.db.delete(pendingCancelation._id);
89
+ }
90
+ console.debug(
91
+ `cleared ${entry.fnName}: ${entry.fnArgs} (${Object.entries({
92
+ pendingStart,
93
+ pendingCompletion,
94
+ pendingCancelation,
95
+ })
96
+ .filter(([_, v]) => v !== null)
97
+ .map(([name]) => name)
98
+ .join(", ")})`
99
+ );
100
+ await ctx.db.delete(entry._id);
101
+ })
102
+ );
103
+ if (!entries.isDone) {
104
+ await ctx.scheduler.runAfter(0, internal.danger.clearOldWork, {
105
+ before: time,
106
+ cursor: entries.continueCursor,
107
+ });
108
+ }
109
+ },
110
+ });