@mikro-orm/migrations 7.3.0-dev.14 → 7.3.0-dev.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/Migrator.d.ts CHANGED
@@ -13,6 +13,8 @@ export declare class Migrator extends AbstractMigrator<AbstractSqlDriver> {
13
13
  protected getDefaultGenerator(): IMigrationGenerator;
14
14
  private getSnapshotPath;
15
15
  protected init(): Promise<void>;
16
+ /** Runs the callback while holding the migration lock (if enabled and supported by the driver). */
17
+ private runLocked;
16
18
  /**
17
19
  * @inheritDoc
18
20
  */
package/Migrator.js CHANGED
@@ -63,6 +63,46 @@ export class Migrator extends AbstractMigrator {
63
63
  await this.storage.ensureTable();
64
64
  }
65
65
  }
66
+ /** Runs the callback while holding the migration lock (if enabled and supported by the driver). */
67
+ async runLocked(cb) {
68
+ const lock = this.options.lock ? this.driver.getPlatform().getSchemaHelper().getMigrationLockSQL() : undefined;
69
+ if (!lock) {
70
+ return cb();
71
+ }
72
+ const poolMax = this.config.get('pool').max;
73
+ if (poolMax != null && poolMax < 2) {
74
+ throw new Error('The migration lock needs at least 2 pooled connections, as it holds one for the whole run');
75
+ }
76
+ // the database has to exist before a connection can be reserved, creating it may reconnect
77
+ await this.#schemaGenerator.ensureDatabase();
78
+ const connection = this.driver.getConnection();
79
+ const name = this.options.tableName;
80
+ const deadline = Date.now() + (this.options.lockTimeout ?? Infinity);
81
+ // a session-level lock on a reserved connection spans all transactions of the run, while its queries keep using the pool
82
+ return connection
83
+ .getClient()
84
+ .connection()
85
+ .execute(async (db) => {
86
+ let waiting = false;
87
+ while (!(await connection.execute(lock.acquire, [name], 'get', db)).locked) {
88
+ if (Date.now() >= deadline) {
89
+ throw new Error(`Timed out after ${this.options.lockTimeout} ms waiting for the migration lock`);
90
+ }
91
+ if (!waiting && !this.options.silent) {
92
+ const logger = this.config.getLogger();
93
+ logger.log('migrator', 'Waiting for the migration lock held by another run', { enabled: true });
94
+ }
95
+ waiting = true;
96
+ await new Promise(resolve => setTimeout(resolve, Math.min(500, deadline - Date.now())));
97
+ }
98
+ try {
99
+ return await cb();
100
+ }
101
+ finally {
102
+ await connection.execute(lock.release, [name], 'run', db);
103
+ }
104
+ });
105
+ }
66
106
  /**
67
107
  * @inheritDoc
68
108
  */
@@ -148,7 +188,7 @@ export class Migrator extends AbstractMigrator {
148
188
  };
149
189
  }
150
190
  async runMigrations(method, options) {
151
- const result = await super.runMigrations(method, options);
191
+ const result = await this.runLocked(() => super.runMigrations(method, options));
152
192
  if (result.length > 0 && this.options.snapshot && this.options.snapshotOnMigrate) {
153
193
  const ctx = Utils.isObject(options) ? options.transaction : undefined;
154
194
  const { skipTables, skipViews } = this.config.get('schemaGenerator');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/migrations",
3
- "version": "7.3.0-dev.14",
3
+ "version": "7.3.0-dev.16",
4
4
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
5
5
  "keywords": [
6
6
  "data-mapper",
@@ -47,13 +47,13 @@
47
47
  "copy": "node ../../scripts/copy.mjs"
48
48
  },
49
49
  "dependencies": {
50
- "@mikro-orm/sql": "7.3.0-dev.14"
50
+ "@mikro-orm/sql": "7.3.0-dev.16"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@mikro-orm/core": "^7.2.3"
54
54
  },
55
55
  "peerDependencies": {
56
- "@mikro-orm/core": "7.3.0-dev.14"
56
+ "@mikro-orm/core": "7.3.0-dev.16"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">= 22.17.0"