percolatestudio / meteor-migrations

Simple migration system for Meteor
https://atmospherejs.com/percolate/migrations
MIT License
245 stars 59 forks source link

Async Migrations are not run in sequence #89

Open vparpoil opened 1 month ago

vparpoil commented 1 month ago

Let's say you have 2 async migrations that needs to be run. Migration 2 should wait for Migration 1 to be completed to execute.

Since migrate() function is not async and not awaited, this doesn't work

I will work on a PR for this

rb365 commented 1 week ago

In case someone needs quick and dirty way to do this while we wait for the PR to get merged and released

(Adjust sleep time as necessary)


const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

const SLEEP_TIME = 2000;

// TODO: remove this hack when they release this PR: https://github.com/percolatestudio/meteor-migrations/pull/90
export const runMigrationSequentially = async (targetVersion: string | number) => {
  if (targetVersion != 'latest' && typeof targetVersion !== 'number') {
    targetVersion = parseInt(targetVersion);
  }
  const currentVersion = await Migrations.getVersion();
  console.log("Current version:", currentVersion, "Target version:", targetVersion)
  const isUp = typeof targetVersion === 'number' 
    ? targetVersion > currentVersion
    : targetVersion === 'latest';

  if (isUp) {
    // Get all migration versions between current and target
    const allVersions = Migrations._list.map(m => m.version).sort((a, b) => a - b);
    const versionsToRun = allVersions.filter(v => v > currentVersion);

    console.log("Versions to run:", versionsToRun)

    // Run migrations one by one
    for (const version of versionsToRun) {
      console.log(`Running migration ${version}`);
      Migrations.migrateTo(version.toString());
      await sleep(SLEEP_TIME);
    }
  } else {
    // Handle downgrade case
    const targetVersionNum = parseInt(targetVersion as string);
    const versionsToRun = Array.from(
      { length: currentVersion - targetVersionNum },
      (_, i) => currentVersion - i
    );

    console.log("Versions to run:", versionsToRun)

    for (const version of versionsToRun) {
      console.log(`Rolling back migration ${version}`);
      Migrations.migrateTo((version - 1).toString());
      await sleep(SLEEP_TIME);
    }
  }
};