@convex-dev/workpool 0.2.14 → 0.2.16
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 +23 -13
- package/dist/commonjs/client/index.d.ts +191 -56
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +55 -6
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/component/complete.js +2 -2
- package/dist/commonjs/component/complete.js.map +1 -1
- package/dist/commonjs/component/schema.js +2 -2
- package/dist/commonjs/component/schema.js.map +1 -1
- package/dist/commonjs/component/shared.d.ts +2 -2
- package/dist/commonjs/component/shared.d.ts.map +1 -1
- package/dist/commonjs/component/shared.js +1 -1
- package/dist/commonjs/component/shared.js.map +1 -1
- package/dist/commonjs/component/stats.d.ts.map +1 -1
- package/dist/commonjs/component/stats.js +7 -25
- package/dist/commonjs/component/stats.js.map +1 -1
- package/dist/esm/client/index.d.ts +191 -56
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +55 -6
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/component/complete.js +2 -2
- package/dist/esm/component/complete.js.map +1 -1
- package/dist/esm/component/schema.js +2 -2
- package/dist/esm/component/schema.js.map +1 -1
- package/dist/esm/component/shared.d.ts +2 -2
- package/dist/esm/component/shared.d.ts.map +1 -1
- package/dist/esm/component/shared.js +1 -1
- package/dist/esm/component/shared.js.map +1 -1
- package/dist/esm/component/stats.d.ts.map +1 -1
- package/dist/esm/component/stats.js +7 -25
- package/dist/esm/component/stats.js.map +1 -1
- package/package.json +4 -3
- package/src/client/index.ts +145 -59
- package/src/component/complete.ts +2 -2
- package/src/component/kick.test.ts +9 -2
- package/src/component/loop.test.ts +0 -1
- package/src/component/schema.ts +2 -2
- package/src/component/shared.ts +2 -2
- package/src/component/stats.ts +8 -31
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"email": "support@convex.dev",
|
|
8
8
|
"url": "https://github.com/get-convex/workpool/issues"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.2.
|
|
10
|
+
"version": "0.2.16",
|
|
11
11
|
"license": "Apache-2.0",
|
|
12
12
|
"keywords": [
|
|
13
13
|
"convex",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"test:debug": "vitest --inspect-brk --no-file-parallelism",
|
|
32
32
|
"test:coverage": "vitest run --coverage --coverage.reporter=text",
|
|
33
33
|
"alpha": "rm -rf dist && npm run build && npm run test && npm version prerelease --preid alpha && npm publish --tag alpha && git push --tags",
|
|
34
|
-
"release": "rm -rf dist && npm run build && npm run test && npm version patch && npm publish && git push --tags",
|
|
34
|
+
"release": "rm -rf dist && npm run build && npm run test && npm version patch && npm publish && git push --tags && git push",
|
|
35
35
|
"prepare": "npm run build",
|
|
36
36
|
"prepack": "node node10stubs.mjs",
|
|
37
37
|
"postpack": "node node10stubs.mjs --cleanup"
|
|
@@ -72,9 +72,10 @@
|
|
|
72
72
|
"@eslint/js": "^9.9.1",
|
|
73
73
|
"@types/node": "^18.17.0",
|
|
74
74
|
"@vitest/coverage-v8": "^2.1.9",
|
|
75
|
-
"convex-test": "^0.0.
|
|
75
|
+
"convex-test": "^0.0.38-alpha.0",
|
|
76
76
|
"eslint": "^9.9.1",
|
|
77
77
|
"globals": "^15.9.0",
|
|
78
|
+
"pkg-pr-new": "^0.0.54",
|
|
78
79
|
"prettier": "3.2.5",
|
|
79
80
|
"typescript": "^5.8.3",
|
|
80
81
|
"typescript-eslint": "^8.4.0",
|
package/src/client/index.ts
CHANGED
|
@@ -5,29 +5,45 @@ import {
|
|
|
5
5
|
FunctionReference,
|
|
6
6
|
FunctionType,
|
|
7
7
|
FunctionVisibility,
|
|
8
|
+
GenericDataModel,
|
|
9
|
+
GenericMutationCtx,
|
|
8
10
|
getFunctionName,
|
|
11
|
+
internalMutationGeneric,
|
|
12
|
+
RegisteredMutation,
|
|
9
13
|
} from "convex/server";
|
|
10
|
-
import { v, VString } from "convex/values";
|
|
14
|
+
import { Infer, v, Validator, VAny, VString } from "convex/values";
|
|
11
15
|
import { Mounts } from "../component/_generated/api.js";
|
|
12
16
|
import { DEFAULT_LOG_LEVEL, type LogLevel } from "../component/logging.js";
|
|
13
17
|
import {
|
|
14
18
|
Config,
|
|
15
19
|
DEFAULT_MAX_PARALLELISM,
|
|
16
20
|
OnComplete,
|
|
17
|
-
|
|
21
|
+
vResultValidator,
|
|
18
22
|
type RetryBehavior,
|
|
19
23
|
RunResult,
|
|
20
24
|
OnCompleteArgs as SharedOnCompleteArgs,
|
|
21
25
|
Status,
|
|
22
26
|
} from "../component/shared.js";
|
|
23
27
|
import { RunMutationCtx, RunQueryCtx, UseApi } from "./utils.js";
|
|
24
|
-
export {
|
|
28
|
+
export {
|
|
29
|
+
vResultValidator,
|
|
30
|
+
type RunResult,
|
|
31
|
+
type RetryBehavior,
|
|
32
|
+
type OnComplete,
|
|
33
|
+
};
|
|
25
34
|
export {
|
|
26
35
|
retryBehavior as vRetryBehavior,
|
|
27
36
|
onComplete as vOnComplete,
|
|
28
37
|
} from "../component/shared.js";
|
|
29
38
|
export { logLevel as vLogLevel, type LogLevel } from "../component/logging.js";
|
|
30
|
-
export {
|
|
39
|
+
export type WorkId = string & { __isWorkId: true };
|
|
40
|
+
export const vWorkIdValidator = v.string() as VString<WorkId>;
|
|
41
|
+
export {
|
|
42
|
+
/** @deprecated Use `vWorkIdValidator` instead. */
|
|
43
|
+
vWorkIdValidator as workIdValidator,
|
|
44
|
+
/** @deprecated Use `vResultValidator` instead. */
|
|
45
|
+
vResultValidator as resultValidator,
|
|
46
|
+
};
|
|
31
47
|
|
|
32
48
|
// Attempts will run with delay [0, 250, 500, 1000, 2000] (ms)
|
|
33
49
|
export const DEFAULT_RETRY_BEHAVIOR: RetryBehavior = {
|
|
@@ -35,56 +51,6 @@ export const DEFAULT_RETRY_BEHAVIOR: RetryBehavior = {
|
|
|
35
51
|
initialBackoffMs: 250,
|
|
36
52
|
base: 2,
|
|
37
53
|
};
|
|
38
|
-
export type WorkId = string & { __isWorkId: true };
|
|
39
|
-
export const workIdValidator = v.string() as VString<WorkId>;
|
|
40
|
-
export { workIdValidator as vWorkIdValidator };
|
|
41
|
-
|
|
42
|
-
export type NameOption = {
|
|
43
|
-
/**
|
|
44
|
-
* The name of the function. By default, if you pass in api.foo.bar.baz,
|
|
45
|
-
* it will use "foo/bar:baz" as the name. If you pass in a function handle,
|
|
46
|
-
* it will use the function handle directly.
|
|
47
|
-
*/
|
|
48
|
-
name?: string;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export type RetryOption = {
|
|
52
|
-
/** Whether to retry the action if it fails.
|
|
53
|
-
* If true, it will use the default retry behavior.
|
|
54
|
-
* If custom behavior is provided, it will retry using that behavior.
|
|
55
|
-
* If unset, it will use the Workpool's configured default.
|
|
56
|
-
*/
|
|
57
|
-
retry?: boolean | RetryBehavior;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export type WorkpoolOptions = {
|
|
61
|
-
/** How many actions/mutations can be running at once within this pool.
|
|
62
|
-
* Min 1, Max 300.
|
|
63
|
-
*/
|
|
64
|
-
maxParallelism?: number;
|
|
65
|
-
/** How much to log. This is updated on each call to `enqueue*`,
|
|
66
|
-
* `status`, or `cancel*`.
|
|
67
|
-
* Default is REPORT, which logs warnings, errors, and a periodic report.
|
|
68
|
-
* With INFO, you can also see events for started and completed work.
|
|
69
|
-
* Stats generated can be parsed by tools like
|
|
70
|
-
* [Axiom](https://axiom.co) for monitoring.
|
|
71
|
-
* With DEBUG, you can see timers and internal events for work being
|
|
72
|
-
* scheduled.
|
|
73
|
-
*/
|
|
74
|
-
logLevel?: LogLevel;
|
|
75
|
-
} & WorkpoolRetryOptions;
|
|
76
|
-
|
|
77
|
-
export type WorkpoolRetryOptions = {
|
|
78
|
-
/** Default retry behavior for enqueued actions.
|
|
79
|
-
* See {@link RetryBehavior}.
|
|
80
|
-
*/
|
|
81
|
-
defaultRetryBehavior?: RetryBehavior;
|
|
82
|
-
/** Whether to retry actions that fail by default. Default: false.
|
|
83
|
-
* NOTE: Only enable this if your actions are idempotent.
|
|
84
|
-
* See the docs (README.md) for more details.
|
|
85
|
-
*/
|
|
86
|
-
retryActionsByDefault?: boolean;
|
|
87
|
-
};
|
|
88
54
|
|
|
89
55
|
export class Workpool {
|
|
90
56
|
/**
|
|
@@ -233,8 +199,122 @@ export class Workpool {
|
|
|
233
199
|
async status(ctx: RunQueryCtx, id: WorkId): Promise<Status> {
|
|
234
200
|
return ctx.runQuery(this.component.lib.status, { id });
|
|
235
201
|
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Defines a mutation that will be run after a work item completes.
|
|
205
|
+
* You can pass this to a call to enqueue* like so:
|
|
206
|
+
* ```ts
|
|
207
|
+
* export const myOnComplete = workpool.defineOnComplete({
|
|
208
|
+
* context: v.literal("myContextValue"), // optional
|
|
209
|
+
* handler: async (ctx, {workId, context, result}) => {
|
|
210
|
+
* // ... do something with the result
|
|
211
|
+
* },
|
|
212
|
+
* });
|
|
213
|
+
*
|
|
214
|
+
* // in some other function:
|
|
215
|
+
* const workId = await workpool.enqueueAction(ctx, internal.foo.bar, {
|
|
216
|
+
* // ... args to action
|
|
217
|
+
* }, {
|
|
218
|
+
* onComplete: internal.foo.myOnComplete,
|
|
219
|
+
* });
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
defineOnComplete<
|
|
223
|
+
DataModel extends GenericDataModel,
|
|
224
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
225
|
+
V extends Validator<any, "required", any> = VAny,
|
|
226
|
+
>({
|
|
227
|
+
context,
|
|
228
|
+
handler,
|
|
229
|
+
}: {
|
|
230
|
+
context?: V;
|
|
231
|
+
handler: (
|
|
232
|
+
ctx: GenericMutationCtx<DataModel>,
|
|
233
|
+
args: {
|
|
234
|
+
workId: WorkId;
|
|
235
|
+
context: Infer<V>;
|
|
236
|
+
result: RunResult;
|
|
237
|
+
}
|
|
238
|
+
) => Promise<void>;
|
|
239
|
+
}): RegisteredMutation<"internal", OnCompleteArgs, null> {
|
|
240
|
+
return internalMutationGeneric({
|
|
241
|
+
args: vOnCompleteValidator(context),
|
|
242
|
+
handler,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Returns a validator to use for the onComplete mutation.
|
|
249
|
+
* To be used like:
|
|
250
|
+
* ```ts
|
|
251
|
+
* export const myOnComplete = internalMutation({
|
|
252
|
+
* args: vOnCompleteValidator(v.string()),
|
|
253
|
+
* handler: async (ctx, {workId, context, result}) => {
|
|
254
|
+
* // context has been validated as a string
|
|
255
|
+
* // ... do something with the result
|
|
256
|
+
* },
|
|
257
|
+
* });
|
|
258
|
+
* @param context - The context validator. If not provided, it will be `v.any()`.
|
|
259
|
+
* @returns The validator for the onComplete mutation.
|
|
260
|
+
*/
|
|
261
|
+
export function vOnCompleteValidator<
|
|
262
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
263
|
+
V extends Validator<any, "required", any> = VAny,
|
|
264
|
+
>(context?: V) {
|
|
265
|
+
return v.object({
|
|
266
|
+
workId: vWorkIdValidator,
|
|
267
|
+
context: context ?? v.any(),
|
|
268
|
+
result: vResultValidator,
|
|
269
|
+
});
|
|
236
270
|
}
|
|
237
271
|
|
|
272
|
+
export type NameOption = {
|
|
273
|
+
/**
|
|
274
|
+
* The name of the function. By default, if you pass in api.foo.bar.baz,
|
|
275
|
+
* it will use "foo/bar:baz" as the name. If you pass in a function handle,
|
|
276
|
+
* it will use the function handle directly.
|
|
277
|
+
*/
|
|
278
|
+
name?: string;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export type RetryOption = {
|
|
282
|
+
/** Whether to retry the action if it fails.
|
|
283
|
+
* If true, it will use the default retry behavior.
|
|
284
|
+
* If custom behavior is provided, it will retry using that behavior.
|
|
285
|
+
* If unset, it will use the Workpool's configured default.
|
|
286
|
+
*/
|
|
287
|
+
retry?: boolean | RetryBehavior;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
export type WorkpoolOptions = {
|
|
291
|
+
/** How many actions/mutations can be running at once within this pool.
|
|
292
|
+
* Min 1, Max 300.
|
|
293
|
+
*/
|
|
294
|
+
maxParallelism?: number;
|
|
295
|
+
/** How much to log. This is updated on each call to `enqueue*`,
|
|
296
|
+
* `status`, or `cancel*`.
|
|
297
|
+
* Default is REPORT, which logs warnings, errors, and a periodic report.
|
|
298
|
+
* With INFO, you can also see events for started and completed work.
|
|
299
|
+
* Stats generated can be parsed by tools like
|
|
300
|
+
* [Axiom](https://axiom.co) for monitoring.
|
|
301
|
+
* With DEBUG, you can see timers and internal events for work being
|
|
302
|
+
* scheduled.
|
|
303
|
+
*/
|
|
304
|
+
logLevel?: LogLevel;
|
|
305
|
+
} & WorkpoolRetryOptions;
|
|
306
|
+
|
|
307
|
+
export type WorkpoolRetryOptions = {
|
|
308
|
+
/** Default retry behavior for enqueued actions.
|
|
309
|
+
* See {@link RetryBehavior}.
|
|
310
|
+
*/
|
|
311
|
+
defaultRetryBehavior?: RetryBehavior;
|
|
312
|
+
/** Whether to retry actions that fail by default. Default: false.
|
|
313
|
+
* NOTE: Only enable this if your actions are idempotent.
|
|
314
|
+
* See the docs (README.md) for more details.
|
|
315
|
+
*/
|
|
316
|
+
retryActionsByDefault?: boolean;
|
|
317
|
+
};
|
|
238
318
|
export type SchedulerOptions =
|
|
239
319
|
| {
|
|
240
320
|
/**
|
|
@@ -259,12 +339,18 @@ export type CallbackOptions = {
|
|
|
259
339
|
* The context type is for your use, feel free to provide a validator for it.
|
|
260
340
|
* e.g.
|
|
261
341
|
* ```ts
|
|
342
|
+
* export const completion = workpool.defineOnComplete({
|
|
343
|
+
* context: v.string(),
|
|
344
|
+
* handler: async (ctx, {workId, context, result}) => {
|
|
345
|
+
* // context has been validated as a string
|
|
346
|
+
* // ... do something with the result
|
|
347
|
+
* },
|
|
348
|
+
* });
|
|
349
|
+
* ```
|
|
350
|
+
* or more manually:
|
|
351
|
+
* ```ts
|
|
262
352
|
* export const completion = internalMutation({
|
|
263
|
-
* args:
|
|
264
|
-
* workId: workIdValidator,
|
|
265
|
-
* context: v.any(),
|
|
266
|
-
* result: resultValidator,
|
|
267
|
-
* },
|
|
353
|
+
* args: vOnCompleteValidator(v.string()),
|
|
268
354
|
* handler: async (ctx, args) => {
|
|
269
355
|
* console.log(args.result, "Got Context back -> ", args.context, Date.now() - args.context);
|
|
270
356
|
* },
|
|
@@ -4,7 +4,7 @@ import { Id } from "./_generated/dataModel.js";
|
|
|
4
4
|
import { internalMutation, MutationCtx } from "./_generated/server.js";
|
|
5
5
|
import { kickMainLoop } from "./kick.js";
|
|
6
6
|
import { createLogger } from "./logging.js";
|
|
7
|
-
import { OnCompleteArgs, RunResult,
|
|
7
|
+
import { OnCompleteArgs, RunResult, vResultValidator } from "./shared.js";
|
|
8
8
|
import { recordCompleted } from "./stats.js";
|
|
9
9
|
|
|
10
10
|
export type CompleteJob = Infer<typeof completeArgs.fields.jobs.element>;
|
|
@@ -12,7 +12,7 @@ export type CompleteJob = Infer<typeof completeArgs.fields.jobs.element>;
|
|
|
12
12
|
export const completeArgs = v.object({
|
|
13
13
|
jobs: v.array(
|
|
14
14
|
v.object({
|
|
15
|
-
runResult:
|
|
15
|
+
runResult: vResultValidator,
|
|
16
16
|
workId: v.id("work"),
|
|
17
17
|
attempt: v.number(),
|
|
18
18
|
})
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
vi,
|
|
10
10
|
} from "vitest";
|
|
11
11
|
import { internal } from "./_generated/api";
|
|
12
|
-
import { Id } from "./_generated/dataModel.js";
|
|
13
12
|
import { kickMainLoop } from "./kick.js";
|
|
14
13
|
import { DEFAULT_LOG_LEVEL } from "./logging.js";
|
|
15
14
|
import schema from "./schema.js";
|
|
@@ -276,13 +275,18 @@ describe("kickMainLoop", () => {
|
|
|
276
275
|
const runStatus = await ctx.db.query("runStatus").unique();
|
|
277
276
|
assert(runStatus);
|
|
278
277
|
const segment = getNextSegment() + 10n;
|
|
278
|
+
const scheduledId = await ctx.scheduler.runAfter(
|
|
279
|
+
10_000,
|
|
280
|
+
internal.loop.main,
|
|
281
|
+
{ generation: 0n, segment }
|
|
282
|
+
);
|
|
279
283
|
await ctx.db.patch(runStatus._id, {
|
|
280
284
|
state: {
|
|
281
285
|
generation: 0n,
|
|
282
286
|
saturated: false,
|
|
283
287
|
kind: "scheduled",
|
|
284
288
|
segment,
|
|
285
|
-
scheduledId
|
|
289
|
+
scheduledId,
|
|
286
290
|
},
|
|
287
291
|
});
|
|
288
292
|
// await all scheduled functions to run
|
|
@@ -291,6 +295,9 @@ describe("kickMainLoop", () => {
|
|
|
291
295
|
assert(afterStatus);
|
|
292
296
|
expect(afterStatus.state.kind).toBe("running");
|
|
293
297
|
assert(afterStatus.state.kind === "running");
|
|
298
|
+
const scheduledJob = await ctx.db.system.get(scheduledId);
|
|
299
|
+
assert(scheduledJob);
|
|
300
|
+
expect(scheduledJob.state.kind).toBe("canceled");
|
|
294
301
|
});
|
|
295
302
|
});
|
|
296
303
|
});
|
package/src/component/schema.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
config,
|
|
6
6
|
onComplete,
|
|
7
7
|
retryBehavior,
|
|
8
|
-
|
|
8
|
+
vResultValidator,
|
|
9
9
|
} from "./shared.js";
|
|
10
10
|
|
|
11
11
|
// Represents a slice of time to process work.
|
|
@@ -80,7 +80,7 @@ export default defineSchema({
|
|
|
80
80
|
// Written by complete, read & deleted by `main`.
|
|
81
81
|
pendingCompletion: defineTable({
|
|
82
82
|
segment,
|
|
83
|
-
runResult,
|
|
83
|
+
runResult: vResultValidator,
|
|
84
84
|
workId: v.id("work"),
|
|
85
85
|
retry: v.boolean(),
|
|
86
86
|
})
|
package/src/component/shared.ts
CHANGED
|
@@ -64,7 +64,7 @@ export type RetryBehavior = {
|
|
|
64
64
|
// This ensures that the type satisfies the schema.
|
|
65
65
|
const _ = {} as RetryBehavior satisfies Infer<typeof retryBehavior>;
|
|
66
66
|
|
|
67
|
-
export const
|
|
67
|
+
export const vResultValidator = v.union(
|
|
68
68
|
v.object({
|
|
69
69
|
kind: v.literal("success"),
|
|
70
70
|
returnValue: v.any(),
|
|
@@ -77,7 +77,7 @@ export const runResult = v.union(
|
|
|
77
77
|
kind: v.literal("canceled"),
|
|
78
78
|
})
|
|
79
79
|
);
|
|
80
|
-
export type RunResult = Infer<typeof
|
|
80
|
+
export type RunResult = Infer<typeof vResultValidator>;
|
|
81
81
|
|
|
82
82
|
export const onComplete = v.object({
|
|
83
83
|
fnHandle: v.string(), // mutation
|
package/src/component/stats.ts
CHANGED
|
@@ -15,8 +15,6 @@ import { internal } from "./_generated/api.js";
|
|
|
15
15
|
import schema from "./schema.js";
|
|
16
16
|
import { paginator } from "convex-helpers/server/pagination";
|
|
17
17
|
|
|
18
|
-
const BACKLOG_BATCH_SIZE = 100;
|
|
19
|
-
|
|
20
18
|
/**
|
|
21
19
|
* Record stats about work execution. Intended to be queried by Axiom or Datadog.
|
|
22
20
|
* See the [README](https://github.com/get-convex/workpool) for example queries.
|
|
@@ -114,36 +112,15 @@ export const calculateBacklogAndReport = internalMutation({
|
|
|
114
112
|
logLevel,
|
|
115
113
|
},
|
|
116
114
|
handler: async (ctx, args) => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
q.gte("segment", args.startSegment).lt("segment", args.endSegment)
|
|
121
|
-
)
|
|
122
|
-
.paginate({
|
|
123
|
-
numItems: BACKLOG_BATCH_SIZE,
|
|
124
|
-
cursor: args.cursor,
|
|
125
|
-
});
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
116
|
+
const pendingStart = await (ctx.db.query("pendingStart") as any).count();
|
|
117
|
+
|
|
126
118
|
const console = createLogger(args.logLevel);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
}
|
|
119
|
+
recordReport(console, {
|
|
120
|
+
...args.report,
|
|
121
|
+
running: args.running,
|
|
122
|
+
backlog: pendingStart,
|
|
123
|
+
});
|
|
147
124
|
},
|
|
148
125
|
});
|
|
149
126
|
|