mongodash 2.6.0 → 2.8.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/README.md +45 -0
- package/dist/lib/ConcurrentRunner.js +47 -2
- package/dist/lib/ConcurrentRunner.js.map +1 -1
- package/dist/lib/createContinuousLock.js +23 -6
- package/dist/lib/createContinuousLock.js.map +1 -1
- package/dist/lib/cronTasks.js +119 -64
- package/dist/lib/cronTasks.js.map +1 -1
- package/dist/lib/index.js +11 -6
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/reactiveTasks/LeaderElector.js +21 -3
- package/dist/lib/reactiveTasks/LeaderElector.js.map +1 -1
- package/dist/lib/reactiveTasks/MetricsCollector.js +118 -39
- package/dist/lib/reactiveTasks/MetricsCollector.js.map +1 -1
- package/dist/lib/reactiveTasks/ReactiveTaskPlanner.js +66 -31
- package/dist/lib/reactiveTasks/ReactiveTaskPlanner.js.map +1 -1
- package/dist/lib/reactiveTasks/ReactiveTaskRepository.js +19 -1
- package/dist/lib/reactiveTasks/ReactiveTaskRepository.js.map +1 -1
- package/dist/lib/reactiveTasks/ReactiveTaskTypes.js +7 -1
- package/dist/lib/reactiveTasks/ReactiveTaskTypes.js.map +1 -1
- package/dist/lib/reactiveTasks/ReactiveTaskWorker.js +80 -5
- package/dist/lib/reactiveTasks/ReactiveTaskWorker.js.map +1 -1
- package/dist/lib/reactiveTasks/index.js +20 -13
- package/dist/lib/reactiveTasks/index.js.map +1 -1
- package/dist/lib/task-management/OperationalTaskController.js +1 -1
- package/dist/lib/task-management/OperationalTaskController.js.map +1 -1
- package/dist/lib/testing/assertNoReactiveTaskErrors.js +16 -12
- package/dist/lib/testing/assertNoReactiveTaskErrors.js.map +1 -1
- package/dist/lib/testing/index.js +2 -0
- package/dist/lib/testing/index.js.map +1 -1
- package/dist/lib/testing/resolveWhitelistFilter.js +48 -0
- package/dist/lib/testing/resolveWhitelistFilter.js.map +1 -0
- package/dist/lib/testing/waitUntilReactiveTasksIdle.js +17 -46
- package/dist/lib/testing/waitUntilReactiveTasksIdle.js.map +1 -1
- package/dist/types/ConcurrentRunner.d.ts +16 -0
- package/dist/types/createContinuousLock.d.ts +17 -1
- package/dist/types/cronTasks.d.ts +17 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/reactiveTasks/LeaderElector.d.ts +15 -1
- package/dist/types/reactiveTasks/MetricsCollector.d.ts +19 -8
- package/dist/types/reactiveTasks/ReactiveTaskPlanner.d.ts +11 -0
- package/dist/types/reactiveTasks/ReactiveTaskRepository.d.ts +10 -1
- package/dist/types/reactiveTasks/ReactiveTaskTypes.d.ts +19 -0
- package/dist/types/reactiveTasks/index.d.ts +8 -2
- package/dist/types/testing/assertNoReactiveTaskErrors.d.ts +4 -4
- package/dist/types/testing/index.d.ts +2 -0
- package/dist/types/testing/resolveWhitelistFilter.d.ts +35 -0
- package/dist/types/testing/waitUntilReactiveTasksIdle.d.ts +7 -13
- package/docs/.vitepress/config.mts +9 -1
- package/docs/cron-tasks.md +130 -1
- package/docs/error-handling.md +156 -0
- package/docs/reactive-tasks/guides.md +1 -1
- package/docs/reactive-tasks/index.md +2 -2
- package/docs/reactive-tasks/monitoring.md +7 -0
- package/docs/reactive-tasks/testing.md +187 -0
- package/docs/testing.md +60 -94
- package/package.json +36 -24
- package/docs/.vitepress/cache/deps/_metadata.json +0 -31
- package/docs/.vitepress/cache/deps/chunk-LE5NDSFD.js +0 -12824
- package/docs/.vitepress/cache/deps/chunk-LE5NDSFD.js.map +0 -7
- package/docs/.vitepress/cache/deps/package.json +0 -3
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -4505
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -9731
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
- package/docs/.vitepress/cache/deps/vue.js +0 -347
- package/docs/.vitepress/cache/deps/vue.js.map +0 -7
package/docs/testing.md
CHANGED
|
@@ -1,123 +1,89 @@
|
|
|
1
|
-
# Testing
|
|
1
|
+
# Testing
|
|
2
2
|
|
|
3
|
-
Mongodash
|
|
3
|
+
Mongodash's asynchronous subsystems (reactive tasks, cron, change streams)
|
|
4
|
+
need more than a fixed `setTimeout` in tests. This page lists the testing
|
|
5
|
+
utilities the library provides, grouped by scope.
|
|
4
6
|
|
|
5
|
-
##
|
|
7
|
+
## Generic
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
### `waitUntil`
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
A general-purpose polling helper that resolves once a condition function
|
|
12
|
+
returns `true`. Useful when the built-in waits are too broad (e.g. waiting
|
|
13
|
+
for an HTTP side effect or an external queue) or as a building block for
|
|
14
|
+
your own utilities.
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
1. **Planner Empty**: The internal `ReactiveTaskPlanner` has no buffered Change Stream events waiting to be flushed.
|
|
16
|
-
2. **Workers Idle**: No `ResponsiveTaskWorker` is currently processing a task (active count is 0).
|
|
17
|
-
3. **Database Settled**: No tasks in any registered task collection are in `pending`, `processing`, or `processing_dirty` state.
|
|
18
|
-
* **Exception**: Pending tasks scheduled for the **distant future** (beyond the current timeout + stability window) are ignored. This ensures that long-term retries (e.g., "retry in 1 hour") do not cause your tests to timeout.
|
|
19
|
-
|
|
20
|
-
### Usage
|
|
16
|
+
It includes a **time-jump detector**: if a breakpoint or a suspended laptop
|
|
17
|
+
pauses the event loop for more than a second, the deadline is extended by
|
|
18
|
+
the observed pause so the wait does not falsely time out.
|
|
21
19
|
|
|
22
20
|
```typescript
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
it('should process user registration workflow', async () => {
|
|
26
|
-
// 1. Trigger the workflow
|
|
27
|
-
await users.insertOne({ email: 'test@example.com', status: 'new' });
|
|
21
|
+
import { waitUntil } from 'mongodash/testing';
|
|
28
22
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// 3. Assert the final state
|
|
34
|
-
const emailTask = await emailTasks.findOne({ email: 'test@example.com' });
|
|
35
|
-
expect(emailTask).toBeDefined();
|
|
36
|
-
expect(emailTask.status).toBe('sent');
|
|
37
|
-
});
|
|
23
|
+
await waitUntil(
|
|
24
|
+
async () => (await getBalance(userId)) === 100,
|
|
25
|
+
{ timeoutMs: 5000, pollIntervalMs: 50, stabilityDurationMs: 100 },
|
|
26
|
+
);
|
|
38
27
|
```
|
|
39
28
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
29
|
+
| Option | Default | Description |
|
|
30
|
+
| :--- | :--- | :--- |
|
|
31
|
+
| `timeoutMs` | `10000` | Maximum time before throwing. |
|
|
32
|
+
| `pollIntervalMs` | `50` | How often the condition is evaluated. |
|
|
33
|
+
| `stabilityDurationMs` | `0` | How long the condition must _remain_ true before resolving. Prevents flakiness when a state briefly flips true then false. |
|
|
43
34
|
|
|
44
|
-
|
|
45
|
-
await waitUntilReactiveTasksIdle({
|
|
46
|
-
timeoutMs: 30000,
|
|
47
|
-
stabilityDurationMs: 200, // Wait for 200ms of "silence" to catch in-flight cascading tasks
|
|
48
|
-
});
|
|
49
|
-
```
|
|
35
|
+
## Reactive tasks
|
|
50
36
|
|
|
51
|
-
|
|
37
|
+
See [**Testing Reactive Tasks**](./reactive-tasks/testing.md) for:
|
|
52
38
|
|
|
53
|
-
|
|
39
|
+
- `waitUntilReactiveTasksIdle` — wait for the reactive-task subsystem to
|
|
40
|
+
fully settle (planner empty, workers idle, DB drained).
|
|
41
|
+
- `assertNoReactiveTaskErrors` — catch silent failures a handler logged
|
|
42
|
+
but never threw up the stack.
|
|
43
|
+
- `configureForTesting` — replace production debounce / polling intervals
|
|
44
|
+
with testing-friendly values.
|
|
45
|
+
- `WhitelistRule` — scope the above helpers to specific
|
|
46
|
+
collections / documents / tasks for parallel tests.
|
|
54
47
|
|
|
55
|
-
|
|
48
|
+
## Cron tasks
|
|
56
49
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
Cron tasks expose a few helpers from the main entry point that are primarily
|
|
51
|
+
useful in tests. They live on the main `mongodash` module alongside the
|
|
52
|
+
cron API rather than under `mongodash/testing`:
|
|
60
53
|
|
|
61
|
-
###
|
|
54
|
+
### Run a task synchronously
|
|
62
55
|
|
|
63
56
|
```typescript
|
|
64
|
-
import {
|
|
65
|
-
|
|
66
|
-
it('should process successfully', async () => {
|
|
67
|
-
const startTime = new Date();
|
|
57
|
+
import { runCronTask } from 'mongodash';
|
|
68
58
|
|
|
69
|
-
|
|
70
|
-
await
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
await assertNoReactiveTaskErrors({ since: startTime });
|
|
59
|
+
it('processes pending invoices', async () => {
|
|
60
|
+
await runCronTask('invoice-sweep');
|
|
61
|
+
const processed = await invoices.countDocuments({ status: 'processed' });
|
|
62
|
+
expect(processed).toBeGreaterThan(0);
|
|
74
63
|
});
|
|
75
64
|
```
|
|
76
65
|
|
|
77
|
-
|
|
66
|
+
`runCronTask(taskId)` enqueues the task and awaits its completion. It throws
|
|
67
|
+
if called from inside another running cron task (use
|
|
68
|
+
`scheduleCronTaskImmediately` / `triggerCronTask` there instead).
|
|
78
69
|
|
|
79
|
-
|
|
80
|
-
await assertNoReactiveTaskErrors({
|
|
81
|
-
since: startTime, // Required: Check for errors after this time
|
|
82
|
-
sourceDocIds: [docId], // Optional: Limit check to specific source documents
|
|
83
|
-
excludeErrors: [ // Optional: Allow known errors (strings or RegEx)
|
|
84
|
-
'Expected Failure',
|
|
85
|
-
/Authorization Error/
|
|
86
|
-
]
|
|
87
|
-
});
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
## `configureForTesting`
|
|
91
|
-
|
|
92
|
-
A helper to configure the library for fast, deterministic testing execution.
|
|
93
|
-
|
|
94
|
-
By default, the library is optimized for production scenarios (e.g. `debounce: 1000ms`, `minPollMs: 200ms`). In tests, these delays cause unnecessary slowness.
|
|
95
|
-
|
|
96
|
-
`configureForTesting` overrides these defaults globally to minimal values (e.g. `10ms`).
|
|
97
|
-
|
|
98
|
-
### Usage
|
|
99
|
-
|
|
100
|
-
Call this **once** in your global test setup (e.g. `jest.setup.js` or `beforeAll`).
|
|
70
|
+
### Disable the scheduler
|
|
101
71
|
|
|
102
|
-
|
|
72
|
+
Running background cron jobs in unit tests causes non-determinism. Two
|
|
73
|
+
options:
|
|
103
74
|
|
|
104
75
|
```typescript
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
76
|
+
// Option A: never auto-start.
|
|
77
|
+
await mongodash.init({ ..., runCronTasks: false });
|
|
78
|
+
|
|
79
|
+
// Option B: stop after init.
|
|
80
|
+
import { stopCronTasks, startCronTasks } from 'mongodash';
|
|
81
|
+
stopCronTasks();
|
|
82
|
+
// ...
|
|
83
|
+
startCronTasks(); // if a test needs it back
|
|
111
84
|
```
|
|
112
85
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
You can customize specific values if needed:
|
|
86
|
+
Called before the first `cronTask()` registration, `stopCronTasks()` also
|
|
87
|
+
prevents any task from starting later in the process.
|
|
116
88
|
|
|
117
|
-
|
|
118
|
-
configureForTesting({
|
|
119
|
-
debounce: 0, // Force 0ms debounce (immediate execution)
|
|
120
|
-
minPollMs: 50, // Poll every 50ms
|
|
121
|
-
minBatchIntervalMs: 50
|
|
122
|
-
});
|
|
123
|
-
```
|
|
89
|
+
See [**Cron Tasks**](./cron-tasks.md) for the full cron reference.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongodash",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "An utility library delivering super-useful and super-simple tools using MongoDB",
|
|
6
6
|
"main": "./dist/lib/index.js",
|
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
"types": "./dist/types/index.d.ts",
|
|
11
11
|
"import": "./dist/lib/index.js",
|
|
12
12
|
"default": "./dist/lib/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./testing": {
|
|
15
|
+
"types": "./dist/types/testing/index.d.ts",
|
|
16
|
+
"import": "./dist/lib/testing/index.js",
|
|
17
|
+
"default": "./dist/lib/testing/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"typesVersions": {
|
|
21
|
+
"*": {
|
|
22
|
+
"testing": [
|
|
23
|
+
"./dist/types/testing/index.d.ts"
|
|
24
|
+
]
|
|
13
25
|
}
|
|
14
26
|
},
|
|
15
27
|
"files": [
|
|
@@ -49,7 +61,7 @@
|
|
|
49
61
|
},
|
|
50
62
|
"dependencies": {
|
|
51
63
|
"@sapphire/duration": "^1.2.0",
|
|
52
|
-
"cron-parser": "^5.
|
|
64
|
+
"cron-parser": "^5.5.0",
|
|
53
65
|
"debug": "^4.4.3",
|
|
54
66
|
"fast-json-stable-stringify": "^2.1.0"
|
|
55
67
|
},
|
|
@@ -64,41 +76,41 @@
|
|
|
64
76
|
},
|
|
65
77
|
"devDependencies": {
|
|
66
78
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
67
|
-
"@commitlint/cli": "^20.
|
|
79
|
+
"@commitlint/cli": "^20.5.0",
|
|
68
80
|
"@semantic-release/changelog": "^6.0.3",
|
|
69
81
|
"@semantic-release/git": "^10.0.1",
|
|
70
|
-
"@stryker-mutator/core": "^9.
|
|
71
|
-
"@stryker-mutator/jest-runner": "^9.
|
|
72
|
-
"@types/debug": "^4.1.
|
|
82
|
+
"@stryker-mutator/core": "^9.6.1",
|
|
83
|
+
"@stryker-mutator/jest-runner": "^9.6.1",
|
|
84
|
+
"@types/debug": "^4.1.13",
|
|
73
85
|
"@types/jest": "^30.0.0",
|
|
74
|
-
"@types/lodash": "^4.17.
|
|
75
|
-
"@types/node": "^25.0
|
|
76
|
-
"@types/sinon": "^21.0.
|
|
77
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
78
|
-
"@typescript-eslint/parser": "^8.
|
|
86
|
+
"@types/lodash": "^4.17.24",
|
|
87
|
+
"@types/node": "^25.6.0",
|
|
88
|
+
"@types/sinon": "^21.0.1",
|
|
89
|
+
"@typescript-eslint/eslint-plugin": "^8.58.2",
|
|
90
|
+
"@typescript-eslint/parser": "^8.58.2",
|
|
79
91
|
"correlation-id": "^5.2.0",
|
|
80
92
|
"coveralls": "^3.1.1",
|
|
81
93
|
"deepdash": "^5.3.9",
|
|
82
|
-
"eslint": "^9.39.
|
|
94
|
+
"eslint": "^9.39.4",
|
|
83
95
|
"eslint-config-prettier": "^10.1.8",
|
|
84
96
|
"eslint-plugin-no-only-tests": "^3.3.0",
|
|
85
|
-
"eslint-plugin-prettier": "^5.5.
|
|
86
|
-
"globals": "^
|
|
97
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
98
|
+
"globals": "^17.5.0",
|
|
87
99
|
"husky": "^9.1.7",
|
|
88
|
-
"jest": "^30.
|
|
100
|
+
"jest": "^30.3.0",
|
|
89
101
|
"js-yaml": "4.1.1",
|
|
90
|
-
"lint-staged": "^16.
|
|
91
|
-
"lodash": "^4.
|
|
92
|
-
"mongodb": "^7.
|
|
102
|
+
"lint-staged": "^16.4.0",
|
|
103
|
+
"lodash": "^4.18.1",
|
|
104
|
+
"mongodb": "^7.1.1",
|
|
93
105
|
"npm-run-all": "^4.1.5",
|
|
94
106
|
"organize-imports-cli": "^0.10.0",
|
|
95
|
-
"path-to-regexp": "8.
|
|
96
|
-
"prettier": "^3.
|
|
107
|
+
"path-to-regexp": "8.4.2",
|
|
108
|
+
"prettier": "^3.8.3",
|
|
97
109
|
"prom-client": "^15.1.3",
|
|
98
|
-
"publint": "^0.3.
|
|
99
|
-
"semantic-release": "^25.0.
|
|
100
|
-
"sinon": "^21.
|
|
101
|
-
"ts-jest": "^29.4.
|
|
110
|
+
"publint": "^0.3.18",
|
|
111
|
+
"semantic-release": "^25.0.3",
|
|
112
|
+
"sinon": "^21.1.2",
|
|
113
|
+
"ts-jest": "^29.4.9",
|
|
102
114
|
"ts-node": "^10.9.2",
|
|
103
115
|
"typescript": "^5.9.3",
|
|
104
116
|
"vitepress": "^1.6.4"
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"hash": "65ae190e",
|
|
3
|
-
"configHash": "1734f516",
|
|
4
|
-
"lockfileHash": "68b03582",
|
|
5
|
-
"browserHash": "246dbe54",
|
|
6
|
-
"optimized": {
|
|
7
|
-
"vue": {
|
|
8
|
-
"src": "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
|
|
9
|
-
"file": "vue.js",
|
|
10
|
-
"fileHash": "1ab8f95b",
|
|
11
|
-
"needsInterop": false
|
|
12
|
-
},
|
|
13
|
-
"vitepress > @vue/devtools-api": {
|
|
14
|
-
"src": "../../../../node_modules/@vue/devtools-api/dist/index.js",
|
|
15
|
-
"file": "vitepress___@vue_devtools-api.js",
|
|
16
|
-
"fileHash": "eb38336e",
|
|
17
|
-
"needsInterop": false
|
|
18
|
-
},
|
|
19
|
-
"vitepress > @vueuse/core": {
|
|
20
|
-
"src": "../../../../node_modules/@vueuse/core/index.mjs",
|
|
21
|
-
"file": "vitepress___@vueuse_core.js",
|
|
22
|
-
"fileHash": "d06fa19f",
|
|
23
|
-
"needsInterop": false
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
"chunks": {
|
|
27
|
-
"chunk-LE5NDSFD": {
|
|
28
|
-
"file": "chunk-LE5NDSFD.js"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|