Conditionally run post-attachment migrations
Introduce placeholder migrations for Backbone models so they never implicitly run migrations whenever they are `fetch`ed. We prefer to run our migrations explicitly upon app startup and then let Backbone models be (slightly) dumb(er) models, without inadvertently triggering migrations.
This commit is contained in:
parent
887bd83852
commit
805031ade8
6 changed files with 87 additions and 25 deletions
|
@ -83,23 +83,15 @@
|
|||
const cancelInitializationMessage = Views.Initialization.setMessage();
|
||||
console.log('Start IndexedDB migrations');
|
||||
|
||||
console.log('Migrate database with attachments');
|
||||
console.log('Run migrations on database with attachment data');
|
||||
await Migrations0DatabaseWithAttachmentData.run({ Backbone });
|
||||
|
||||
// console.log('Migrate attachments to disk');
|
||||
// const database = Migrations0DatabaseWithAttachmentData.getDatabase();
|
||||
// await MessageDataMigrator.processAll({
|
||||
// Backbone,
|
||||
// databaseName: database.name,
|
||||
// minDatabaseVersion: database.version,
|
||||
// upgradeMessageSchema,
|
||||
// });
|
||||
|
||||
// console.log('Migrate database without attachments');
|
||||
// await Migrations1DatabaseWithoutAttachmentData.run({
|
||||
// Backbone,
|
||||
// database: Whisper.Database,
|
||||
// });
|
||||
const database = Whisper.Database;
|
||||
const status = await Migrations1DatabaseWithoutAttachmentData.getStatus({ database });
|
||||
console.log('Run migrations on database without attachment data:', status);
|
||||
if (status.canRun) {
|
||||
await Migrations1DatabaseWithoutAttachmentData.run({ Backbone, database });
|
||||
}
|
||||
|
||||
console.log('Storage fetch');
|
||||
storage.fetch();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
const { Migrations0DatabaseWithAttachmentData } = window.Signal.Migrations;
|
||||
const { getPlaceholderMigrations } = window.Signal.Migrations;
|
||||
|
||||
window.Whisper = window.Whisper || {};
|
||||
window.Whisper.Database = window.Whisper.Database || {};
|
||||
|
@ -123,5 +123,5 @@
|
|||
request.onsuccess = resolve;
|
||||
}));
|
||||
|
||||
Whisper.Database.migrations = Migrations0DatabaseWithAttachmentData.migrations;
|
||||
Whisper.Database.migrations = getPlaceholderMigrations();
|
||||
}());
|
||||
|
|
23
js/modules/migrations/get_placeholder_migrations.js
Normal file
23
js/modules/migrations/get_placeholder_migrations.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
const Migrations0DatabaseWithAttachmentData =
|
||||
require('./migrations_0_database_with_attachment_data');
|
||||
const Migrations1DatabaseWithoutAttachmentData =
|
||||
require('./migrations_1_database_without_attachment_data');
|
||||
|
||||
|
||||
exports.getPlaceholderMigrations = () => {
|
||||
const last0MigrationVersion =
|
||||
Migrations0DatabaseWithAttachmentData.getLatestVersion();
|
||||
const last1MigrationVersion =
|
||||
Migrations1DatabaseWithoutAttachmentData.getLatestVersion();
|
||||
|
||||
const lastMigrationVersion = last1MigrationVersion || last0MigrationVersion;
|
||||
|
||||
return [{
|
||||
version: lastMigrationVersion,
|
||||
migrate() {
|
||||
throw new Error('Unexpected invocation of placeholder migration!' +
|
||||
'\n\nMigrations must explicitly be run upon application startup instead' +
|
||||
' of implicitly via Backbone IndexedDB adapter at any time.');
|
||||
},
|
||||
}];
|
||||
};
|
|
@ -154,3 +154,12 @@ exports.getDatabase = () => ({
|
|||
name: database.id,
|
||||
version: last(exports.migrations).version,
|
||||
});
|
||||
|
||||
exports.getLatestVersion = () => {
|
||||
const lastMigration = last(migrations);
|
||||
if (!lastMigration) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return lastMigration.version;
|
||||
};
|
||||
|
|
|
@ -1,15 +1,50 @@
|
|||
const last = require('lodash/last');
|
||||
|
||||
const db = require('../database');
|
||||
const settings = require('../settings');
|
||||
const { runMigrations } = require('./run_migrations');
|
||||
|
||||
|
||||
exports.migrations = [
|
||||
// NOTE: Add new migrations that need to traverse entire database, e.g. messages
|
||||
// store, here. These will only run after attachment migration has completed in
|
||||
// the background:
|
||||
const migrations = [
|
||||
// {
|
||||
// version: 18,
|
||||
// async migrate(transaction, next) {
|
||||
// console.log('Migration 18');
|
||||
// console.log('Attachments stored on disk');
|
||||
// version: 0,
|
||||
// migrate(transaction, next) {
|
||||
// next();
|
||||
// },
|
||||
// },
|
||||
];
|
||||
|
||||
exports.run = runMigrations;
|
||||
exports.run = async ({ Backbone, database } = {}) => {
|
||||
const { canRun } = await exports.getStatus({ database });
|
||||
if (!canRun) {
|
||||
throw new Error('Cannot run migrations on database without attachment data');
|
||||
}
|
||||
|
||||
await runMigrations({ Backbone, database });
|
||||
};
|
||||
|
||||
exports.getStatus = async ({ database } = {}) => {
|
||||
const connection = await db.open(database.id, database.version);
|
||||
const isAttachmentMigrationComplete =
|
||||
await settings.isAttachmentMigrationComplete(connection);
|
||||
const hasMigrations = migrations.length > 0;
|
||||
|
||||
const canRun = isAttachmentMigrationComplete && hasMigrations;
|
||||
return {
|
||||
isAttachmentMigrationComplete,
|
||||
hasMigrations,
|
||||
canRun,
|
||||
};
|
||||
};
|
||||
|
||||
exports.getLatestVersion = () => {
|
||||
const lastMigration = last(migrations);
|
||||
if (!lastMigration) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return lastMigration.version;
|
||||
};
|
||||
|
|
|
@ -119,6 +119,8 @@
|
|||
const upgradeMessageSchema = message =>
|
||||
Message.upgradeSchema(message, upgradeSchemaContext);
|
||||
|
||||
const { getPlaceholderMigrations } =
|
||||
require('./js/modules/migrations/get_placeholder_migrations');
|
||||
const { IdleDetector} = require('./js/modules/idle_detector');
|
||||
|
||||
window.Signal = {};
|
||||
|
@ -128,13 +130,14 @@
|
|||
window.Signal.Debug = require('./js/modules/debug');
|
||||
window.Signal.Logs = require('./js/modules/logs');
|
||||
window.Signal.Migrations = {};
|
||||
window.Signal.Migrations.loadAttachmentData = Attachment.loadData(readAttachmentData);
|
||||
window.Signal.Migrations.deleteAttachmentData = Attachment.deleteData(deleteAttachmentData);
|
||||
window.Signal.Migrations.upgradeMessageSchema = upgradeMessageSchema;
|
||||
window.Signal.Migrations.getPlaceholderMigrations =getPlaceholderMigrations;
|
||||
window.Signal.Migrations.loadAttachmentData = Attachment.loadData(readAttachmentData);
|
||||
window.Signal.Migrations.Migrations0DatabaseWithAttachmentData =
|
||||
require('./js/modules/migrations/migrations_0_database_with_attachment_data');
|
||||
window.Signal.Migrations.Migrations1DatabaseWithoutAttachmentData =
|
||||
require('./js/modules/migrations/migrations_1_database_without_attachment_data');
|
||||
window.Signal.Migrations.upgradeMessageSchema = upgradeMessageSchema;
|
||||
window.Signal.OS = require('./js/modules/os');
|
||||
window.Signal.Settings = require('./js/modules/settings');
|
||||
window.Signal.Types = {};
|
||||
|
|
Loading…
Add table
Reference in a new issue