| @@ -28,9 +28,9 @@ | ||
| 28 | 28 | TagRelationsMigrator::class, |
| 29 | 29 | DataMetrixMigrator::class, |
| 30 | 30 | MetaMigrator::class, |
| 31 | 31 | MailBoxMigrator::class, |
| 32 | - ActivityMigrator::class | |
| 32 | + ActivityMigrator::class, | |
| 33 | 33 | ]; |
| 34 | 34 | |
| 35 | 35 | public static function run($network_wide = false) |
| 36 | 36 | { |
| @@ -63,6 +63,52 @@ | ||
| 63 | 63 | { |
| 64 | 64 | foreach (static::$migrators as $class) { |
| 65 | 65 | $class::migrate(); |
| 66 | 66 | } |
| 67 | + } | |
| 68 | + | |
| 69 | + // Version-gated re-run for in-place updates that never reactivate; locked so concurrent requests don't race. | |
| 70 | + public static function maybeMigrateDBChanges() | |
| 71 | + { | |
| 72 | + $currentDbVersion = get_option('fluent_support_db_version'); | |
| 73 | + | |
| 74 | + if ($currentDbVersion && !version_compare($currentDbVersion, FLUENT_SUPPORT_DB_VERSION, '<')) { | |
| 75 | + return; | |
| 76 | + } | |
| 77 | + | |
| 78 | + if (!self::acquireMigrationLock()) { | |
| 79 | + return; | |
| 80 | + } | |
| 81 | + | |
| 82 | + self::migrate(); | |
| 83 | + update_option('fluent_support_db_version', FLUENT_SUPPORT_DB_VERSION, 'no'); | |
| 84 | + | |
| 85 | + self::releaseMigrationLock(); | |
| 86 | + } | |
| 87 | + | |
| 88 | + // MySQL advisory lock (zero-wait); fails open on NULL so a locking hiccup never blocks upgrades. | |
| 89 | + private static function acquireMigrationLock() | |
| 90 | + { | |
| 91 | + global $wpdb; | |
| 92 | + | |
| 93 | + $acquired = $wpdb->get_var($wpdb->prepare("SELECT GET_LOCK(%s, 0)", self::getMigrationLockName())); | |
| 94 | + | |
| 95 | + return $acquired === null || (string) $acquired === '1'; | |
| 96 | + } | |
| 97 | + | |
| 98 | + private static function releaseMigrationLock() | |
| 99 | + { | |
| 100 | + global $wpdb; | |
| 101 | + | |
| 102 | + $wpdb->query($wpdb->prepare("SELECT RELEASE_LOCK(%s)", self::getMigrationLockName())); | |
| 103 | + } | |
| 104 | + | |
| 105 | + private static function getMigrationLockName() | |
| 106 | + { | |
| 107 | + global $wpdb; | |
| 108 | + | |
| 109 | + // GET_LOCK names are server-wide; scope to this site's DB and prefix. | |
| 110 | + $dbName = defined('DB_NAME') ? DB_NAME : ''; | |
| 111 | + | |
| 112 | + return 'fs_db_migration_' . md5($dbName . '|' . $wpdb->prefix); | |
| 67 | 113 | } |
| 68 | 114 | } |