@convex-dev/workpool 0.1.2 → 0.2.0-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 (125) hide show
  1. package/README.md +155 -17
  2. package/dist/commonjs/client/index.d.ts +123 -35
  3. package/dist/commonjs/client/index.d.ts.map +1 -1
  4. package/dist/commonjs/client/index.js +122 -15
  5. package/dist/commonjs/client/index.js.map +1 -1
  6. package/dist/commonjs/client/utils.d.ts +16 -0
  7. package/dist/commonjs/client/utils.d.ts.map +1 -0
  8. package/dist/commonjs/client/utils.js +2 -0
  9. package/dist/commonjs/client/utils.js.map +1 -0
  10. package/dist/commonjs/component/complete.d.ts +89 -0
  11. package/dist/commonjs/component/complete.d.ts.map +1 -0
  12. package/dist/commonjs/component/complete.js +80 -0
  13. package/dist/commonjs/component/complete.js.map +1 -0
  14. package/dist/commonjs/component/convex.config.d.ts.map +1 -1
  15. package/dist/commonjs/component/convex.config.js +0 -2
  16. package/dist/commonjs/component/convex.config.js.map +1 -1
  17. package/dist/commonjs/component/kick.d.ts +9 -0
  18. package/dist/commonjs/component/kick.d.ts.map +1 -0
  19. package/dist/commonjs/component/kick.js +97 -0
  20. package/dist/commonjs/component/kick.js.map +1 -0
  21. package/dist/commonjs/component/lib.d.ts +23 -32
  22. package/dist/commonjs/component/lib.d.ts.map +1 -1
  23. package/dist/commonjs/component/lib.js +91 -563
  24. package/dist/commonjs/component/lib.js.map +1 -1
  25. package/dist/commonjs/component/logging.d.ts +5 -3
  26. package/dist/commonjs/component/logging.d.ts.map +1 -1
  27. package/dist/commonjs/component/logging.js +13 -2
  28. package/dist/commonjs/component/logging.js.map +1 -1
  29. package/dist/commonjs/component/loop.d.ts +13 -0
  30. package/dist/commonjs/component/loop.d.ts.map +1 -0
  31. package/dist/commonjs/component/loop.js +482 -0
  32. package/dist/commonjs/component/loop.js.map +1 -0
  33. package/dist/commonjs/component/recovery.d.ts +24 -0
  34. package/dist/commonjs/component/recovery.d.ts.map +1 -0
  35. package/dist/commonjs/component/recovery.js +94 -0
  36. package/dist/commonjs/component/recovery.js.map +1 -0
  37. package/dist/commonjs/component/schema.d.ts +167 -93
  38. package/dist/commonjs/component/schema.d.ts.map +1 -1
  39. package/dist/commonjs/component/schema.js +56 -65
  40. package/dist/commonjs/component/schema.js.map +1 -1
  41. package/dist/commonjs/component/shared.d.ts +138 -0
  42. package/dist/commonjs/component/shared.d.ts.map +1 -0
  43. package/dist/commonjs/component/shared.js +77 -0
  44. package/dist/commonjs/component/shared.js.map +1 -0
  45. package/dist/commonjs/component/stats.d.ts +6 -3
  46. package/dist/commonjs/component/stats.d.ts.map +1 -1
  47. package/dist/commonjs/component/stats.js +23 -4
  48. package/dist/commonjs/component/stats.js.map +1 -1
  49. package/dist/commonjs/component/worker.d.ts +15 -0
  50. package/dist/commonjs/component/worker.d.ts.map +1 -0
  51. package/dist/commonjs/component/worker.js +73 -0
  52. package/dist/commonjs/component/worker.js.map +1 -0
  53. package/dist/esm/client/index.d.ts +123 -35
  54. package/dist/esm/client/index.d.ts.map +1 -1
  55. package/dist/esm/client/index.js +122 -15
  56. package/dist/esm/client/index.js.map +1 -1
  57. package/dist/esm/client/utils.d.ts +16 -0
  58. package/dist/esm/client/utils.d.ts.map +1 -0
  59. package/dist/esm/client/utils.js +2 -0
  60. package/dist/esm/client/utils.js.map +1 -0
  61. package/dist/esm/component/complete.d.ts +89 -0
  62. package/dist/esm/component/complete.d.ts.map +1 -0
  63. package/dist/esm/component/complete.js +80 -0
  64. package/dist/esm/component/complete.js.map +1 -0
  65. package/dist/esm/component/convex.config.d.ts.map +1 -1
  66. package/dist/esm/component/convex.config.js +0 -2
  67. package/dist/esm/component/convex.config.js.map +1 -1
  68. package/dist/esm/component/kick.d.ts +9 -0
  69. package/dist/esm/component/kick.d.ts.map +1 -0
  70. package/dist/esm/component/kick.js +97 -0
  71. package/dist/esm/component/kick.js.map +1 -0
  72. package/dist/esm/component/lib.d.ts +23 -32
  73. package/dist/esm/component/lib.d.ts.map +1 -1
  74. package/dist/esm/component/lib.js +91 -563
  75. package/dist/esm/component/lib.js.map +1 -1
  76. package/dist/esm/component/logging.d.ts +5 -3
  77. package/dist/esm/component/logging.d.ts.map +1 -1
  78. package/dist/esm/component/logging.js +13 -2
  79. package/dist/esm/component/logging.js.map +1 -1
  80. package/dist/esm/component/loop.d.ts +13 -0
  81. package/dist/esm/component/loop.d.ts.map +1 -0
  82. package/dist/esm/component/loop.js +482 -0
  83. package/dist/esm/component/loop.js.map +1 -0
  84. package/dist/esm/component/recovery.d.ts +24 -0
  85. package/dist/esm/component/recovery.d.ts.map +1 -0
  86. package/dist/esm/component/recovery.js +94 -0
  87. package/dist/esm/component/recovery.js.map +1 -0
  88. package/dist/esm/component/schema.d.ts +167 -93
  89. package/dist/esm/component/schema.d.ts.map +1 -1
  90. package/dist/esm/component/schema.js +56 -65
  91. package/dist/esm/component/schema.js.map +1 -1
  92. package/dist/esm/component/shared.d.ts +138 -0
  93. package/dist/esm/component/shared.d.ts.map +1 -0
  94. package/dist/esm/component/shared.js +77 -0
  95. package/dist/esm/component/shared.js.map +1 -0
  96. package/dist/esm/component/stats.d.ts +6 -3
  97. package/dist/esm/component/stats.d.ts.map +1 -1
  98. package/dist/esm/component/stats.js +23 -4
  99. package/dist/esm/component/stats.js.map +1 -1
  100. package/dist/esm/component/worker.d.ts +15 -0
  101. package/dist/esm/component/worker.d.ts.map +1 -0
  102. package/dist/esm/component/worker.js +73 -0
  103. package/dist/esm/component/worker.js.map +1 -0
  104. package/package.json +6 -5
  105. package/src/client/index.ts +232 -68
  106. package/src/client/utils.ts +45 -0
  107. package/src/component/README.md +73 -0
  108. package/src/component/_generated/api.d.ts +38 -66
  109. package/src/component/complete.test.ts +508 -0
  110. package/src/component/complete.ts +98 -0
  111. package/src/component/convex.config.ts +0 -3
  112. package/src/component/kick.test.ts +285 -0
  113. package/src/component/kick.ts +118 -0
  114. package/src/component/lib.test.ts +448 -0
  115. package/src/component/lib.ts +105 -667
  116. package/src/component/logging.ts +24 -12
  117. package/src/component/loop.test.ts +1204 -0
  118. package/src/component/loop.ts +637 -0
  119. package/src/component/recovery.test.ts +541 -0
  120. package/src/component/recovery.ts +96 -0
  121. package/src/component/schema.ts +61 -77
  122. package/src/component/setup.test.ts +5 -0
  123. package/src/component/shared.ts +141 -0
  124. package/src/component/stats.ts +26 -8
  125. package/src/component/worker.ts +81 -0
@@ -1,53 +1,141 @@
1
- import { DefaultFunctionArgs, Expand, FunctionReference, FunctionVisibility, GenericDataModel, GenericMutationCtx, GenericQueryCtx } from "convex/server";
2
- import { GenericId } from "convex/values";
3
- import { api } from "../component/_generated/api";
4
- import { LogLevel } from "../component/logging";
5
- import { completionStatus, type CompletionStatus } from "../component/schema";
6
- export { completionStatus, type CompletionStatus };
7
- export type WorkId = string;
1
+ import { DefaultFunctionArgs, FunctionReference, FunctionVisibility } from "convex/server";
2
+ import { VString } from "convex/values";
3
+ import { Mounts } from "../component/_generated/api.js";
4
+ import { runResult as runResultValidator, RunResult, type RetryBehavior, Status } from "../component/shared.js";
5
+ import { type LogLevel } from "../component/logging.js";
6
+ import { RunMutationCtx, RunQueryCtx, UseApi } from "./utils.js";
7
+ export { runResultValidator, type RunResult };
8
+ export declare const DEFAULT_RETRY_BEHAVIOR: RetryBehavior;
9
+ export type WorkId = string & {
10
+ __isWorkId: true;
11
+ };
12
+ export declare const workIdValidator: VString<WorkId, "required">;
8
13
  export declare class Workpool {
9
14
  private component;
10
15
  private options;
11
- constructor(component: UseApi<typeof api>, options: {
16
+ /**
17
+ * Initializes a Workpool.
18
+ *
19
+ * Note: if you want different pools, you need to *create different instances*
20
+ * of Workpool in convex.config.ts. It isn't sufficient to have different
21
+ * instances of this class.
22
+ *
23
+ * @param component - The component to use, like `components.workpool` from
24
+ * `./_generated/api.ts`.
25
+ * @param options - The options for the Workpool.
26
+ */
27
+ constructor(component: UseApi<Mounts>, // UseApi<api> for jump to definition
28
+ options: {
12
29
  /** How many actions/mutations can be running at once within this pool.
13
30
  * Min 1, Max 300.
14
31
  */
15
- maxParallelism: number;
16
- /** How much to log.
17
- * Default WARN.
32
+ maxParallelism?: number;
33
+ /** How much to log. This is updated on each call to `enqueue*`,
34
+ * `status`, or `cancel*`.
35
+ * Default is WARN.
18
36
  * With INFO, you can see events for started and completed work, which can
19
- * be parsed.
37
+ * be parsed by tools like [Axiom](https://axiom.co) for monitoring.
20
38
  * With DEBUG, you can see timers and internal events for work being
21
39
  * scheduled.
22
40
  */
23
41
  logLevel?: LogLevel;
24
- /** How long to keep completed work in the database, for access by `status`.
25
- * Default 1 day.
42
+ /** Default retry behavior for enqueued actions. */
43
+ defaultRetryBehavior?: RetryBehavior;
44
+ /** Whether to retry actions that fail by default. Default: false.
45
+ * NOTE: Only do this if your actions are idempotent.
46
+ * See the docs (README.md) for more details.
26
47
  */
27
- statusTtl?: number;
48
+ retryActionsByDefault?: boolean;
28
49
  });
29
- enqueueAction<Args extends DefaultFunctionArgs, ReturnType>(ctx: RunMutationCtx, fn: FunctionReference<"action", FunctionVisibility, Args, ReturnType>, fnArgs: Args): Promise<WorkId>;
30
- enqueueMutation<Args extends DefaultFunctionArgs, ReturnType>(ctx: RunMutationCtx, fn: FunctionReference<"mutation", FunctionVisibility, Args, ReturnType>, fnArgs: Args): Promise<WorkId>;
50
+ /**
51
+ * Enqueues an action to be run.
52
+ *
53
+ * @param ctx - The mutation or action context that can call ctx.runMutation.
54
+ * @param fn - The action to run, like `internal.example.myAction`.
55
+ * @param fnArgs - The arguments to pass to the action.
56
+ * @param options - The options for the action to specify retry behavior,
57
+ * onComplete handling, and scheduling via `runAt` or `runAfter`.
58
+ * @returns The ID of the work that was enqueued.
59
+ */
60
+ enqueueAction<Args extends DefaultFunctionArgs, ReturnType>(ctx: RunMutationCtx, fn: FunctionReference<"action", FunctionVisibility, Args, ReturnType>, fnArgs: Args, options?: {
61
+ /** Whether to retry the action if it fails.
62
+ * If true, it will use the default retry behavior.
63
+ * If custom behavior is provided, it will retry using that behavior.
64
+ * If unset, it will use the Workpool's configured default.
65
+ */
66
+ retry?: boolean | RetryBehavior;
67
+ } & CallbackOptions & SchedulerOptions): Promise<WorkId>;
68
+ /**
69
+ * Enqueues a mutation to be run.
70
+ *
71
+ * Note: mutations are not retried by the workpool. Convex automatically
72
+ * retries them on database conflicts and transient failures.
73
+ * Because they're deterministic, external retries don't provide any benefit.
74
+ *
75
+ * @param ctx - The mutation or action context that can call ctx.runMutation.
76
+ * @param fn - The mutation to run, like `internal.example.myMutation`.
77
+ * @param fnArgs - The arguments to pass to the mutation.
78
+ * @param options - The options for the mutation to specify onComplete handling
79
+ * and scheduling via `runAt` or `runAfter`.
80
+ */
81
+ enqueueMutation<Args extends DefaultFunctionArgs, ReturnType>(ctx: RunMutationCtx, fn: FunctionReference<"mutation", FunctionVisibility, Args, ReturnType>, fnArgs: Args, options?: CallbackOptions & SchedulerOptions): Promise<WorkId>;
31
82
  cancel(ctx: RunMutationCtx, id: WorkId): Promise<void>;
32
- status(ctx: RunQueryCtx, id: WorkId): Promise<{
33
- kind: "pending";
34
- } | {
35
- kind: "inProgress";
36
- } | {
37
- kind: "completed";
38
- completionStatus: CompletionStatus;
39
- }>;
83
+ cancelAll(ctx: RunMutationCtx): Promise<void>;
84
+ status(ctx: RunQueryCtx, id: WorkId): Promise<Status>;
40
85
  }
41
- type RunQueryCtx = {
42
- runQuery: GenericQueryCtx<GenericDataModel>["runQuery"];
86
+ export type SchedulerOptions = {
87
+ /**
88
+ * The time (ms since epoch) to run the action at.
89
+ * If not provided, the action will be run as soon as possible.
90
+ * Note: this is advisory only. It may run later.
91
+ */
92
+ runAt?: number;
93
+ } | {
94
+ /**
95
+ * The number of milliseconds to run the action after.
96
+ * If not provided, the action will be run as soon as possible.
97
+ * Note: this is advisory only. It may run later.
98
+ */
99
+ runAfter?: number;
100
+ };
101
+ export type CallbackOptions = {
102
+ /**
103
+ * A mutation to run after the function succeeds, fails, or is canceled.
104
+ * The context type is for your use, feel free to provide a validator for it.
105
+ * e.g.
106
+ * ```ts
107
+ * export const completion = internalMutation({
108
+ * args: {
109
+ * workId: workIdValidator,
110
+ * context: v.any(),
111
+ * result: runResult,
112
+ * },
113
+ * handler: async (ctx, args) => {
114
+ * console.log(args.result, "Got Context back -> ", args.context, Date.now() - args.context);
115
+ * },
116
+ * });
117
+ * ```
118
+ */
119
+ onComplete?: FunctionReference<"mutation", FunctionVisibility, OnCompleteArgs> | null;
120
+ /**
121
+ * A context object to pass to the `onComplete` mutation.
122
+ * Useful for passing data from the enqueue site to the onComplete site.
123
+ */
124
+ context?: unknown;
43
125
  };
44
- type RunMutationCtx = {
45
- runMutation: GenericMutationCtx<GenericDataModel>["runMutation"];
126
+ export type OnCompleteArgs = {
127
+ /**
128
+ * The ID of the work that completed.
129
+ */
130
+ workId: WorkId;
131
+ /**
132
+ * The context object passed when enqueuing the work.
133
+ * Useful for passing data from the enqueue site to the onComplete site.
134
+ */
135
+ context: unknown;
136
+ /**
137
+ * The result of the run that completed.
138
+ */
139
+ result: RunResult;
46
140
  };
47
- export type OpaqueIds<T> = T extends GenericId<infer _T> ? string : T extends (infer U)[] ? OpaqueIds<U>[] : T extends object ? {
48
- [K in keyof T]: OpaqueIds<T[K]>;
49
- } : T;
50
- export type UseApi<API> = Expand<{
51
- [mod in keyof API]: API[mod] extends FunctionReference<infer FType, "public", infer FArgs, infer FReturnType, infer FComponentPath> ? FunctionReference<FType, "internal", OpaqueIds<FArgs>, OpaqueIds<FReturnType>, FComponentPath> : UseApi<API[mod]>;
52
- }>;
53
141
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAEnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AACxD,OAAO,EAEL,SAAS,IAAI,kBAAkB,EAC/B,SAAS,EACT,KAAK,aAAa,EAElB,MAAM,EAEP,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,KAAK,QAAQ,EAAY,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGjE,OAAO,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,CAAC;AAG9C,eAAO,MAAM,sBAAsB,EAAE,aAIpC,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG;IAAE,UAAU,EAAE,IAAI,CAAA;CAAE,CAAC;AACnD,eAAO,MAAM,eAAe,6BAAgC,CAAC;AAE7D,qBAAa,QAAQ;IAajB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,OAAO;IAbjB;;;;;;;;;;OAUG;gBAEO,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,qCAAqC;IAChE,OAAO,EAAE;QACf;;WAEG;QACH,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB;;;;;;;WAOG;QACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;QACpB,mDAAmD;QACnD,oBAAoB,CAAC,EAAE,aAAa,CAAC;QACrC;;;WAGG;QACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;KACjC;IAEH;;;;;;;;;OASG;IACG,aAAa,CAAC,IAAI,SAAS,mBAAmB,EAAE,UAAU,EAC9D,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,UAAU,CAAC,EACrE,MAAM,EAAE,IAAI,EACZ,OAAO,CAAC,EAAE;QACR;;;;WAIG;QACH,KAAK,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;KACjC,GAAG,eAAe,GACjB,gBAAgB,GACjB,OAAO,CAAC,MAAM,CAAC;IAuBlB;;;;;;;;;;;;OAYG;IACG,eAAe,CAAC,IAAI,SAAS,mBAAmB,EAAE,UAAU,EAChE,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,EAAE,IAAI,EAAE,UAAU,CAAC,EACvE,MAAM,EAAE,IAAI,EACZ,OAAO,CAAC,EAAE,eAAe,GAAG,gBAAgB,GAC3C,OAAO,CAAC,MAAM,CAAC;IASZ,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7C,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAG5D;AAgCD,MAAM,MAAM,gBAAgB,GACxB;IACE;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACD;IACE;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEN,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAC5B,UAAU,EACV,kBAAkB,EAClB,cAAc,CACf,GAAG,IAAI,CAAC;IAET;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,SAAS,CAAC;CACnB,CAAC"}
@@ -1,40 +1,147 @@
1
1
  import { createFunctionHandle, getFunctionName, } from "convex/server";
2
- import { completionStatus } from "../component/schema";
3
- export { completionStatus };
2
+ import { v } from "convex/values";
3
+ import { runResult as runResultValidator, } from "../component/shared.js";
4
+ import { logLevel } from "../component/logging.js";
5
+ import { DEFAULT_LOG_LEVEL } from "../component/logging.js";
6
+ import { DEFAULT_MAX_PARALLELISM } from "../component/kick.js";
7
+ export { runResultValidator };
8
+ // Attempts will run with delay [0, 250, 500, 1000, 2000] (ms)
9
+ export const DEFAULT_RETRY_BEHAVIOR = {
10
+ maxAttempts: 5,
11
+ initialBackoffMs: 250,
12
+ base: 2,
13
+ };
14
+ export const workIdValidator = v.string();
4
15
  export class Workpool {
5
16
  component;
6
17
  options;
7
- constructor(component, options) {
18
+ /**
19
+ * Initializes a Workpool.
20
+ *
21
+ * Note: if you want different pools, you need to *create different instances*
22
+ * of Workpool in convex.config.ts. It isn't sufficient to have different
23
+ * instances of this class.
24
+ *
25
+ * @param component - The component to use, like `components.workpool` from
26
+ * `./_generated/api.ts`.
27
+ * @param options - The options for the Workpool.
28
+ */
29
+ constructor(component, // UseApi<api> for jump to definition
30
+ options) {
8
31
  this.component = component;
9
32
  this.options = options;
10
33
  }
11
- async enqueueAction(ctx, fn, fnArgs) {
12
- const fnHandle = await createFunctionHandle(fn);
34
+ /**
35
+ * Enqueues an action to be run.
36
+ *
37
+ * @param ctx - The mutation or action context that can call ctx.runMutation.
38
+ * @param fn - The action to run, like `internal.example.myAction`.
39
+ * @param fnArgs - The arguments to pass to the action.
40
+ * @param options - The options for the action to specify retry behavior,
41
+ * onComplete handling, and scheduling via `runAt` or `runAfter`.
42
+ * @returns The ID of the work that was enqueued.
43
+ */
44
+ async enqueueAction(ctx, fn, fnArgs, options) {
45
+ const retryBehavior = getRetryBehavior(this.options.defaultRetryBehavior, this.options.retryActionsByDefault, options?.retry);
46
+ const onComplete = options?.onComplete
47
+ ? {
48
+ fnHandle: await createFunctionHandle(options.onComplete),
49
+ context: options.context,
50
+ }
51
+ : undefined;
13
52
  const id = await ctx.runMutation(this.component.lib.enqueue, {
14
- fnHandle,
15
- fnName: getFunctionName(fn),
53
+ ...(await defaultEnqueueArgs(fn, this.options)),
16
54
  fnArgs,
17
55
  fnType: "action",
18
- options: this.options,
56
+ runAt: getRunAt(options),
57
+ onComplete,
58
+ retryBehavior,
19
59
  });
20
60
  return id;
21
61
  }
22
- async enqueueMutation(ctx, fn, fnArgs) {
23
- const fnHandle = await createFunctionHandle(fn);
62
+ /**
63
+ * Enqueues a mutation to be run.
64
+ *
65
+ * Note: mutations are not retried by the workpool. Convex automatically
66
+ * retries them on database conflicts and transient failures.
67
+ * Because they're deterministic, external retries don't provide any benefit.
68
+ *
69
+ * @param ctx - The mutation or action context that can call ctx.runMutation.
70
+ * @param fn - The mutation to run, like `internal.example.myMutation`.
71
+ * @param fnArgs - The arguments to pass to the mutation.
72
+ * @param options - The options for the mutation to specify onComplete handling
73
+ * and scheduling via `runAt` or `runAfter`.
74
+ */
75
+ async enqueueMutation(ctx, fn, fnArgs, options) {
24
76
  const id = await ctx.runMutation(this.component.lib.enqueue, {
25
- fnHandle,
26
- fnName: getFunctionName(fn),
77
+ ...(await defaultEnqueueArgs(fn, this.options)),
27
78
  fnArgs,
28
79
  fnType: "mutation",
29
- options: this.options,
80
+ runAt: getRunAt(options),
30
81
  });
31
82
  return id;
32
83
  }
33
84
  async cancel(ctx, id) {
34
- await ctx.runMutation(this.component.lib.cancel, { id });
85
+ await ctx.runMutation(this.component.lib.cancel, {
86
+ id,
87
+ logLevel: this.options.logLevel ?? getDefaultLogLevel(),
88
+ });
89
+ }
90
+ async cancelAll(ctx) {
91
+ await ctx.runMutation(this.component.lib.cancelAll, {
92
+ logLevel: this.options.logLevel ?? getDefaultLogLevel(),
93
+ });
35
94
  }
36
95
  async status(ctx, id) {
37
- return await ctx.runQuery(this.component.lib.status, { id });
96
+ return ctx.runQuery(this.component.lib.status, { id });
97
+ }
98
+ }
99
+ function getRetryBehavior(defaultRetryBehavior, retryActionsByDefault, retryOverride) {
100
+ const defaultRetry = defaultRetryBehavior ?? DEFAULT_RETRY_BEHAVIOR;
101
+ const retryByDefault = retryActionsByDefault ?? false;
102
+ if (retryOverride === true) {
103
+ return defaultRetry;
104
+ }
105
+ if (retryOverride === false) {
106
+ return undefined;
107
+ }
108
+ return retryOverride ?? (retryByDefault ? defaultRetry : undefined);
109
+ }
110
+ async function defaultEnqueueArgs(fn, { logLevel, maxParallelism }) {
111
+ return {
112
+ fnHandle: await createFunctionHandle(fn),
113
+ fnName: getFunctionName(fn),
114
+ config: {
115
+ logLevel: logLevel ?? getDefaultLogLevel(),
116
+ maxParallelism: maxParallelism ?? DEFAULT_MAX_PARALLELISM,
117
+ },
118
+ };
119
+ }
120
+ // ensure OnCompleteArgs satisfies SharedOnCompleteArgs
121
+ const _ = {};
122
+ function getRunAt(options) {
123
+ if (!options) {
124
+ return Date.now();
125
+ }
126
+ if ("runAt" in options && options.runAt !== undefined) {
127
+ return options.runAt;
128
+ }
129
+ if ("runAfter" in options && options.runAfter !== undefined) {
130
+ return Date.now() + options.runAfter;
131
+ }
132
+ return Date.now();
133
+ }
134
+ function getDefaultLogLevel() {
135
+ if (process.env.WORKPOOL_LOG_LEVEL) {
136
+ if (!logLevel.members
137
+ .map((m) => m.value)
138
+ .includes(process.env.WORKPOOL_LOG_LEVEL)) {
139
+ console.warn(`Invalid log level (${process.env.WORKPOOL_LOG_LEVEL}), defaulting to "INFO"`);
140
+ }
141
+ else {
142
+ return process.env.WORKPOOL_LOG_LEVEL;
143
+ }
38
144
  }
145
+ return DEFAULT_LOG_LEVEL;
39
146
  }
40
147
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EAQpB,eAAe,GAChB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,gBAAgB,EAAyB,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAyB,CAAC;AAInD,MAAM,OAAO,QAAQ;IAET;IACA;IAFV,YACU,SAA6B,EAC7B,OAiBP;QAlBO,cAAS,GAAT,SAAS,CAAoB;QAC7B,YAAO,GAAP,OAAO,CAiBd;IACA,CAAC;IACJ,KAAK,CAAC,aAAa,CACjB,GAAmB,EACnB,EAAqE,EACrE,MAAY;QAEZ,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE;YAC3D,QAAQ;YACR,MAAM,EAAE,eAAe,CAAC,EAAE,CAAC;YAC3B,MAAM;YACN,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QACH,OAAO,EAAY,CAAC;IACtB,CAAC;IACD,KAAK,CAAC,eAAe,CACnB,GAAmB,EACnB,EAAuE,EACvE,MAAY;QAEZ,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE;YAC3D,QAAQ;YACR,MAAM,EAAE,eAAe,CAAC,EAAE,CAAC;YAC3B,MAAM;YACN,MAAM,EAAE,UAAU;YAClB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QACH,OAAO,EAAY,CAAC;IACtB,CAAC;IACD,KAAK,CAAC,MAAM,CAAC,GAAmB,EAAE,EAAU;QAC1C,MAAM,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3D,CAAC;IACD,KAAK,CAAC,MAAM,CACV,GAAgB,EAChB,EAAU;QAMV,OAAO,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/D,CAAC;CACF"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { Expand, FunctionReference, GenericMutationCtx, GenericQueryCtx } from "convex/server";
2
+ import { GenericId } from "convex/values";
3
+ import { GenericDataModel } from "convex/server";
4
+ export type RunQueryCtx = {
5
+ runQuery: GenericQueryCtx<GenericDataModel>["runQuery"];
6
+ };
7
+ export type RunMutationCtx = {
8
+ runMutation: GenericMutationCtx<GenericDataModel>["runMutation"];
9
+ };
10
+ export type OpaqueIds<T> = T extends GenericId<infer _T> ? string : T extends (infer U)[] ? OpaqueIds<U>[] : T extends object ? {
11
+ [K in keyof T]: OpaqueIds<T[K]>;
12
+ } : T;
13
+ export type UseApi<API> = Expand<{
14
+ [mod in keyof API]: API[mod] extends FunctionReference<infer FType, "public", infer FArgs, infer FReturnType, infer FComponentPath> ? FunctionReference<FType, "internal", OpaqueIds<FArgs>, OpaqueIds<FReturnType>, FComponentPath> : UseApi<API[mod]>;
15
+ }>;
16
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/client/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAIjD,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,eAAe,CAAC,gBAAgB,CAAC,CAAC,UAAU,CAAC,CAAC;CACzD,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IAC3B,WAAW,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,CAAC;AAEF,MAAM,MAAM,SAAS,CAAC,CAAC,IACrB,CAAC,SAAS,SAAS,CAAC,MAAM,EAAE,CAAC,GACzB,MAAM,GACN,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GACnB,SAAS,CAAC,CAAC,CAAC,EAAE,GACd,CAAC,SAAS,MAAM,GACd;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GACnC,CAAC,CAAC;AAEZ,MAAM,MAAM,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC;KAC9B,GAAG,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,SAAS,iBAAiB,CACpD,MAAM,KAAK,EACX,QAAQ,EACR,MAAM,KAAK,EACX,MAAM,WAAW,EACjB,MAAM,cAAc,CACrB,GACG,iBAAiB,CACf,KAAK,EACL,UAAU,EACV,SAAS,CAAC,KAAK,CAAC,EAChB,SAAS,CAAC,WAAW,CAAC,EACtB,cAAc,CACf,GACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CACrB,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/client/utils.ts"],"names":[],"mappings":""}
@@ -0,0 +1,89 @@
1
+ import { Infer } from "convex/values";
2
+ import { MutationCtx } from "./_generated/server.js";
3
+ export type CompleteJob = Infer<typeof completeArgs.fields.jobs.element>;
4
+ export declare const completeArgs: import("convex/values").VObject<{
5
+ jobs: {
6
+ workId: import("convex/values").GenericId<"work">;
7
+ runResult: {
8
+ kind: "success";
9
+ returnValue: any;
10
+ } | {
11
+ kind: "failed";
12
+ error: string;
13
+ } | {
14
+ kind: "canceled";
15
+ };
16
+ attempt: number;
17
+ }[];
18
+ }, {
19
+ jobs: import("convex/values").VArray<{
20
+ workId: import("convex/values").GenericId<"work">;
21
+ runResult: {
22
+ kind: "success";
23
+ returnValue: any;
24
+ } | {
25
+ kind: "failed";
26
+ error: string;
27
+ } | {
28
+ kind: "canceled";
29
+ };
30
+ attempt: number;
31
+ }[], import("convex/values").VObject<{
32
+ workId: import("convex/values").GenericId<"work">;
33
+ runResult: {
34
+ kind: "success";
35
+ returnValue: any;
36
+ } | {
37
+ kind: "failed";
38
+ error: string;
39
+ } | {
40
+ kind: "canceled";
41
+ };
42
+ attempt: number;
43
+ }, {
44
+ runResult: import("convex/values").VUnion<{
45
+ kind: "success";
46
+ returnValue: any;
47
+ } | {
48
+ kind: "failed";
49
+ error: string;
50
+ } | {
51
+ kind: "canceled";
52
+ }, [import("convex/values").VObject<{
53
+ kind: "success";
54
+ returnValue: any;
55
+ }, {
56
+ kind: import("convex/values").VLiteral<"success", "required">;
57
+ returnValue: import("convex/values").VAny<any, "required", string>;
58
+ }, "required", "kind" | "returnValue" | `returnValue.${string}`>, import("convex/values").VObject<{
59
+ kind: "failed";
60
+ error: string;
61
+ }, {
62
+ kind: import("convex/values").VLiteral<"failed", "required">;
63
+ error: import("convex/values").VString<string, "required">;
64
+ }, "required", "kind" | "error">, import("convex/values").VObject<{
65
+ kind: "canceled";
66
+ }, {
67
+ kind: import("convex/values").VLiteral<"canceled", "required">;
68
+ }, "required", "kind">], "required", "kind" | "returnValue" | `returnValue.${string}` | "error">;
69
+ workId: import("convex/values").VId<import("convex/values").GenericId<"work">, "required">;
70
+ attempt: import("convex/values").VFloat64<number, "required">;
71
+ }, "required", "workId" | "runResult" | "runResult.kind" | "runResult.returnValue" | `runResult.returnValue.${string}` | "runResult.error" | "attempt">, "required">;
72
+ }, "required", "jobs">;
73
+ export declare function completeHandler(ctx: MutationCtx, args: Infer<typeof completeArgs>): Promise<void>;
74
+ export declare const complete: import("convex/server").RegisteredMutation<"internal", {
75
+ jobs: {
76
+ workId: import("convex/values").GenericId<"work">;
77
+ runResult: {
78
+ kind: "success";
79
+ returnValue: any;
80
+ } | {
81
+ kind: "failed";
82
+ error: string;
83
+ } | {
84
+ kind: "canceled";
85
+ };
86
+ attempt: number;
87
+ }[];
88
+ }, Promise<void>>;
89
+ //# sourceMappingURL=complete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../../src/component/complete.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAK,MAAM,eAAe,CAAC;AACzC,OAAO,EAAoB,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAMvE,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAEzE,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAQvB,CAAC;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,KAAK,CAAC,OAAO,YAAY,CAAC,iBAuEjC;AAED,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;iBAGnB,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { v } from "convex/values";
2
+ import { internalMutation } from "./_generated/server.js";
3
+ import { kickMainLoop } from "./kick.js";
4
+ import { createLogger } from "./logging.js";
5
+ import { nextSegment, runResult } from "./shared.js";
6
+ import { recordCompleted } from "./stats.js";
7
+ export const completeArgs = v.object({
8
+ jobs: v.array(v.object({
9
+ runResult: runResult,
10
+ workId: v.id("work"),
11
+ attempt: v.number(),
12
+ })),
13
+ });
14
+ export async function completeHandler(ctx, args) {
15
+ const globals = await ctx.db.query("globals").unique();
16
+ const console = createLogger(globals?.logLevel);
17
+ let anyPendingCompletions = false;
18
+ await Promise.all(args.jobs.map(async (job) => {
19
+ const work = await ctx.db.get(job.workId);
20
+ if (!work) {
21
+ console.warn(`[complete] ${job.workId} is done, but its work is gone`);
22
+ return;
23
+ }
24
+ if (work.attempts !== job.attempt) {
25
+ console.warn(`[complete] ${job.workId} mismatched attempt number`);
26
+ return;
27
+ }
28
+ work.attempts++;
29
+ await ctx.db.patch(work._id, { attempts: work.attempts });
30
+ const pendingCompletion = await ctx.db
31
+ .query("pendingCompletion")
32
+ .withIndex("workId", (q) => q.eq("workId", job.workId))
33
+ .unique();
34
+ if (pendingCompletion) {
35
+ console.warn(`[complete] ${job.workId} already in pendingCompletion`);
36
+ return;
37
+ }
38
+ const maxAttempts = work.retryBehavior?.maxAttempts;
39
+ const retry = job.runResult.kind === "failed" &&
40
+ !!maxAttempts &&
41
+ work.attempts < maxAttempts;
42
+ if (!retry) {
43
+ if (work.onComplete) {
44
+ try {
45
+ const handle = work.onComplete.fnHandle;
46
+ await ctx.runMutation(handle, {
47
+ workId: work._id,
48
+ context: work.onComplete.context,
49
+ result: job.runResult,
50
+ });
51
+ console.debug(`[complete] onComplete for ${job.workId} completed`);
52
+ }
53
+ catch (e) {
54
+ console.error(`[complete] error running onComplete for ${job.workId}`, e);
55
+ // TODO: store failures in a table for later debugging
56
+ }
57
+ }
58
+ console.info(recordCompleted(work, job.runResult.kind));
59
+ // This is the terminating state for work.
60
+ await ctx.db.delete(job.workId);
61
+ }
62
+ if (job.runResult.kind !== "canceled") {
63
+ await ctx.db.insert("pendingCompletion", {
64
+ runResult: job.runResult,
65
+ workId: job.workId,
66
+ segment: nextSegment(),
67
+ retry,
68
+ });
69
+ anyPendingCompletions = true;
70
+ }
71
+ }));
72
+ if (anyPendingCompletions) {
73
+ await kickMainLoop(ctx, "complete");
74
+ }
75
+ }
76
+ export const complete = internalMutation({
77
+ args: completeArgs,
78
+ handler: completeHandler,
79
+ });
80
+ //# sourceMappingURL=complete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complete.js","sourceRoot":"","sources":["../../../src/component/complete.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"convex.config.d.ts","sourceRoot":"","sources":["../../../src/component/convex.config.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,SAAS,kDAA8B,CAAC;AAI9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"convex.config.d.ts","sourceRoot":"","sources":["../../../src/component/convex.config.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,SAAS,kDAA8B,CAAC;AAE9C,eAAe,SAAS,CAAC"}
@@ -1,6 +1,4 @@
1
1
  import { defineComponent } from "convex/server";
2
- import crons from "@convex-dev/crons/convex.config";
3
2
  const component = defineComponent("workpool");
4
- component.use(crons);
5
3
  export default component;
6
4
  //# sourceMappingURL=convex.config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"convex.config.js","sourceRoot":"","sources":["../../../src/component/convex.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,MAAM,iCAAiC,CAAC;AAEpD,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;AAE9C,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAErB,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"convex.config.js","sourceRoot":"","sources":["../../../src/component/convex.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;AAE9C,eAAe,SAAS,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { MutationCtx } from "./_generated/server.js";
2
+ import { Config } from "./shared.js";
3
+ export declare const DEFAULT_MAX_PARALLELISM = 10;
4
+ /**
5
+ * Called from outside the loop:
6
+ */
7
+ export declare function kickMainLoop(ctx: MutationCtx, source: "enqueue" | "cancel" | "complete", config?: Partial<Config>): Promise<void>;
8
+ export declare const forceKick: import("convex/server").RegisteredMutation<"internal", {}, Promise<void>>;
9
+ //# sourceMappingURL=kick.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kick.d.ts","sourceRoot":"","sources":["../../../src/component/kick.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGvE,OAAO,EAAE,MAAM,EAAe,MAAM,aAAa,CAAC;AAElD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C;;GAEG;AAEH,wBAAsB,YAAY,CAChC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,EACzC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GACvB,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAED,eAAO,MAAM,SAAS,2EAOpB,CAAC"}