@convex-dev/workpool 0.1.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.
- package/LICENSE +201 -0
- package/README.md +183 -0
- package/dist/commonjs/client/index.d.ts +53 -0
- package/dist/commonjs/client/index.d.ts.map +1 -0
- package/dist/commonjs/client/index.js +40 -0
- package/dist/commonjs/client/index.js.map +1 -0
- package/dist/commonjs/component/_generated/api.d.ts +14 -0
- package/dist/commonjs/component/_generated/api.d.ts.map +1 -0
- package/dist/commonjs/component/_generated/api.js +22 -0
- package/dist/commonjs/component/_generated/api.js.map +1 -0
- package/dist/commonjs/component/_generated/server.d.ts +64 -0
- package/dist/commonjs/component/_generated/server.d.ts.map +1 -0
- package/dist/commonjs/component/_generated/server.js +74 -0
- package/dist/commonjs/component/_generated/server.js.map +1 -0
- package/dist/commonjs/component/convex.config.d.ts +3 -0
- package/dist/commonjs/component/convex.config.d.ts.map +1 -0
- package/dist/commonjs/component/convex.config.js +6 -0
- package/dist/commonjs/component/convex.config.js.map +1 -0
- package/dist/commonjs/component/lib.d.ts +50 -0
- package/dist/commonjs/component/lib.d.ts.map +1 -0
- package/dist/commonjs/component/lib.js +562 -0
- package/dist/commonjs/component/lib.js.map +1 -0
- package/dist/commonjs/component/logging.d.ts +13 -0
- package/dist/commonjs/component/logging.d.ts.map +1 -0
- package/dist/commonjs/component/logging.js +41 -0
- package/dist/commonjs/component/logging.js.map +1 -0
- package/dist/commonjs/component/schema.d.ts +149 -0
- package/dist/commonjs/component/schema.d.ts.map +1 -0
- package/dist/commonjs/component/schema.js +85 -0
- package/dist/commonjs/component/schema.js.map +1 -0
- package/dist/commonjs/component/stats.d.ts +37 -0
- package/dist/commonjs/component/stats.d.ts.map +1 -0
- package/dist/commonjs/component/stats.js +75 -0
- package/dist/commonjs/component/stats.js.map +1 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/esm/client/index.d.ts +53 -0
- package/dist/esm/client/index.d.ts.map +1 -0
- package/dist/esm/client/index.js +40 -0
- package/dist/esm/client/index.js.map +1 -0
- package/dist/esm/component/_generated/api.d.ts +14 -0
- package/dist/esm/component/_generated/api.d.ts.map +1 -0
- package/dist/esm/component/_generated/api.js +22 -0
- package/dist/esm/component/_generated/api.js.map +1 -0
- package/dist/esm/component/_generated/server.d.ts +64 -0
- package/dist/esm/component/_generated/server.d.ts.map +1 -0
- package/dist/esm/component/_generated/server.js +74 -0
- package/dist/esm/component/_generated/server.js.map +1 -0
- package/dist/esm/component/convex.config.d.ts +3 -0
- package/dist/esm/component/convex.config.d.ts.map +1 -0
- package/dist/esm/component/convex.config.js +6 -0
- package/dist/esm/component/convex.config.js.map +1 -0
- package/dist/esm/component/lib.d.ts +50 -0
- package/dist/esm/component/lib.d.ts.map +1 -0
- package/dist/esm/component/lib.js +562 -0
- package/dist/esm/component/lib.js.map +1 -0
- package/dist/esm/component/logging.d.ts +13 -0
- package/dist/esm/component/logging.d.ts.map +1 -0
- package/dist/esm/component/logging.js +41 -0
- package/dist/esm/component/logging.js.map +1 -0
- package/dist/esm/component/schema.d.ts +149 -0
- package/dist/esm/component/schema.d.ts.map +1 -0
- package/dist/esm/component/schema.js +85 -0
- package/dist/esm/component/schema.js.map +1 -0
- package/dist/esm/component/stats.d.ts +37 -0
- package/dist/esm/component/stats.d.ts.map +1 -0
- package/dist/esm/component/stats.js +75 -0
- package/dist/esm/component/stats.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/package.json +83 -0
- package/src/client/index.ts +121 -0
- package/src/component/_generated/api.d.ts +133 -0
- package/src/component/_generated/api.js +23 -0
- package/src/component/_generated/dataModel.d.ts +60 -0
- package/src/component/_generated/server.d.ts +149 -0
- package/src/component/_generated/server.js +90 -0
- package/src/component/convex.config.ts +8 -0
- package/src/component/lib.ts +670 -0
- package/src/component/logging.ts +59 -0
- package/src/component/schema.ts +103 -0
- package/src/component/stats.ts +90 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { Infer } from "convex/values";
|
|
2
|
+
export declare const completionStatus: import("convex/values").VUnion<"success" | "error" | "canceled" | "timeout", [import("convex/values").VLiteral<"success", "required">, import("convex/values").VLiteral<"error", "required">, import("convex/values").VLiteral<"canceled", "required">, import("convex/values").VLiteral<"timeout", "required">], "required", never>;
|
|
3
|
+
export type CompletionStatus = Infer<typeof completionStatus>;
|
|
4
|
+
/**
|
|
5
|
+
Data flow:
|
|
6
|
+
|
|
7
|
+
- The mutation `mainLoop` runs periodically and serially.
|
|
8
|
+
- Several tables act as queues, with client-driven mutations enqueueing at high
|
|
9
|
+
timestamps and `mainLoop` popping at low timestamps:
|
|
10
|
+
pendingStart, pendingCompletion, and pendingCancelation.
|
|
11
|
+
- The `enqueue` mutation writes to pendingStart.
|
|
12
|
+
- The `cancel` mutation writes to pendingCancelation.
|
|
13
|
+
- The `saveResult` mutation, run as part of scheduled work, writes to pendingCompletion.
|
|
14
|
+
- mainLoop processes the queues:
|
|
15
|
+
- pendingStart => inProgressWork.
|
|
16
|
+
- pendingCompletion and pendingCancelation => completedWork.
|
|
17
|
+
- inProgressWork that finishes uncleanly (timeout or system failure) => completedWork.
|
|
18
|
+
- `mainLoop` schedules itself to run.
|
|
19
|
+
- `enqueue`, `cancel`, and `saveResult` mutations check when `mainLoop` is scheduled to run,
|
|
20
|
+
and if it's too far in the future, they schedule it to run sooner.
|
|
21
|
+
- `status` query reads from pendingWork and completedWork.
|
|
22
|
+
- `cleanup` mutation deletes old rows from completedWork.
|
|
23
|
+
|
|
24
|
+
To avoid OCCs, we restrict which mutations can read and write from each table:
|
|
25
|
+
- pools: read by all, written only when static Workpool options change.
|
|
26
|
+
- mainLoop (table): read by all, written mostly by `mainLoop`.
|
|
27
|
+
If `mainLoop` will not run for a while, mainLoop table is written by `enqueue`, `cancel`, or `saveResult`.
|
|
28
|
+
- pendingWork: `enqueue` inserts at high timestamps, `mainLoop` pops at low timestamps. `status` query does point-reads.
|
|
29
|
+
- pendingCompletion: `saveResult` inserts at high timestamps, `mainLoop` pops at low timestamps.
|
|
30
|
+
- pendingCancelation: `cancel` inserts at high timestamps, `mainLoop` pops at low timestamps.
|
|
31
|
+
- inProgressWork: `mainLoop` inserts, reads all, and deletes.
|
|
32
|
+
- completedWork: `mainLoop` inserts at hight timestamps, `status` query reads, `cleanup` deletes at low timestamps.
|
|
33
|
+
|
|
34
|
+
*/
|
|
35
|
+
declare const _default: import("convex/server").SchemaDefinition<{
|
|
36
|
+
pool: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
37
|
+
maxParallelism: number;
|
|
38
|
+
statusTtl: number;
|
|
39
|
+
logLevel: "DEBUG" | "INFO" | "WARN" | "ERROR";
|
|
40
|
+
}, {
|
|
41
|
+
maxParallelism: import("convex/values").VFloat64<number, "required">;
|
|
42
|
+
statusTtl: import("convex/values").VFloat64<number, "required">;
|
|
43
|
+
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>;
|
|
44
|
+
}, "required", "maxParallelism" | "statusTtl" | "logLevel">, {}, {}, {}>;
|
|
45
|
+
mainLoop: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
46
|
+
state: {
|
|
47
|
+
kind: "running";
|
|
48
|
+
} | {
|
|
49
|
+
kind: "scheduled";
|
|
50
|
+
runAtTime: number;
|
|
51
|
+
fn: import("convex/values").GenericId<"_scheduled_functions">;
|
|
52
|
+
} | {
|
|
53
|
+
kind: "idle";
|
|
54
|
+
};
|
|
55
|
+
}, {
|
|
56
|
+
state: import("convex/values").VUnion<{
|
|
57
|
+
kind: "running";
|
|
58
|
+
} | {
|
|
59
|
+
kind: "scheduled";
|
|
60
|
+
runAtTime: number;
|
|
61
|
+
fn: import("convex/values").GenericId<"_scheduled_functions">;
|
|
62
|
+
} | {
|
|
63
|
+
kind: "idle";
|
|
64
|
+
}, [import("convex/values").VObject<{
|
|
65
|
+
kind: "running";
|
|
66
|
+
}, {
|
|
67
|
+
kind: import("convex/values").VLiteral<"running", "required">;
|
|
68
|
+
}, "required", "kind">, import("convex/values").VObject<{
|
|
69
|
+
kind: "scheduled";
|
|
70
|
+
runAtTime: number;
|
|
71
|
+
fn: import("convex/values").GenericId<"_scheduled_functions">;
|
|
72
|
+
}, {
|
|
73
|
+
kind: import("convex/values").VLiteral<"scheduled", "required">;
|
|
74
|
+
runAtTime: import("convex/values").VFloat64<number, "required">;
|
|
75
|
+
fn: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">;
|
|
76
|
+
}, "required", "kind" | "runAtTime" | "fn">, import("convex/values").VObject<{
|
|
77
|
+
kind: "idle";
|
|
78
|
+
}, {
|
|
79
|
+
kind: import("convex/values").VLiteral<"idle", "required">;
|
|
80
|
+
}, "required", "kind">], "required", "kind" | "runAtTime" | "fn">;
|
|
81
|
+
}, "required", "state" | "state.kind" | "state.runAtTime" | "state.fn">, {}, {}, {}>;
|
|
82
|
+
work: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
83
|
+
fnType: "action" | "mutation";
|
|
84
|
+
fnHandle: string;
|
|
85
|
+
fnName: string;
|
|
86
|
+
fnArgs: any;
|
|
87
|
+
}, {
|
|
88
|
+
fnType: import("convex/values").VUnion<"action" | "mutation", [import("convex/values").VLiteral<"action", "required">, import("convex/values").VLiteral<"mutation", "required">], "required", never>;
|
|
89
|
+
fnHandle: import("convex/values").VString<string, "required">;
|
|
90
|
+
fnName: import("convex/values").VString<string, "required">;
|
|
91
|
+
fnArgs: import("convex/values").VAny<any, "required", string>;
|
|
92
|
+
}, "required", "fnType" | "fnHandle" | "fnName" | "fnArgs" | `fnArgs.${string}`>, {}, {}, {}>;
|
|
93
|
+
pendingStart: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
94
|
+
workId: import("convex/values").GenericId<"work">;
|
|
95
|
+
}, {
|
|
96
|
+
workId: import("convex/values").VId<import("convex/values").GenericId<"work">, "required">;
|
|
97
|
+
}, "required", "workId">, {
|
|
98
|
+
workId: ["workId", "_creationTime"];
|
|
99
|
+
}, {}, {}>;
|
|
100
|
+
pendingCompletion: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
101
|
+
workId: import("convex/values").GenericId<"work">;
|
|
102
|
+
generation: number;
|
|
103
|
+
completionStatus: "success" | "error" | "canceled" | "timeout";
|
|
104
|
+
}, {
|
|
105
|
+
generation: import("convex/values").VFloat64<number, "required">;
|
|
106
|
+
completionStatus: import("convex/values").VUnion<"success" | "error" | "canceled" | "timeout", [import("convex/values").VLiteral<"success", "required">, import("convex/values").VLiteral<"error", "required">, import("convex/values").VLiteral<"canceled", "required">, import("convex/values").VLiteral<"timeout", "required">], "required", never>;
|
|
107
|
+
workId: import("convex/values").VId<import("convex/values").GenericId<"work">, "required">;
|
|
108
|
+
}, "required", "workId" | "generation" | "completionStatus">, {
|
|
109
|
+
workId: ["workId", "_creationTime"];
|
|
110
|
+
generation: ["generation", "_creationTime"];
|
|
111
|
+
}, {}, {}>;
|
|
112
|
+
pendingCancelation: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
113
|
+
workId: import("convex/values").GenericId<"work">;
|
|
114
|
+
}, {
|
|
115
|
+
workId: import("convex/values").VId<import("convex/values").GenericId<"work">, "required">;
|
|
116
|
+
}, "required", "workId">, {}, {}, {}>;
|
|
117
|
+
inProgressWork: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
118
|
+
running: import("convex/values").GenericId<"_scheduled_functions">;
|
|
119
|
+
workId: import("convex/values").GenericId<"work">;
|
|
120
|
+
timeoutMs: number | null;
|
|
121
|
+
}, {
|
|
122
|
+
running: import("convex/values").VId<import("convex/values").GenericId<"_scheduled_functions">, "required">;
|
|
123
|
+
timeoutMs: import("convex/values").VUnion<number | null, [import("convex/values").VFloat64<number, "required">, import("convex/values").VNull<null, "required">], "required", never>;
|
|
124
|
+
workId: import("convex/values").VId<import("convex/values").GenericId<"work">, "required">;
|
|
125
|
+
}, "required", "running" | "workId" | "timeoutMs">, {
|
|
126
|
+
workId: ["workId", "_creationTime"];
|
|
127
|
+
}, {}, {}>;
|
|
128
|
+
inProgressCount: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
129
|
+
count: number;
|
|
130
|
+
}, {
|
|
131
|
+
count: import("convex/values").VFloat64<number, "required">;
|
|
132
|
+
}, "required", "count">, {}, {}, {}>;
|
|
133
|
+
completedWork: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
134
|
+
workId: import("convex/values").GenericId<"work">;
|
|
135
|
+
completionStatus: "success" | "error" | "canceled" | "timeout";
|
|
136
|
+
}, {
|
|
137
|
+
completionStatus: import("convex/values").VUnion<"success" | "error" | "canceled" | "timeout", [import("convex/values").VLiteral<"success", "required">, import("convex/values").VLiteral<"error", "required">, import("convex/values").VLiteral<"canceled", "required">, import("convex/values").VLiteral<"timeout", "required">], "required", never>;
|
|
138
|
+
workId: import("convex/values").VId<import("convex/values").GenericId<"work">, "required">;
|
|
139
|
+
}, "required", "workId" | "completionStatus">, {
|
|
140
|
+
workId: ["workId", "_creationTime"];
|
|
141
|
+
}, {}, {}>;
|
|
142
|
+
completionGeneration: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
143
|
+
generation: number;
|
|
144
|
+
}, {
|
|
145
|
+
generation: import("convex/values").VFloat64<number, "required">;
|
|
146
|
+
}, "required", "generation">, {}, {}, {}>;
|
|
147
|
+
}, true>;
|
|
148
|
+
export default _default;
|
|
149
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/component/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAK,MAAM,eAAe,CAAC;AAGzC,eAAO,MAAM,gBAAgB,sUAK5B,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,wBA0DG"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { defineSchema, defineTable } from "convex/server";
|
|
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
|
+
*/
|
|
36
|
+
export default defineSchema({
|
|
37
|
+
// Statically configured, singleton.
|
|
38
|
+
pool: defineTable({
|
|
39
|
+
maxParallelism: v.number(),
|
|
40
|
+
statusTtl: v.number(),
|
|
41
|
+
logLevel,
|
|
42
|
+
}),
|
|
43
|
+
mainLoop: defineTable({
|
|
44
|
+
state: v.union(v.object({ kind: v.literal("running") }), v.object({
|
|
45
|
+
kind: v.literal("scheduled"),
|
|
46
|
+
runAtTime: v.number(),
|
|
47
|
+
fn: v.id("_scheduled_functions"),
|
|
48
|
+
}), v.object({ kind: v.literal("idle") })),
|
|
49
|
+
}),
|
|
50
|
+
work: defineTable({
|
|
51
|
+
fnType: v.union(v.literal("action"), v.literal("mutation")),
|
|
52
|
+
fnHandle: v.string(),
|
|
53
|
+
fnName: v.string(),
|
|
54
|
+
fnArgs: v.any(),
|
|
55
|
+
}),
|
|
56
|
+
pendingStart: defineTable({
|
|
57
|
+
workId: v.id("work"),
|
|
58
|
+
}).index("workId", ["workId"]),
|
|
59
|
+
pendingCompletion: defineTable({
|
|
60
|
+
generation: v.number(),
|
|
61
|
+
completionStatus,
|
|
62
|
+
workId: v.id("work"),
|
|
63
|
+
})
|
|
64
|
+
.index("workId", ["workId"])
|
|
65
|
+
.index("generation", ["generation"]),
|
|
66
|
+
pendingCancelation: defineTable({
|
|
67
|
+
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
|
+
});
|
|
85
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/component/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Doc } from "./_generated/dataModel";
|
|
2
|
+
/**
|
|
3
|
+
* Record stats about work execution. Intended to be queried by Axiom or Datadog.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Sample axiom dashboard query:
|
|
7
|
+
|
|
8
|
+
workpool
|
|
9
|
+
| extend parsed_message = iff(
|
|
10
|
+
isnotnull(parse_json(trim("'", tostring(["data.message"])))),
|
|
11
|
+
parse_json(trim("'", tostring(["data.message"]))),
|
|
12
|
+
parse_json('{}')
|
|
13
|
+
)
|
|
14
|
+
| extend lagSinceEnqueued = parsed_message["lagSinceEnqueued"]
|
|
15
|
+
| extend fnName = parsed_message["fnName"]
|
|
16
|
+
| summarize avg(todouble(lagSinceEnqueued)) by bin_auto(_time), tostring(fnName)
|
|
17
|
+
|
|
18
|
+
*/
|
|
19
|
+
export declare function recordStarted(work: Doc<"work">): string;
|
|
20
|
+
export declare function recordCompleted(work: Doc<"work">, status: "success" | "error" | "canceled" | "timeout"): string;
|
|
21
|
+
/**
|
|
22
|
+
* Warning: this should not be used from a mutation, as it will cause conflicts.
|
|
23
|
+
* Use this to debug or diagnose your queue length when it's backed up.
|
|
24
|
+
*/
|
|
25
|
+
export declare const queueLength: import("convex/server").RegisteredQuery<"internal", {}, Promise<any>>;
|
|
26
|
+
/**
|
|
27
|
+
* Warning: this should not be used from a mutation, as it will cause conflicts.
|
|
28
|
+
* Use this while developing to see the state of the queue.
|
|
29
|
+
*/
|
|
30
|
+
export declare const debugCounts: import("convex/server").RegisteredQuery<"internal", {}, Promise<{
|
|
31
|
+
pendingStart: any;
|
|
32
|
+
inProgressWork: any;
|
|
33
|
+
pendingCompletion: any;
|
|
34
|
+
pendingCancelation: any;
|
|
35
|
+
active: number;
|
|
36
|
+
}>>;
|
|
37
|
+
//# sourceMappingURL=stats.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { v } from "convex/values";
|
|
2
|
+
import { internalQuery } from "./_generated/server";
|
|
3
|
+
/**
|
|
4
|
+
* Record stats about work execution. Intended to be queried by Axiom or Datadog.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Sample axiom dashboard query:
|
|
8
|
+
|
|
9
|
+
workpool
|
|
10
|
+
| extend parsed_message = iff(
|
|
11
|
+
isnotnull(parse_json(trim("'", tostring(["data.message"])))),
|
|
12
|
+
parse_json(trim("'", tostring(["data.message"]))),
|
|
13
|
+
parse_json('{}')
|
|
14
|
+
)
|
|
15
|
+
| extend lagSinceEnqueued = parsed_message["lagSinceEnqueued"]
|
|
16
|
+
| extend fnName = parsed_message["fnName"]
|
|
17
|
+
| summarize avg(todouble(lagSinceEnqueued)) by bin_auto(_time), tostring(fnName)
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
export function recordStarted(work) {
|
|
21
|
+
return JSON.stringify({
|
|
22
|
+
workId: work._id,
|
|
23
|
+
event: "started",
|
|
24
|
+
fnName: work.fnName,
|
|
25
|
+
enqueuedAt: work._creationTime,
|
|
26
|
+
startedAt: Date.now(),
|
|
27
|
+
lagSinceEnqueued: Date.now() - work._creationTime,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export function recordCompleted(work, status) {
|
|
31
|
+
return JSON.stringify({
|
|
32
|
+
workId: work._id,
|
|
33
|
+
event: "completed",
|
|
34
|
+
fnName: work.fnName,
|
|
35
|
+
completedAt: Date.now(),
|
|
36
|
+
status,
|
|
37
|
+
lagSinceEnqueued: Date.now() - work._creationTime,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Warning: this should not be used from a mutation, as it will cause conflicts.
|
|
42
|
+
* Use this to debug or diagnose your queue length when it's backed up.
|
|
43
|
+
*/
|
|
44
|
+
export const queueLength = internalQuery({
|
|
45
|
+
args: {},
|
|
46
|
+
returns: v.number(),
|
|
47
|
+
handler: async (ctx) => {
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
49
|
+
return ctx.db.query("pendingStart").count();
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
/**
|
|
53
|
+
* Warning: this should not be used from a mutation, as it will cause conflicts.
|
|
54
|
+
* Use this while developing to see the state of the queue.
|
|
55
|
+
*/
|
|
56
|
+
export const debugCounts = internalQuery({
|
|
57
|
+
args: {},
|
|
58
|
+
returns: v.any(),
|
|
59
|
+
handler: async (ctx) => {
|
|
60
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
61
|
+
const inProgressWork = await ctx.db.query("inProgressWork").count();
|
|
62
|
+
const pendingStart = await ctx.db.query("pendingStart").count();
|
|
63
|
+
const pendingCompletion = await ctx.db.query("pendingCompletion").count();
|
|
64
|
+
const pendingCancelation = await ctx.db.query("pendingCancelation").count();
|
|
65
|
+
return {
|
|
66
|
+
pendingStart,
|
|
67
|
+
inProgressWork,
|
|
68
|
+
pendingCompletion,
|
|
69
|
+
pendingCancelation,
|
|
70
|
+
active: inProgressWork - pendingCompletion - pendingCancelation,
|
|
71
|
+
};
|
|
72
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@convex-dev/workpool",
|
|
3
|
+
"description": "A Convex component for managing async work.",
|
|
4
|
+
"repository": "github:get-convex/workpool",
|
|
5
|
+
"homepage": "https://github.com/get-convex/workpool#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"email": "support@convex.dev",
|
|
8
|
+
"url": "https://github.com/get-convex/workpool/issues"
|
|
9
|
+
},
|
|
10
|
+
"version": "0.1.0",
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"convex",
|
|
14
|
+
"queue",
|
|
15
|
+
"pool",
|
|
16
|
+
"component",
|
|
17
|
+
"async",
|
|
18
|
+
"work"
|
|
19
|
+
],
|
|
20
|
+
"type": "module",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "npm run build:esm && npm run build:cjs",
|
|
23
|
+
"build:esm": "tsc --project ./esm.json && echo '{\\n \"type\": \"module\"\\n}' > dist/esm/package.json",
|
|
24
|
+
"build:cjs": "tsc --project ./commonjs.json && echo '{\\n \"type\": \"commonjs\"\\n}' > dist/commonjs/package.json",
|
|
25
|
+
"dev": "cd example; npm run dev",
|
|
26
|
+
"typecheck": "tsc --noEmit",
|
|
27
|
+
"prepare": "npm run build",
|
|
28
|
+
"prepack": "node node10stubs.mjs",
|
|
29
|
+
"postpack": "node node10stubs.mjs --cleanup",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"lint": "tsc --noEmit && eslint . && prettier --check .",
|
|
32
|
+
"format": "prettier --write .",
|
|
33
|
+
"test:debug": "vitest --inspect-brk --no-file-parallelism",
|
|
34
|
+
"test:coverage": "vitest run --coverage --coverage.reporter=text"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"src",
|
|
39
|
+
"react"
|
|
40
|
+
],
|
|
41
|
+
"exports": {
|
|
42
|
+
"./package.json": "./package.json",
|
|
43
|
+
".": {
|
|
44
|
+
"import": {
|
|
45
|
+
"@convex-dev/component-source": "./src/client/index.ts",
|
|
46
|
+
"types": "./dist/esm/client/index.d.ts",
|
|
47
|
+
"default": "./dist/esm/client/index.js"
|
|
48
|
+
},
|
|
49
|
+
"require": {
|
|
50
|
+
"@convex-dev/component-source": "./src/client/index.ts",
|
|
51
|
+
"types": "./dist/commonjs/client/index.d.ts",
|
|
52
|
+
"default": "./dist/commonjs/client/index.js"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"./convex.config": {
|
|
56
|
+
"import": {
|
|
57
|
+
"@convex-dev/component-source": "./src/component/convex.config.ts",
|
|
58
|
+
"types": "./dist/esm/component/convex.config.d.ts",
|
|
59
|
+
"default": "./dist/esm/component/convex.config.js"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"convex": "^1.17.0 || ^1.18.0"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@eslint/js": "^9.9.1",
|
|
68
|
+
"@types/node": "^18.17.0",
|
|
69
|
+
"convex-test": "^0.0.35",
|
|
70
|
+
"eslint": "^9.9.1",
|
|
71
|
+
"globals": "^15.9.0",
|
|
72
|
+
"prettier": "3.2.5",
|
|
73
|
+
"typescript": "~5.0.3",
|
|
74
|
+
"typescript-eslint": "^8.4.0",
|
|
75
|
+
"vitest": "^2.1.4"
|
|
76
|
+
},
|
|
77
|
+
"main": "./dist/commonjs/client/index.js",
|
|
78
|
+
"types": "./dist/commonjs/client/index.d.ts",
|
|
79
|
+
"module": "./dist/esm/client/index.js",
|
|
80
|
+
"dependencies": {
|
|
81
|
+
"@convex-dev/crons": "^0.1.5"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createFunctionHandle,
|
|
3
|
+
DefaultFunctionArgs,
|
|
4
|
+
Expand,
|
|
5
|
+
FunctionReference,
|
|
6
|
+
FunctionVisibility,
|
|
7
|
+
GenericDataModel,
|
|
8
|
+
GenericMutationCtx,
|
|
9
|
+
GenericQueryCtx,
|
|
10
|
+
getFunctionName,
|
|
11
|
+
} from "convex/server";
|
|
12
|
+
import { GenericId } from "convex/values";
|
|
13
|
+
import { api } from "../component/_generated/api";
|
|
14
|
+
import { LogLevel } from "../component/logging";
|
|
15
|
+
import { completionStatus, type CompletionStatus } from "../component/schema";
|
|
16
|
+
export { completionStatus, type CompletionStatus };
|
|
17
|
+
|
|
18
|
+
export type WorkId = string;
|
|
19
|
+
|
|
20
|
+
export class Workpool {
|
|
21
|
+
constructor(
|
|
22
|
+
private component: UseApi<typeof api>,
|
|
23
|
+
private options: {
|
|
24
|
+
/** How many actions/mutations can be running at once within this pool.
|
|
25
|
+
* Min 1, Max 300.
|
|
26
|
+
*/
|
|
27
|
+
maxParallelism: number;
|
|
28
|
+
/** How much to log.
|
|
29
|
+
* Default WARN.
|
|
30
|
+
* With INFO, you can see events for started and completed work, which can
|
|
31
|
+
* be parsed.
|
|
32
|
+
* With DEBUG, you can see timers and internal events for work being
|
|
33
|
+
* scheduled.
|
|
34
|
+
*/
|
|
35
|
+
logLevel?: LogLevel;
|
|
36
|
+
/** How long to keep completed work in the database, for access by `status`.
|
|
37
|
+
* Default 1 day.
|
|
38
|
+
*/
|
|
39
|
+
statusTtl?: number;
|
|
40
|
+
}
|
|
41
|
+
) {}
|
|
42
|
+
async enqueueAction<Args extends DefaultFunctionArgs, ReturnType>(
|
|
43
|
+
ctx: RunMutationCtx,
|
|
44
|
+
fn: FunctionReference<"action", FunctionVisibility, Args, ReturnType>,
|
|
45
|
+
fnArgs: Args
|
|
46
|
+
): Promise<WorkId> {
|
|
47
|
+
const fnHandle = await createFunctionHandle(fn);
|
|
48
|
+
const id = await ctx.runMutation(this.component.lib.enqueue, {
|
|
49
|
+
fnHandle,
|
|
50
|
+
fnName: getFunctionName(fn),
|
|
51
|
+
fnArgs,
|
|
52
|
+
fnType: "action",
|
|
53
|
+
options: this.options,
|
|
54
|
+
});
|
|
55
|
+
return id as WorkId;
|
|
56
|
+
}
|
|
57
|
+
async enqueueMutation<Args extends DefaultFunctionArgs, ReturnType>(
|
|
58
|
+
ctx: RunMutationCtx,
|
|
59
|
+
fn: FunctionReference<"mutation", FunctionVisibility, Args, ReturnType>,
|
|
60
|
+
fnArgs: Args
|
|
61
|
+
): Promise<WorkId> {
|
|
62
|
+
const fnHandle = await createFunctionHandle(fn);
|
|
63
|
+
const id = await ctx.runMutation(this.component.lib.enqueue, {
|
|
64
|
+
fnHandle,
|
|
65
|
+
fnName: getFunctionName(fn),
|
|
66
|
+
fnArgs,
|
|
67
|
+
fnType: "mutation",
|
|
68
|
+
options: this.options,
|
|
69
|
+
});
|
|
70
|
+
return id as WorkId;
|
|
71
|
+
}
|
|
72
|
+
async cancel(ctx: RunMutationCtx, id: WorkId): Promise<void> {
|
|
73
|
+
await ctx.runMutation(this.component.lib.cancel, { id });
|
|
74
|
+
}
|
|
75
|
+
async status(
|
|
76
|
+
ctx: RunQueryCtx,
|
|
77
|
+
id: WorkId
|
|
78
|
+
): Promise<
|
|
79
|
+
| { kind: "pending" }
|
|
80
|
+
| { kind: "inProgress" }
|
|
81
|
+
| { kind: "completed"; completionStatus: CompletionStatus }
|
|
82
|
+
> {
|
|
83
|
+
return await ctx.runQuery(this.component.lib.status, { id });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Type utils follow */
|
|
88
|
+
|
|
89
|
+
type RunQueryCtx = {
|
|
90
|
+
runQuery: GenericQueryCtx<GenericDataModel>["runQuery"];
|
|
91
|
+
};
|
|
92
|
+
type RunMutationCtx = {
|
|
93
|
+
runMutation: GenericMutationCtx<GenericDataModel>["runMutation"];
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type OpaqueIds<T> =
|
|
97
|
+
T extends GenericId<infer _T>
|
|
98
|
+
? string
|
|
99
|
+
: T extends (infer U)[]
|
|
100
|
+
? OpaqueIds<U>[]
|
|
101
|
+
: T extends object
|
|
102
|
+
? { [K in keyof T]: OpaqueIds<T[K]> }
|
|
103
|
+
: T;
|
|
104
|
+
|
|
105
|
+
export type UseApi<API> = Expand<{
|
|
106
|
+
[mod in keyof API]: API[mod] extends FunctionReference<
|
|
107
|
+
infer FType,
|
|
108
|
+
"public",
|
|
109
|
+
infer FArgs,
|
|
110
|
+
infer FReturnType,
|
|
111
|
+
infer FComponentPath
|
|
112
|
+
>
|
|
113
|
+
? FunctionReference<
|
|
114
|
+
FType,
|
|
115
|
+
"internal",
|
|
116
|
+
OpaqueIds<FArgs>,
|
|
117
|
+
OpaqueIds<FReturnType>,
|
|
118
|
+
FComponentPath
|
|
119
|
+
>
|
|
120
|
+
: UseApi<API[mod]>;
|
|
121
|
+
}>;
|