@alexify/migronaut 2.1.0 → 2.3.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 (71) hide show
  1. package/CHANGELOG.md +223 -0
  2. package/README.md +68 -10
  3. package/bullmq.d.ts +465 -7
  4. package/index.d.ts +1272 -18
  5. package/migronaut.schema.json +150 -2
  6. package/package.json +8 -2
  7. package/src/bullmq/background-processor.js +469 -0
  8. package/src/bullmq/index.js +12 -0
  9. package/src/bullmq/jobs.js +254 -7
  10. package/src/bullmq/processor.js +153 -15
  11. package/src/bullmq/producer.js +202 -27
  12. package/src/bullmq/service.js +480 -45
  13. package/src/cli/commands/background.js +500 -0
  14. package/src/cli/commands/converge.js +38 -10
  15. package/src/cli/commands/create.js +6 -0
  16. package/src/cli/exit-codes.js +6 -0
  17. package/src/cli/index.js +2 -0
  18. package/src/cli/table.js +68 -9
  19. package/src/core/audit.js +98 -3
  20. package/src/core/background-audit.js +139 -0
  21. package/src/core/background-drift.js +126 -0
  22. package/src/core/background-dry-run.js +366 -0
  23. package/src/core/background-engine.js +818 -0
  24. package/src/core/background-kit.js +425 -0
  25. package/src/core/background-partition.js +298 -0
  26. package/src/core/background-runner.js +305 -0
  27. package/src/core/background-sandbox.js +701 -0
  28. package/src/core/background-shard.js +542 -0
  29. package/src/core/background-spec.js +597 -0
  30. package/src/core/background-store.js +951 -0
  31. package/src/core/background-throttle.js +269 -0
  32. package/src/core/background-watch-plan.js +164 -0
  33. package/src/core/background-watch-store.js +78 -0
  34. package/src/core/background-watch.js +605 -0
  35. package/src/core/background.js +1121 -0
  36. package/src/core/bson-peer.js +23 -0
  37. package/src/core/changelog.js +32 -0
  38. package/src/core/collections.js +125 -31
  39. package/src/core/config.js +133 -13
  40. package/src/core/converge-plan.js +343 -61
  41. package/src/core/converge-search-run.js +440 -0
  42. package/src/core/converge-search.js +404 -0
  43. package/src/core/converge.js +428 -183
  44. package/src/core/index-spec.js +27 -16
  45. package/src/core/lock.js +97 -32
  46. package/src/core/migrator.js +951 -26
  47. package/src/core/options.js +32 -1
  48. package/src/core/run.js +26 -12
  49. package/src/core/runner.js +1 -1
  50. package/src/core/search-index-spec.js +758 -0
  51. package/src/core/server-info.js +70 -0
  52. package/src/core/shard-info.js +76 -0
  53. package/src/core/versioning-spec.js +181 -0
  54. package/src/errors/index.js +97 -5
  55. package/src/index.js +16 -0
  56. package/src/utils/canonical.js +34 -1
  57. package/src/utils/error.js +11 -2
  58. package/src/utils/loader.js +77 -9
  59. package/src/utils/migration-name.js +33 -1
  60. package/src/utils/telemetry.js +125 -1
  61. package/src/utils/template.js +69 -1
  62. package/src/versioning/config.js +155 -0
  63. package/src/versioning/document.js +326 -0
  64. package/src/versioning/index.js +50 -0
  65. package/src/versioning/internal.js +279 -0
  66. package/src/versioning/mongoose.js +151 -0
  67. package/src/versioning/occ.js +318 -0
  68. package/src/versioning/registry.js +187 -0
  69. package/src/versioning/upcaster.js +213 -0
  70. package/versioning.d.ts +666 -0
  71. package/versioning.js +1 -0
@@ -152,6 +152,20 @@ function assertConvergeAfterUpValid(converge, filename, to) {
152
152
  }
153
153
  }
154
154
 
155
+ /**
156
+ * `onBackgroundPending`: what a run does at a migration that `requires` a
157
+ * background migration not completed yet — `'error'` (throw
158
+ * BackgroundPendingError) or `'stop'` (end the run there, cleanly).
159
+ */
160
+ function assertBackgroundPendingValid(onBackgroundPending) {
161
+ if (onBackgroundPending === undefined) return;
162
+ if (onBackgroundPending !== 'error' && onBackgroundPending !== 'stop') {
163
+ throw new ConfigInvalidError("onBackgroundPending must be 'error' or 'stop'", {
164
+ onBackgroundPending,
165
+ });
166
+ }
167
+ }
168
+
155
169
  /** `up(filename, options)` */
156
170
  function assertUpOptions(filename, options) {
157
171
  assertFilename(filename);
@@ -167,6 +181,7 @@ function assertUpOptions(filename, options) {
167
181
  assertOrderedValid(options.ordered, filename);
168
182
  assertConvergeAfterUpValid(options.converge, filename, options.to);
169
183
  assertChecksumValid(options.checksum, filename);
184
+ assertBackgroundPendingValid(options.onBackgroundPending);
170
185
  assertActorValid(options);
171
186
  }
172
187
 
@@ -198,11 +213,26 @@ function assertDryRunOptions(filename, options) {
198
213
 
199
214
  /** `converge(options)` */
200
215
  function assertConvergeOptions(options) {
201
- for (const key of ['dryRun', 'prune', 'noLock', 'ordered', 'rebuildUnique']) {
216
+ for (const key of [
217
+ 'dryRun',
218
+ 'prune',
219
+ 'noLock',
220
+ 'ordered',
221
+ 'rebuildUnique',
222
+ 'waitForSearchIndexes',
223
+ ]) {
202
224
  if (options[key] !== undefined && typeof options[key] !== 'boolean') {
203
225
  throw new ConfigInvalidError(`${key} must be a boolean`, { [key]: options[key] });
204
226
  }
205
227
  }
228
+ // A dry run builds nothing, so there is nothing to wait for — asking for
229
+ // both is a mistake worth saying, not a wait that silently never happens.
230
+ if (options.dryRun && options.waitForSearchIndexes) {
231
+ throw new ConfigInvalidError('waitForSearchIndexes cannot be combined with dryRun', {
232
+ dryRun: true,
233
+ waitForSearchIndexes: true,
234
+ });
235
+ }
206
236
  assertActorValid(options);
207
237
  }
208
238
 
@@ -239,6 +269,7 @@ function assertImportOptions(options) {
239
269
  }
240
270
 
241
271
  module.exports = {
272
+ assertActorValid,
242
273
  assertConvergeOptions,
243
274
  assertDownOptions,
244
275
  assertDryRunOptions,
package/src/core/run.js CHANGED
@@ -41,6 +41,7 @@ const { MigratorKit, RECORD_LOCK_WAIT } = require('./migrator.js');
41
41
  async function runMigrations(config = {}, options = {}) {
42
42
  const {
43
43
  noLock,
44
+ onBackgroundPending,
44
45
  onLockHeld = 'throw',
45
46
  // Left undefined unless given: the default then follows the holder's TTL.
46
47
  lockWaitTimeoutMs,
@@ -71,6 +72,11 @@ async function runMigrations(config = {}, options = {}) {
71
72
  kit.on('converge:end', (event) => {
72
73
  if (event.trigger === 'up' && event.success) converge = event.result;
73
74
  });
75
+ // With onBackgroundPending: 'stop', where the run stopped and what for.
76
+ const waiting = [];
77
+ kit.on('background:waiting', (event) => {
78
+ waiting.push({ migration: event.migration, waitsFor: event.waitsFor });
79
+ });
74
80
 
75
81
  // An abort reaches the run wherever it is: the wait loop sees the signal
76
82
  // between polls, and kit.stop() stops a run that is setting up or between
@@ -90,20 +96,28 @@ async function runMigrations(config = {}, options = {}) {
90
96
  waited,
91
97
  waitedMs,
92
98
  attempts,
93
- } = await withLockWait(() => kit.up(undefined, noLock ? { noLock: true } : {}), {
94
- onLockHeld,
95
- ...(lockWaitTimeoutMs !== undefined ? { lockWaitTimeoutMs } : {}),
96
- ...(lockPollIntervalMs !== undefined ? { lockPollIntervalMs } : {}),
97
- // Resolved AFTER connect, from the kit's own merged config: a `logger:
98
- // null` in the config file must silence the wait lines too, not only
99
- // the kit's own.
100
- logger: kit.logger,
101
- ...(signal ? { signal } : {}),
102
- onSettle: (wait) => kit[RECORD_LOCK_WAIT](wait),
103
- });
99
+ } = await withLockWait(
100
+ () =>
101
+ kit.up(undefined, {
102
+ ...(noLock ? { noLock: true } : {}),
103
+ ...(onBackgroundPending !== undefined ? { onBackgroundPending } : {}),
104
+ }),
105
+ {
106
+ onLockHeld,
107
+ ...(lockWaitTimeoutMs !== undefined ? { lockWaitTimeoutMs } : {}),
108
+ ...(lockPollIntervalMs !== undefined ? { lockPollIntervalMs } : {}),
109
+ // Resolved AFTER connect, from the kit's own merged config: a `logger:
110
+ // null` in the config file must silence the wait lines too, not only
111
+ // the kit's own.
112
+ logger: kit.logger,
113
+ ...(signal ? { signal } : {}),
114
+ onSettle: (wait) => kit[RECORD_LOCK_WAIT](wait),
115
+ },
116
+ );
104
117
  return {
105
118
  applied,
106
- upToDate: applied.length === 0,
119
+ upToDate: applied.length === 0 && waiting.length === 0,
120
+ ...(waiting.length > 0 ? { waiting } : {}),
107
121
  waited,
108
122
  waitedMs,
109
123
  attempts,
@@ -197,4 +197,4 @@ async function runMigration(params) {
197
197
  }
198
198
  }
199
199
 
200
- module.exports = { runMigration };
200
+ module.exports = { isTransactionsUnsupported, runMigration };