@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,88 +1,79 @@
1
1
  import { defineSchema, defineTable } from "convex/server";
2
2
  import { v } from "convex/values";
3
- import { logLevel } from "./logging";
4
- export const completionStatus = v.union(v.literal("success"), v.literal("error"), v.literal("canceled"), v.literal("timeout"));
5
- /**
6
- Data flow:
7
-
8
- - The mutation `mainLoop` runs periodically and serially.
9
- - Several tables act as queues, with client-driven mutations enqueueing at high
10
- timestamps and `mainLoop` popping at low timestamps:
11
- pendingStart, pendingCompletion, and pendingCancelation.
12
- - The `enqueue` mutation writes to pendingStart.
13
- - The `cancel` mutation writes to pendingCancelation.
14
- - The `saveResult` mutation, run as part of scheduled work, writes to pendingCompletion.
15
- - mainLoop processes the queues:
16
- - pendingStart => inProgressWork.
17
- - pendingCompletion and pendingCancelation => completedWork.
18
- - inProgressWork that finishes uncleanly (timeout or system failure) => completedWork.
19
- - `mainLoop` schedules itself to run.
20
- - `enqueue`, `cancel`, and `saveResult` mutations check when `mainLoop` is scheduled to run,
21
- and if it's too far in the future, they schedule it to run sooner.
22
- - `status` query reads from pendingWork and completedWork.
23
- - `cleanup` mutation deletes old rows from completedWork.
24
-
25
- To avoid OCCs, we restrict which mutations can read and write from each table:
26
- - pools: read by all, written only when static Workpool options change.
27
- - mainLoop (table): read by all, written mostly by `mainLoop`.
28
- If `mainLoop` will not run for a while, mainLoop table is written by `enqueue`, `cancel`, or `saveResult`.
29
- - pendingWork: `enqueue` inserts at high timestamps, `mainLoop` pops at low timestamps. `status` query does point-reads.
30
- - pendingCompletion: `saveResult` inserts at high timestamps, `mainLoop` pops at low timestamps.
31
- - pendingCancelation: `cancel` inserts at high timestamps, `mainLoop` pops at low timestamps.
32
- - inProgressWork: `mainLoop` inserts, reads all, and deletes.
33
- - completedWork: `mainLoop` inserts at hight timestamps, `status` query reads, `cleanup` deletes at low timestamps.
34
-
35
- */
3
+ import { config, onComplete, retryBehavior, runResult } from "./shared.js";
4
+ // Represents a slice of time to process work.
5
+ const segment = v.int64();
36
6
  export default defineSchema({
37
- // Statically configured, singleton.
38
- pool: defineTable({
39
- maxParallelism: v.number(),
40
- statusTtl: v.number(),
41
- logLevel,
7
+ // Written from kickLoop, read everywhere.
8
+ globals: defineTable(config),
9
+ // Singleton, only read & written by `main`.
10
+ internalState: defineTable({
11
+ // Ensure that only one main is running at a time.
12
+ generation: v.int64(),
13
+ segmentCursors: v.object({
14
+ incoming: segment,
15
+ completion: segment,
16
+ cancelation: segment,
17
+ }),
18
+ lastRecovery: segment,
19
+ report: v.object({
20
+ completed: v.number(),
21
+ succeeded: v.number(),
22
+ failed: v.number(),
23
+ retries: v.number(),
24
+ canceled: v.number(),
25
+ lastReportTs: v.number(),
26
+ }),
27
+ running: v.array(v.object({
28
+ workId: v.id("work"),
29
+ scheduledId: v.id("_scheduled_functions"),
30
+ started: v.number(),
31
+ })),
42
32
  }),
43
- mainLoop: defineTable({
33
+ // Singleton, written by `updateRunStatus` when running, by client or worker otherwise.
34
+ // Safe to read from kickLoop, since it should update infrequently.
35
+ runStatus: defineTable({
44
36
  state: v.union(v.object({ kind: v.literal("running") }), v.object({
45
37
  kind: v.literal("scheduled"),
46
- runAtTime: v.number(),
47
- fn: v.id("_scheduled_functions"),
48
- }), v.object({ kind: v.literal("idle") })),
38
+ segment,
39
+ scheduledId: v.id("_scheduled_functions"),
40
+ saturated: v.boolean(),
41
+ generation: v.int64(),
42
+ }), v.object({ kind: v.literal("idle"), generation: v.int64() })),
49
43
  }),
44
+ // Written on enqueue. Deleted by `complete` for success, failure, canceled.
50
45
  work: defineTable({
51
46
  fnType: v.union(v.literal("action"), v.literal("mutation")),
52
47
  fnHandle: v.string(),
53
48
  fnName: v.string(),
54
49
  fnArgs: v.any(),
50
+ attempts: v.number(),
51
+ onComplete: v.optional(onComplete),
52
+ retryBehavior: v.optional(retryBehavior),
53
+ canceled: v.optional(v.boolean()),
55
54
  }),
55
+ // Written on enqueue & rescheduled for retry, read & deleted by `main`.
56
56
  pendingStart: defineTable({
57
57
  workId: v.id("work"),
58
- }).index("workId", ["workId"]),
58
+ segment,
59
+ })
60
+ .index("workId", ["workId"])
61
+ .index("segment", ["segment"]),
62
+ // Written by complete, read & deleted by `main`.
59
63
  pendingCompletion: defineTable({
60
- generation: v.number(),
61
- completionStatus,
64
+ segment,
65
+ runResult,
62
66
  workId: v.id("work"),
67
+ retry: v.boolean(),
63
68
  })
64
69
  .index("workId", ["workId"])
65
- .index("generation", ["generation"]),
70
+ .index("segment", ["segment"]),
71
+ // Written on cancelation, read & deleted by `main`.
66
72
  pendingCancelation: defineTable({
73
+ segment,
67
74
  workId: v.id("work"),
68
- }),
69
- inProgressWork: defineTable({
70
- running: v.id("_scheduled_functions"),
71
- timeoutMs: v.union(v.number(), v.null()),
72
- workId: v.id("work"),
73
- }).index("workId", ["workId"]),
74
- inProgressCount: defineTable({
75
- count: v.number(),
76
- }),
77
- completedWork: defineTable({
78
- completionStatus,
79
- workId: v.id("work"),
80
- }).index("workId", ["workId"]),
81
- completionGeneration: defineTable({
82
- generation: v.number(),
83
- }),
84
- pendingStartCursor: defineTable({
85
- cursor: v.number(),
86
- }),
75
+ })
76
+ .index("workId", ["workId"])
77
+ .index("segment", ["segment"]),
87
78
  });
88
79
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/component/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/component/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE3E,8CAA8C;AAC9C,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;AAE1B,eAAe,YAAY,CAAC;IAC1B,0CAA0C;IAC1C,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC;IAC5B,4CAA4C;IAC5C,aAAa,EAAE,WAAW,CAAC;QACzB,kDAAkD;QAClD,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE;QACrB,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC;YACvB,QAAQ,EAAE,OAAO;YACjB,UAAU,EAAE,OAAO;YACnB,WAAW,EAAE,OAAO;SACrB,CAAC;QACF,YAAY,EAAE,OAAO;QACrB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;YACf,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;YACrB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;YACrB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;YAClB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;YACnB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;YACpB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;SACzB,CAAC;QACF,OAAO,EAAE,CAAC,CAAC,KAAK,CACd,CAAC,CAAC,MAAM,CAAC;YACP,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC;YACpB,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,sBAAsB,CAAC;YACzC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;SACpB,CAAC,CACH;KACF,CAAC;IAEF,uFAAuF;IACvF,mEAAmE;IACnE,SAAS,EAAE,WAAW,CAAC;QACrB,KAAK,EAAE,CAAC,CAAC,KAAK,CACZ,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,EACxC,CAAC,CAAC,MAAM,CAAC;YACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;YAC5B,OAAO;YACP,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,sBAAsB,CAAC;YACzC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;YACtB,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE;SACtB,CAAC,EACF,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAC7D;KACF,CAAC;IAEF,4EAA4E;IAC5E,IAAI,EAAE,WAAW,CAAC;QAChB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3D,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE;QACf,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;QAClC,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC;QACxC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;KAClC,CAAC;IAEF,wEAAwE;IACxE,YAAY,EAAE,WAAW,CAAC;QACxB,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC;QACpB,OAAO;KACR,CAAC;SACC,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;SAC3B,KAAK,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,CAAC;IAEhC,iDAAiD;IACjD,iBAAiB,EAAE,WAAW,CAAC;QAC7B,OAAO;QACP,SAAS;QACT,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC;QACpB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;KACnB,CAAC;SACC,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;SAC3B,KAAK,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,CAAC;IAEhC,oDAAoD;IACpD,kBAAkB,EAAE,WAAW,CAAC;QAC9B,OAAO;QACP,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC;KACrB,CAAC;SACC,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;SAC3B,KAAK,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,CAAC;CACjC,CAAC,CAAC"}
@@ -0,0 +1,138 @@
1
+ import { Infer } from "convex/values";
2
+ import { Logger } from "./logging.js";
3
+ export declare const SECOND = 1000;
4
+ export declare const MINUTE: number;
5
+ export declare const HOUR: number;
6
+ export declare const DAY: number;
7
+ export declare const YEAR: number;
8
+ export declare function toSegment(ms: number): bigint;
9
+ export declare function currentSegment(): bigint;
10
+ export declare function nextSegment(): bigint;
11
+ export declare function fromSegment(segment: bigint): number;
12
+ export declare const config: import("convex/values").VObject<{
13
+ maxParallelism: number;
14
+ logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR";
15
+ }, {
16
+ maxParallelism: import("convex/values").VFloat64<number, "required">;
17
+ logLevel: import("convex/values").VUnion<"DEBUG" | "INFO" | "WARN" | "ERROR", [import("convex/values").VLiteral<"DEBUG", "required">, import("convex/values").VLiteral<"INFO", "required">, import("convex/values").VLiteral<"WARN", "required">, import("convex/values").VLiteral<"ERROR", "required">], "required", never>;
18
+ }, "required", "maxParallelism" | "logLevel">;
19
+ export type Config = Infer<typeof config>;
20
+ export declare const retryBehavior: import("convex/values").VObject<{
21
+ maxAttempts: number;
22
+ initialBackoffMs: number;
23
+ base: number;
24
+ }, {
25
+ maxAttempts: import("convex/values").VFloat64<number, "required">;
26
+ initialBackoffMs: import("convex/values").VFloat64<number, "required">;
27
+ base: import("convex/values").VFloat64<number, "required">;
28
+ }, "required", "maxAttempts" | "initialBackoffMs" | "base">;
29
+ export type RetryBehavior = {
30
+ /**
31
+ * The maximum number of attempts to make. 2 means one retry.
32
+ */
33
+ maxAttempts: number;
34
+ /**
35
+ * The initial backoff time in milliseconds. 100 means wait 100ms before the
36
+ * first retry.
37
+ */
38
+ initialBackoffMs: number;
39
+ /**
40
+ * The base for the backoff. 2 means double the backoff each time.
41
+ * e.g. if the initial backoff is 100ms, and the base is 2, then the first
42
+ * retry will wait 200ms, the second will wait 400ms, etc.
43
+ */
44
+ base: number;
45
+ };
46
+ export declare const runResult: import("convex/values").VUnion<{
47
+ kind: "success";
48
+ returnValue: any;
49
+ } | {
50
+ kind: "failed";
51
+ error: string;
52
+ } | {
53
+ kind: "canceled";
54
+ }, [import("convex/values").VObject<{
55
+ kind: "success";
56
+ returnValue: any;
57
+ }, {
58
+ kind: import("convex/values").VLiteral<"success", "required">;
59
+ returnValue: import("convex/values").VAny<any, "required", string>;
60
+ }, "required", "kind" | "returnValue" | `returnValue.${string}`>, import("convex/values").VObject<{
61
+ kind: "failed";
62
+ error: string;
63
+ }, {
64
+ kind: import("convex/values").VLiteral<"failed", "required">;
65
+ error: import("convex/values").VString<string, "required">;
66
+ }, "required", "kind" | "error">, import("convex/values").VObject<{
67
+ kind: "canceled";
68
+ }, {
69
+ kind: import("convex/values").VLiteral<"canceled", "required">;
70
+ }, "required", "kind">], "required", "kind" | "returnValue" | `returnValue.${string}` | "error">;
71
+ export type RunResult = Infer<typeof runResult>;
72
+ export declare const onComplete: import("convex/values").VObject<{
73
+ context?: any;
74
+ fnHandle: string;
75
+ }, {
76
+ fnHandle: import("convex/values").VString<string, "required">;
77
+ context: import("convex/values").VAny<any, "optional", string>;
78
+ }, "required", "fnHandle" | "context" | `context.${string}`>;
79
+ export type OnComplete = Infer<typeof onComplete>;
80
+ export type OnCompleteArgs = {
81
+ /**
82
+ * The ID of the work that completed.
83
+ */
84
+ workId: string;
85
+ /**
86
+ * The context object passed when enqueuing the work.
87
+ * Useful for passing data from the enqueue site to the onComplete site.
88
+ */
89
+ context: unknown;
90
+ /**
91
+ * The result of the run that completed.
92
+ */
93
+ result: RunResult;
94
+ };
95
+ export declare const status: import("convex/values").VUnion<{
96
+ state: "pending";
97
+ previousAttempts: number;
98
+ } | {
99
+ state: "running";
100
+ previousAttempts: number;
101
+ } | {
102
+ state: "finished";
103
+ }, [import("convex/values").VUnion<{
104
+ state: "pending";
105
+ previousAttempts: number;
106
+ } | {
107
+ state: "running";
108
+ previousAttempts: number;
109
+ } | {
110
+ state: "finished";
111
+ }, [import("convex/values").VObject<{
112
+ state: "pending";
113
+ previousAttempts: number;
114
+ }, {
115
+ state: import("convex/values").VLiteral<"pending", "required">;
116
+ previousAttempts: import("convex/values").VFloat64<number, "required">;
117
+ }, "required", "state" | "previousAttempts">, import("convex/values").VObject<{
118
+ state: "running";
119
+ previousAttempts: number;
120
+ }, {
121
+ state: import("convex/values").VLiteral<"running", "required">;
122
+ previousAttempts: import("convex/values").VFloat64<number, "required">;
123
+ }, "required", "state" | "previousAttempts">, import("convex/values").VObject<{
124
+ state: "finished";
125
+ }, {
126
+ state: import("convex/values").VLiteral<"finished", "required">;
127
+ }, "required", "state">], "required", "state" | "previousAttempts">], "required", "state" | "previousAttempts">;
128
+ export type Status = Infer<typeof status>;
129
+ export declare function boundScheduledTime(ms: number, console: Logger): number;
130
+ /**
131
+ * Returns the smaller of two bigint values.
132
+ */
133
+ export declare function min<T extends bigint>(a: T, b: T): T;
134
+ /**
135
+ * Returns the larger of two bigint values.
136
+ */
137
+ export declare function max<T extends bigint>(a: T, b: T): T;
138
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/component/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAGtC,OAAO,EAAE,MAAM,EAAY,MAAM,cAAc,CAAC;AAGhD,eAAO,MAAM,MAAM,OAAO,CAAC;AAC3B,eAAO,MAAM,MAAM,QAAc,CAAC;AAClC,eAAO,MAAM,IAAI,QAAc,CAAC;AAChC,eAAO,MAAM,GAAG,QAAY,CAAC;AAC7B,eAAO,MAAM,IAAI,QAAY,CAAC;AAE9B,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,eAAO,MAAM,MAAM;;;;;;6CAGjB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE1C,eAAO,MAAM,aAAa;;;;;;;;2DAIxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAIF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;gGAYrB,CAAC;AACF,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAEhD,eAAO,MAAM,UAAU;;;;;;4DAGrB,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAElD,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;AAEF,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+GAclB,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC;AAE1C,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAatE;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAEnD;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAEnD"}
@@ -0,0 +1,77 @@
1
+ import { v } from "convex/values";
2
+ import { logLevel } from "./logging.js";
3
+ const SEGMENT_MS = 100;
4
+ export const SECOND = 1000;
5
+ export const MINUTE = 60 * SECOND;
6
+ export const HOUR = 60 * MINUTE;
7
+ export const DAY = 24 * HOUR;
8
+ export const YEAR = 365 * DAY;
9
+ export function toSegment(ms) {
10
+ return BigInt(Math.floor(ms / SEGMENT_MS));
11
+ }
12
+ export function currentSegment() {
13
+ return toSegment(Date.now());
14
+ }
15
+ export function nextSegment() {
16
+ return toSegment(Date.now()) + 1n;
17
+ }
18
+ export function fromSegment(segment) {
19
+ return Number(segment) * SEGMENT_MS;
20
+ }
21
+ export const config = v.object({
22
+ maxParallelism: v.number(),
23
+ logLevel,
24
+ });
25
+ export const retryBehavior = v.object({
26
+ maxAttempts: v.number(),
27
+ initialBackoffMs: v.number(),
28
+ base: v.number(),
29
+ });
30
+ // This ensures that the type satisfies the schema.
31
+ const _ = {};
32
+ export const runResult = v.union(v.object({
33
+ kind: v.literal("success"),
34
+ returnValue: v.any(),
35
+ }), v.object({
36
+ kind: v.literal("failed"),
37
+ error: v.string(),
38
+ }), v.object({
39
+ kind: v.literal("canceled"),
40
+ }));
41
+ export const onComplete = v.object({
42
+ fnHandle: v.string(),
43
+ context: v.optional(v.any()),
44
+ });
45
+ export const status = v.union(v.union(v.object({
46
+ state: v.literal("pending"),
47
+ previousAttempts: v.number(),
48
+ }), v.object({
49
+ state: v.literal("running"),
50
+ previousAttempts: v.number(),
51
+ }), v.object({
52
+ state: v.literal("finished"),
53
+ })));
54
+ export function boundScheduledTime(ms, console) {
55
+ if (ms < Date.now() - YEAR) {
56
+ console.error("scheduled time is too old, defaulting to now", ms);
57
+ return Date.now();
58
+ }
59
+ if (ms > Date.now() + 4 * YEAR) {
60
+ console.error("scheduled time is too far in the future, defaulting to 1 year from now", ms);
61
+ return Date.now() + YEAR;
62
+ }
63
+ return ms;
64
+ }
65
+ /**
66
+ * Returns the smaller of two bigint values.
67
+ */
68
+ export function min(a, b) {
69
+ return a > b ? b : a;
70
+ }
71
+ /**
72
+ * Returns the larger of two bigint values.
73
+ */
74
+ export function max(a, b) {
75
+ return a < b ? b : a;
76
+ }
77
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/component/shared.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Doc } from "./_generated/dataModel";
1
+ import { Doc } from "./_generated/dataModel.js";
2
2
  /**
3
3
  * Record stats about work execution. Intended to be queried by Axiom or Datadog.
4
4
  */
@@ -17,7 +17,8 @@ workpool
17
17
 
18
18
  */
19
19
  export declare function recordStarted(work: Doc<"work">): string;
20
- export declare function recordCompleted(work: Doc<"work">, status: "success" | "error" | "canceled" | "timeout"): string;
20
+ export declare function recordCompleted(work: Doc<"work">, status: "success" | "failed" | "canceled" | "retrying"): string;
21
+ export declare function recordReport(state: Doc<"internalState">): string;
21
22
  /**
22
23
  * Warning: this should not be used from a mutation, as it will cause conflicts.
23
24
  * Use this to debug or diagnose your queue length when it's backed up.
@@ -29,9 +30,11 @@ export declare const queueLength: import("convex/server").RegisteredQuery<"inter
29
30
  */
30
31
  export declare const debugCounts: import("convex/server").RegisteredQuery<"internal", {}, Promise<{
31
32
  pendingStart: any;
32
- inProgressWork: any;
33
+ inProgressWork: number;
33
34
  pendingCompletion: any;
34
35
  pendingCancelation: any;
35
36
  active: number;
37
+ runStatus: "running" | "scheduled" | "idle" | undefined;
38
+ generation: bigint | undefined;
36
39
  }>>;
37
40
  //# sourceMappingURL=stats.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../src/component/stats.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAG7C;;GAEG;AAEH;;;;;;;;;;;;;GAaG;AAEH,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CASvD;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EACjB,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,GACnD,MAAM,CASR;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,uEAOtB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;GAwBtB,CAAC"}
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../src/component/stats.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAGhD;;GAEG;AAEH;;;;;;;;;;;;;GAaG;AAEH,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CASvD;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EACjB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GACrD,MAAM,CAUR;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,eAAe,CAAC,GAAG,MAAM,CAahE;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,uEAOtB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;GA0BtB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { v } from "convex/values";
2
- import { internalQuery } from "./_generated/server";
2
+ import { internalQuery } from "./_generated/server.js";
3
3
  /**
4
4
  * Record stats about work execution. Intended to be queried by Axiom or Datadog.
5
5
  */
@@ -33,10 +33,25 @@ export function recordCompleted(work, status) {
33
33
  event: "completed",
34
34
  fnName: work.fnName,
35
35
  completedAt: Date.now(),
36
+ attempts: work.attempts,
36
37
  status,
37
38
  lagSinceEnqueued: Date.now() - work._creationTime,
38
39
  });
39
40
  }
41
+ export function recordReport(state) {
42
+ const { completed, succeeded, failed, retries, canceled } = state.report;
43
+ const withoutRetries = completed - retries;
44
+ return JSON.stringify({
45
+ event: "report",
46
+ completed,
47
+ succeeded,
48
+ failed,
49
+ retries,
50
+ canceled,
51
+ failureRate: completed ? (failed + retries) / completed : 0,
52
+ permanentFailureRate: withoutRetries ? failed / withoutRetries : 0,
53
+ });
54
+ }
40
55
  /**
41
56
  * Warning: this should not be used from a mutation, as it will cause conflicts.
42
57
  * Use this to debug or diagnose your queue length when it's backed up.
@@ -57,19 +72,23 @@ export const debugCounts = internalQuery({
57
72
  args: {},
58
73
  returns: v.any(),
59
74
  handler: async (ctx) => {
75
+ const internalState = await ctx.db.query("internalState").unique();
76
+ const inProgressWork = internalState?.running.length ?? 0;
60
77
  /* eslint-disable @typescript-eslint/no-explicit-any */
61
- const inProgressWork = await ctx.db.query("inProgressWork").count();
62
78
  const pendingStart = await ctx.db.query("pendingStart").count();
63
79
  const pendingCompletion = await ctx.db.query("pendingCompletion").count();
64
80
  const pendingCancelation = await ctx.db.query("pendingCancelation").count();
81
+ const runStatus = await ctx.db.query("runStatus").unique();
82
+ /* eslint-enable @typescript-eslint/no-explicit-any */
65
83
  return {
66
84
  pendingStart,
67
85
  inProgressWork,
68
86
  pendingCompletion,
69
87
  pendingCancelation,
70
- active: inProgressWork - pendingCompletion - pendingCancelation,
88
+ active: inProgressWork - pendingCompletion,
89
+ runStatus: runStatus?.state.kind,
90
+ generation: internalState?.generation,
71
91
  };
72
- /* eslint-enable @typescript-eslint/no-explicit-any */
73
92
  },
74
93
  });
75
94
  //# sourceMappingURL=stats.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/component/stats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;GAEG;AAEH;;;;;;;;;;;;;GAaG;AAEH,MAAM,UAAU,aAAa,CAAC,IAAiB;IAC7C,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,MAAM,EAAE,IAAI,CAAC,GAAG;QAChB,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,UAAU,EAAE,IAAI,CAAC,aAAa;QAC9B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,gBAAgB,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa;KAClD,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,IAAiB,EACjB,MAAoD;IAEpD,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,MAAM,EAAE,IAAI,CAAC,GAAG;QAChB,KAAK,EAAE,WAAW;QAClB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;QACvB,MAAM;QACN,gBAAgB,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa;KAClD,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;IACvC,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACrB,8DAA8D;QAC9D,OAAQ,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAS,CAAC,KAAK,EAAE,CAAC;IACvD,CAAC;CACF,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;IACvC,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE;IAChB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACrB,uDAAuD;QACvD,MAAM,cAAc,GAAG,MACrB,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAC9B,CAAC,KAAK,EAAE,CAAC;QACV,MAAM,YAAY,GAAG,MAAO,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAS,CAAC,KAAK,EAAE,CAAC;QACzE,MAAM,iBAAiB,GAAG,MACxB,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CACjC,CAAC,KAAK,EAAE,CAAC;QACV,MAAM,kBAAkB,GAAG,MACzB,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAClC,CAAC,KAAK,EAAE,CAAC;QACV,OAAO;YACL,YAAY;YACZ,cAAc;YACd,iBAAiB;YACjB,kBAAkB;YAClB,MAAM,EAAE,cAAc,GAAG,iBAAiB,GAAG,kBAAkB;SAChE,CAAC;QACF,sDAAsD;IACxD,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/component/stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export declare const runMutationWrapper: import("convex/server").RegisteredMutation<"internal", {
2
+ logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR";
3
+ fnHandle: string;
4
+ workId: import("convex/values").GenericId<"work">;
5
+ fnArgs: any;
6
+ attempt: number;
7
+ }, Promise<void>>;
8
+ export declare const runActionWrapper: import("convex/server").RegisteredAction<"internal", {
9
+ logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR";
10
+ fnHandle: string;
11
+ workId: import("convex/values").GenericId<"work">;
12
+ fnArgs: any;
13
+ attempt: number;
14
+ }, Promise<void>>;
15
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../src/component/worker.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,kBAAkB;;;;;;iBA4B7B,CAAC;AASH,eAAO,MAAM,gBAAgB;;;;;;iBA4B3B,CAAC"}
@@ -0,0 +1,73 @@
1
+ import { v } from "convex/values";
2
+ import { internal } from "./_generated/api.js";
3
+ import { internalAction, internalMutation } from "./_generated/server.js";
4
+ import { createLogger, logLevel } from "./logging.js";
5
+ export const runMutationWrapper = internalMutation({
6
+ args: {
7
+ workId: v.id("work"),
8
+ fnHandle: v.string(),
9
+ fnArgs: v.any(),
10
+ logLevel,
11
+ attempt: v.number(),
12
+ },
13
+ handler: async (ctx, { workId, attempt, ...args }) => {
14
+ const console = createLogger(args.logLevel);
15
+ const fnHandle = args.fnHandle;
16
+ try {
17
+ const returnValue = await ctx.runMutation(fnHandle, args.fnArgs);
18
+ // NOTE: we could run the `saveResult` handler here, or call `ctx.runMutation`,
19
+ // but we want the mutation to be a separate transaction to reduce the window for OCCs.
20
+ await ctx.scheduler.runAfter(0, internal.complete.complete, {
21
+ jobs: [
22
+ { workId, runResult: { kind: "success", returnValue }, attempt },
23
+ ],
24
+ });
25
+ }
26
+ catch (e) {
27
+ console.error(e);
28
+ const runResult = { kind: "failed", error: formatError(e) };
29
+ await ctx.scheduler.runAfter(0, internal.complete.complete, {
30
+ jobs: [{ workId, runResult, attempt }],
31
+ });
32
+ }
33
+ },
34
+ });
35
+ function formatError(e) {
36
+ if (e instanceof Error) {
37
+ return e.message;
38
+ }
39
+ return String(e);
40
+ }
41
+ export const runActionWrapper = internalAction({
42
+ args: {
43
+ workId: v.id("work"),
44
+ fnHandle: v.string(),
45
+ fnArgs: v.any(),
46
+ logLevel,
47
+ attempt: v.number(),
48
+ },
49
+ handler: async (ctx, { workId, attempt, ...args }) => {
50
+ const console = createLogger(args.logLevel);
51
+ const fnHandle = args.fnHandle;
52
+ try {
53
+ const returnValue = await ctx.runAction(fnHandle, args.fnArgs);
54
+ // NOTE: we could run `ctx.runMutation`, but we want to guarantee execution,
55
+ // and `ctx.scheduler.runAfter` won't OCC.
56
+ const runResult = { kind: "success", returnValue };
57
+ await ctx.scheduler.runAfter(0, internal.complete.complete, {
58
+ jobs: [{ workId, runResult, attempt }],
59
+ });
60
+ }
61
+ catch (e) {
62
+ console.error(e);
63
+ // We let the main loop handle the retries.
64
+ const runResult = { kind: "failed", error: formatError(e) };
65
+ await ctx.scheduler.runAfter(0, internal.complete.complete, {
66
+ jobs: [{ workId, runResult, attempt }],
67
+ });
68
+ }
69
+ },
70
+ });
71
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
72
+ const console = "THIS IS A REMINDER TO USE createLogger";
73
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../src/component/worker.ts"],"names":[],"mappings":"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"}
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.1.2",
10
+ "version": "0.2.0-alpha.0",
11
11
  "license": "Apache-2.0",
12
12
  "keywords": [
13
13
  "convex",
@@ -27,7 +27,7 @@
27
27
  "prepare": "npm run build",
28
28
  "prepack": "node node10stubs.mjs",
29
29
  "postpack": "node node10stubs.mjs --cleanup",
30
- "test": "vitest run",
30
+ "test": "vitest",
31
31
  "lint": "tsc --noEmit && eslint . && prettier --check .",
32
32
  "format": "prettier --write .",
33
33
  "test:debug": "vitest --inspect-brk --no-file-parallelism",
@@ -66,18 +66,19 @@
66
66
  "devDependencies": {
67
67
  "@eslint/js": "^9.9.1",
68
68
  "@types/node": "^18.17.0",
69
- "convex-test": "^0.0.35",
69
+ "convex-test": "^0.0.36-alpha.0",
70
70
  "eslint": "^9.9.1",
71
71
  "globals": "^15.9.0",
72
72
  "prettier": "3.2.5",
73
73
  "typescript": "~5.0.3",
74
74
  "typescript-eslint": "^8.4.0",
75
- "vitest": "^2.1.4"
75
+ "vitest": "^2.1.9"
76
76
  },
77
77
  "main": "./dist/commonjs/client/index.js",
78
78
  "types": "./dist/commonjs/client/index.d.ts",
79
79
  "module": "./dist/esm/client/index.js",
80
80
  "dependencies": {
81
- "@convex-dev/crons": "^0.1.5"
81
+ "@edge-runtime/vm": "^4.0.4",
82
+ "@vitest/coverage-v8": "^2.1.9"
82
83
  }
83
84
  }