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:
Daniel Gasienica 2018-03-30 16:31:33 -04:00
parent 887bd83852
commit 805031ade8
6 changed files with 87 additions and 25 deletions

View 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.');
},
}];
};

View file

@ -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;
};

View file

@ -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;
};