@convex-dev/workpool 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -3
- package/dist/commonjs/client/index.d.ts +30 -5
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +27 -2
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/component/complete.d.ts.map +1 -1
- package/dist/commonjs/component/complete.js +9 -7
- package/dist/commonjs/component/complete.js.map +1 -1
- package/dist/commonjs/component/kick.d.ts +3 -2
- package/dist/commonjs/component/kick.d.ts.map +1 -1
- package/dist/commonjs/component/kick.js +12 -9
- package/dist/commonjs/component/kick.js.map +1 -1
- package/dist/commonjs/component/lib.d.ts +3 -3
- package/dist/commonjs/component/lib.d.ts.map +1 -1
- package/dist/commonjs/component/lib.js +25 -19
- package/dist/commonjs/component/lib.js.map +1 -1
- package/dist/commonjs/component/logging.d.ts +3 -2
- package/dist/commonjs/component/logging.d.ts.map +1 -1
- package/dist/commonjs/component/logging.js +34 -15
- package/dist/commonjs/component/logging.js.map +1 -1
- package/dist/commonjs/component/loop.js +10 -10
- package/dist/commonjs/component/loop.js.map +1 -1
- package/dist/commonjs/component/recovery.d.ts +29 -0
- package/dist/commonjs/component/recovery.d.ts.map +1 -1
- package/dist/commonjs/component/recovery.js +69 -66
- package/dist/commonjs/component/recovery.js.map +1 -1
- package/dist/commonjs/component/schema.d.ts +11 -11
- package/dist/commonjs/component/shared.d.ts +4 -4
- package/dist/commonjs/component/shared.d.ts.map +1 -1
- package/dist/commonjs/component/shared.js +2 -2
- package/dist/commonjs/component/shared.js.map +1 -1
- package/dist/commonjs/component/stats.d.ts +20 -21
- package/dist/commonjs/component/stats.d.ts.map +1 -1
- package/dist/commonjs/component/stats.js +86 -38
- package/dist/commonjs/component/stats.js.map +1 -1
- package/dist/commonjs/component/worker.d.ts +2 -2
- package/dist/esm/client/index.d.ts +30 -5
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +27 -2
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/component/complete.d.ts.map +1 -1
- package/dist/esm/component/complete.js +9 -7
- package/dist/esm/component/complete.js.map +1 -1
- package/dist/esm/component/kick.d.ts +3 -2
- package/dist/esm/component/kick.d.ts.map +1 -1
- package/dist/esm/component/kick.js +12 -9
- package/dist/esm/component/kick.js.map +1 -1
- package/dist/esm/component/lib.d.ts +3 -3
- package/dist/esm/component/lib.d.ts.map +1 -1
- package/dist/esm/component/lib.js +25 -19
- package/dist/esm/component/lib.js.map +1 -1
- package/dist/esm/component/logging.d.ts +3 -2
- package/dist/esm/component/logging.d.ts.map +1 -1
- package/dist/esm/component/logging.js +34 -15
- package/dist/esm/component/logging.js.map +1 -1
- package/dist/esm/component/loop.js +10 -10
- package/dist/esm/component/loop.js.map +1 -1
- package/dist/esm/component/recovery.d.ts +29 -0
- package/dist/esm/component/recovery.d.ts.map +1 -1
- package/dist/esm/component/recovery.js +69 -66
- package/dist/esm/component/recovery.js.map +1 -1
- package/dist/esm/component/schema.d.ts +11 -11
- package/dist/esm/component/shared.d.ts +4 -4
- package/dist/esm/component/shared.d.ts.map +1 -1
- package/dist/esm/component/shared.js +2 -2
- package/dist/esm/component/shared.js.map +1 -1
- package/dist/esm/component/stats.d.ts +20 -21
- package/dist/esm/component/stats.d.ts.map +1 -1
- package/dist/esm/component/stats.js +86 -38
- package/dist/esm/component/stats.js.map +1 -1
- package/dist/esm/component/worker.d.ts +2 -2
- package/package.json +6 -7
- package/src/client/index.ts +64 -35
- package/src/component/_generated/api.d.ts +6 -6
- package/src/component/complete.ts +18 -7
- package/src/component/kick.test.ts +17 -7
- package/src/component/kick.ts +14 -11
- package/src/component/lib.ts +33 -26
- package/src/component/logging.test.ts +16 -0
- package/src/component/logging.ts +45 -23
- package/src/component/loop.test.ts +12 -12
- package/src/component/loop.ts +11 -11
- package/src/component/recovery.test.ts +6 -11
- package/src/component/recovery.ts +77 -69
- package/src/component/shared.ts +2 -2
- package/src/component/stats.test.ts +345 -0
- package/src/component/stats.ts +111 -41
package/src/component/stats.ts
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
import { v } from "convex/values";
|
|
2
2
|
import { Doc, Id } from "./_generated/dataModel.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import {
|
|
4
|
+
internalMutation,
|
|
5
|
+
internalQuery,
|
|
6
|
+
MutationCtx,
|
|
7
|
+
} from "./_generated/server.js";
|
|
8
|
+
import {
|
|
9
|
+
Config,
|
|
10
|
+
DEFAULT_MAX_PARALLELISM,
|
|
11
|
+
getCurrentSegment,
|
|
12
|
+
} from "./shared.js";
|
|
13
|
+
import { createLogger, Logger, logLevel, shouldLog } from "./logging.js";
|
|
14
|
+
import { internal } from "./_generated/api.js";
|
|
15
|
+
import schema from "./schema.js";
|
|
16
|
+
import { paginator } from "convex-helpers/server/pagination";
|
|
6
17
|
|
|
7
|
-
|
|
8
|
-
* Record stats about work execution. Intended to be queried by Axiom or Datadog.
|
|
9
|
-
*/
|
|
18
|
+
const BACKLOG_BATCH_SIZE = 100;
|
|
10
19
|
|
|
11
20
|
/**
|
|
12
|
-
*
|
|
13
|
-
|
|
14
|
-
workpool
|
|
15
|
-
| extend parsed_message = iff(
|
|
16
|
-
isnotnull(parse_json(trim("'", tostring(["data.message"])))),
|
|
17
|
-
parse_json(trim("'", tostring(["data.message"]))),
|
|
18
|
-
parse_json('{}')
|
|
19
|
-
)
|
|
20
|
-
| extend startLag = parsed_message["startLag"]
|
|
21
|
-
| extend fnName = parsed_message["fnName"]
|
|
22
|
-
| summarize avg(todouble(startLag)) by bin_auto(_time), tostring(fnName)
|
|
23
|
-
|
|
21
|
+
* Record stats about work execution. Intended to be queried by Axiom or Datadog.
|
|
22
|
+
* See the [README](https://github.com/get-convex/workpool) for example queries.
|
|
24
23
|
*/
|
|
25
24
|
|
|
26
25
|
export function recordEnqueued(
|
|
@@ -65,38 +64,109 @@ export function recordCompleted(
|
|
|
65
64
|
});
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
export function
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
67
|
+
export async function generateReport(
|
|
68
|
+
ctx: MutationCtx,
|
|
69
|
+
console: Logger,
|
|
70
|
+
state: Doc<"internalState">,
|
|
71
|
+
{ maxParallelism, logLevel }: Config
|
|
72
|
+
) {
|
|
73
|
+
if (!shouldLog(logLevel, "REPORT")) {
|
|
74
|
+
// Don't waste time if we're not going to log.
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const currentSegment = getCurrentSegment();
|
|
78
|
+
const pendingStart = await paginator(ctx.db, schema)
|
|
79
|
+
.query("pendingStart")
|
|
80
|
+
.withIndex("segment", (q) =>
|
|
81
|
+
q
|
|
82
|
+
.gte("segment", state.segmentCursors.incoming)
|
|
83
|
+
.lt("segment", currentSegment)
|
|
84
|
+
)
|
|
85
|
+
.paginate({
|
|
86
|
+
numItems: maxParallelism,
|
|
87
|
+
cursor: null,
|
|
88
|
+
});
|
|
89
|
+
if (pendingStart.isDone) {
|
|
90
|
+
recordReport(console, {
|
|
91
|
+
...state.report,
|
|
92
|
+
running: state.running.length,
|
|
93
|
+
backlog: pendingStart.page.length,
|
|
94
|
+
});
|
|
95
|
+
} else {
|
|
96
|
+
await ctx.scheduler.runAfter(0, internal.stats.calculateBacklogAndReport, {
|
|
97
|
+
startSegment: state.segmentCursors.incoming,
|
|
98
|
+
endSegment: currentSegment,
|
|
99
|
+
cursor: pendingStart.continueCursor,
|
|
100
|
+
report: state.report,
|
|
101
|
+
running: state.running.length,
|
|
102
|
+
logLevel,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
80
105
|
}
|
|
81
106
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
107
|
+
export const calculateBacklogAndReport = internalMutation({
|
|
108
|
+
args: {
|
|
109
|
+
startSegment: v.int64(),
|
|
110
|
+
endSegment: v.int64(),
|
|
111
|
+
cursor: v.string(),
|
|
112
|
+
report: schema.tables.internalState.validator.fields.report,
|
|
113
|
+
running: v.number(),
|
|
114
|
+
logLevel,
|
|
115
|
+
},
|
|
116
|
+
handler: async (ctx, args) => {
|
|
117
|
+
const pendingStart = await paginator(ctx.db, schema)
|
|
118
|
+
.query("pendingStart")
|
|
119
|
+
.withIndex("segment", (q) =>
|
|
120
|
+
q.gte("segment", args.startSegment).lt("segment", args.endSegment)
|
|
121
|
+
)
|
|
122
|
+
.paginate({
|
|
123
|
+
numItems: BACKLOG_BATCH_SIZE,
|
|
124
|
+
cursor: args.cursor,
|
|
125
|
+
});
|
|
126
|
+
const console = createLogger(args.logLevel);
|
|
127
|
+
if (pendingStart.isDone) {
|
|
128
|
+
recordReport(console, {
|
|
129
|
+
...args.report,
|
|
130
|
+
running: args.running,
|
|
131
|
+
backlog: pendingStart.page.length,
|
|
132
|
+
});
|
|
133
|
+
} else {
|
|
134
|
+
await ctx.scheduler.runAfter(
|
|
135
|
+
0,
|
|
136
|
+
internal.stats.calculateBacklogAndReport,
|
|
137
|
+
{
|
|
138
|
+
startSegment: args.startSegment,
|
|
139
|
+
endSegment: args.endSegment,
|
|
140
|
+
cursor: pendingStart.continueCursor,
|
|
141
|
+
report: args.report,
|
|
142
|
+
running: args.running,
|
|
143
|
+
logLevel: args.logLevel,
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
}
|
|
92
147
|
},
|
|
93
148
|
});
|
|
94
149
|
|
|
150
|
+
function recordReport(
|
|
151
|
+
console: Logger,
|
|
152
|
+
report: Doc<"internalState">["report"] & { running: number; backlog: number }
|
|
153
|
+
) {
|
|
154
|
+
const { completed, failed, retries } = report;
|
|
155
|
+
const withoutRetries = completed - retries;
|
|
156
|
+
const failureRate = completed ? (failed + retries) / completed : 0;
|
|
157
|
+
const permanentFailureRate = withoutRetries ? failed / withoutRetries : 0;
|
|
158
|
+
console.event("report", {
|
|
159
|
+
...report,
|
|
160
|
+
failureRate: Number(failureRate.toFixed(4)),
|
|
161
|
+
permanentFailureRate: Number(permanentFailureRate.toFixed(4)),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
95
165
|
/**
|
|
96
166
|
* Warning: this should not be used from a mutation, as it will cause conflicts.
|
|
97
167
|
* Use this while developing to see the state of the queue.
|
|
98
168
|
*/
|
|
99
|
-
export const
|
|
169
|
+
export const diagnostics = internalQuery({
|
|
100
170
|
args: {},
|
|
101
171
|
returns: v.any(),
|
|
102
172
|
handler: async (ctx) => {
|