Fix v2.19.1 migration schema connection ownership
This commit is contained in:
1 parent
9ca372429b
commit
0044cbc1fc
2 files changed
+41
-16
No files matched your search
+8
-11
@@ -830,14 +830,13 @@ const VERSIONED_MIGRATIONS = [
|
|||||||
version: '2.19.1',
|
version: '2.19.1',
|
||||||
label: 'v2.19.1 rebuild managed font references',
|
label: 'v2.19.1 rebuild managed font references',
|
||||||
run: async function (pool) {
|
run: async function (pool) {
|
||||||
const connection = await pool.getConnection();
|
|
||||||
try {
|
try {
|
||||||
await connection.beginTransaction();
|
await pool.beginTransaction();
|
||||||
await connection.query('DELETE FROM c_content_references WHERE reference_type = ?', ['font-family']);
|
await pool.query('DELETE FROM c_content_references WHERE reference_type = ?', ['font-family']);
|
||||||
|
|
||||||
let lastSlideId = 0;
|
let lastSlideId = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
const [slides] = await connection.query(
|
const [slides] = await pool.query(
|
||||||
'SELECT id, content_json FROM c_slides WHERE id > ? AND content_json IS NOT NULL ORDER BY id ASC LIMIT 500',
|
'SELECT id, content_json FROM c_slides WHERE id > ? AND content_json IS NOT NULL ORDER BY id ASC LIMIT 500',
|
||||||
[lastSlideId]
|
[lastSlideId]
|
||||||
);
|
);
|
||||||
@@ -847,13 +846,13 @@ const VERSIONED_MIGRATIONS = [
|
|||||||
references.push.apply(references, collectContentReferences('slide', slide.id, parseJsonSafe(slide.content_json) || {})
|
references.push.apply(references, collectContentReferences('slide', slide.id, parseJsonSafe(slide.content_json) || {})
|
||||||
.filter(function (reference) { return reference.reference_type === 'font-family'; }));
|
.filter(function (reference) { return reference.reference_type === 'font-family'; }));
|
||||||
});
|
});
|
||||||
await insertContentReferences(connection, references);
|
await insertContentReferences(pool, references);
|
||||||
lastSlideId = Number(slides[slides.length - 1].id);
|
lastSlideId = Number(slides[slides.length - 1].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastRegionId = 0;
|
let lastRegionId = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
const [regions] = await connection.query(
|
const [regions] = await pool.query(
|
||||||
'SELECT id, template_id, region_key, default_content_json FROM c_template_regions WHERE id > ? AND default_content_json IS NOT NULL ORDER BY id ASC LIMIT 500',
|
'SELECT id, template_id, region_key, default_content_json FROM c_template_regions WHERE id > ? AND default_content_json IS NOT NULL ORDER BY id ASC LIMIT 500',
|
||||||
[lastRegionId]
|
[lastRegionId]
|
||||||
);
|
);
|
||||||
@@ -865,16 +864,14 @@ const VERSIONED_MIGRATIONS = [
|
|||||||
references.push.apply(references, collectContentReferences('template', region.template_id, regionContent)
|
references.push.apply(references, collectContentReferences('template', region.template_id, regionContent)
|
||||||
.filter(function (reference) { return reference.reference_type === 'font-family'; }));
|
.filter(function (reference) { return reference.reference_type === 'font-family'; }));
|
||||||
});
|
});
|
||||||
await insertContentReferences(connection, references);
|
await insertContentReferences(pool, references);
|
||||||
lastRegionId = Number(regions[regions.length - 1].id);
|
lastRegionId = Number(regions[regions.length - 1].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
await connection.commit();
|
await pool.commit();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await connection.rollback();
|
await pool.rollback();
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
|
||||||
connection.release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,9 @@ function createPool(responses) {
|
|||||||
const queries = [];
|
const queries = [];
|
||||||
return {
|
return {
|
||||||
queries,
|
queries,
|
||||||
async getConnection() { return this; },
|
|
||||||
async beginTransaction() { queries.push(['START TRANSACTION']); },
|
async beginTransaction() { queries.push(['START TRANSACTION']); },
|
||||||
async commit() { queries.push(['COMMIT']); },
|
async commit() { queries.push(['COMMIT']); },
|
||||||
async rollback() { queries.push(['ROLLBACK']); },
|
async rollback() { queries.push(['ROLLBACK']); },
|
||||||
release() { queries.push(['RELEASE CONNECTION']); },
|
|
||||||
async query(sql, params) {
|
async query(sql, params) {
|
||||||
queries.push([sql, params]);
|
queries.push([sql, params]);
|
||||||
const text = String(sql);
|
const text = String(sql);
|
||||||
@@ -244,11 +242,11 @@ test('2.19.1 migration rebuilds only managed font references for all content in
|
|||||||
assert.ok(pool.queries.some(([sql, params]) => sql.startsWith('SELECT id, content_json') && params[0] === 118));
|
assert.ok(pool.queries.some(([sql, params]) => sql.startsWith('SELECT id, content_json') && params[0] === 118));
|
||||||
assert.ok(pool.queries.some(([sql, params]) => sql.startsWith('SELECT id, template_id, region_key') && params[0] === 900));
|
assert.ok(pool.queries.some(([sql, params]) => sql.startsWith('SELECT id, template_id, region_key') && params[0] === 900));
|
||||||
assert.ok(!pool.queries.some(([sql]) => /^(UPDATE|ALTER|TRUNCATE)/.test(sql)));
|
assert.ok(!pool.queries.some(([sql]) => /^(UPDATE|ALTER|TRUNCATE)/.test(sql)));
|
||||||
assert.deepEqual(pool.queries.slice(-2), [['COMMIT'], ['RELEASE CONNECTION']]);
|
assert.deepEqual(pool.queries.slice(-1), [['COMMIT']]);
|
||||||
assert.deepEqual(await getPendingMigrations(pool, { currentVersion: '2.19.1' }), []);
|
assert.deepEqual(await getPendingMigrations(pool, { currentVersion: '2.19.1' }), []);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('2.19.1 font repair rolls back and releases its connection on failure', async () => {
|
test('2.19.1 font repair rolls back without releasing the caller-owned connection on failure', async () => {
|
||||||
const pool = createPool([
|
const pool = createPool([
|
||||||
{ match: sql => sql.includes('information_schema.COLUMNS'), result: [[{ column_count: 1 }]] },
|
{ match: sql => sql.includes('information_schema.COLUMNS'), result: [[{ column_count: 1 }]] },
|
||||||
{ match: sql => sql.includes('information_schema.TABLES'), result: [[{ table_count: 0 }]] }
|
{ match: sql => sql.includes('information_schema.TABLES'), result: [[{ table_count: 0 }]] }
|
||||||
@@ -261,6 +259,36 @@ test('2.19.1 font repair rolls back and releases its connection on failure', asy
|
|||||||
};
|
};
|
||||||
|
|
||||||
await assert.rejects(migration.run(pool), /read failed/);
|
await assert.rejects(migration.run(pool), /read failed/);
|
||||||
assert.deepEqual(pool.queries.slice(-2), [['ROLLBACK'], ['RELEASE CONNECTION']]);
|
assert.deepEqual(pool.queries.slice(-1), [['ROLLBACK']]);
|
||||||
assert.ok(!pool.queries.some(([sql]) => sql === 'COMMIT'));
|
assert.ok(!pool.queries.some(([sql]) => sql === 'COMMIT'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('schema startup runs the 2.19.1 repair on its existing locked connection', async () => {
|
||||||
|
const { ensureSchema } = require('../src/db');
|
||||||
|
const connection = createPool([
|
||||||
|
{ match: sql => sql.includes('SELECT GET_LOCK'), result: [[{ lock_acquired: 1 }]] },
|
||||||
|
{ match: (sql, params) => sql.includes('information_schema.TABLES') && params[0] === 'o_app_state', result: [[{ table_count: 1 }]] },
|
||||||
|
{ match: sql => sql.startsWith('SELECT state_value'), result: [[{ state_value: '2.19.0' }]] },
|
||||||
|
{ match: sql => sql.includes('information_schema.COLUMNS'), result: [[{ column_count: 1 }]] },
|
||||||
|
{ match: sql => sql.includes('information_schema.TABLES'), result: [[{ table_count: 0 }]] }
|
||||||
|
]);
|
||||||
|
connection.release = function () { connection.queries.push(['RELEASE CONNECTION']); };
|
||||||
|
let acquisitions = 0;
|
||||||
|
|
||||||
|
await ensureSchema({
|
||||||
|
async getConnection() {
|
||||||
|
acquisitions += 1;
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(acquisitions, 1);
|
||||||
|
const commitIndex = connection.queries.findIndex(([sql]) => sql === 'COMMIT');
|
||||||
|
const versionIndex = connection.queries.findIndex(([sql, params]) => sql.startsWith('UPDATE o_app_state') && params[0] === '2.19.1');
|
||||||
|
assert.ok(commitIndex > 0);
|
||||||
|
assert.ok(versionIndex > commitIndex);
|
||||||
|
assert.deepEqual(connection.queries.slice(-2), [
|
||||||
|
['SELECT RELEASE_LOCK(?)', ['pulse_signage_schema_lock']],
|
||||||
|
['RELEASE CONNECTION']
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user