diff --git a/client/lib/migrationManager.js b/client/lib/migrationManager.js index c178b69e7..19ea53f10 100644 --- a/client/lib/migrationManager.js +++ b/client/lib/migrationManager.js @@ -646,6 +646,23 @@ class MigrationManager { } } + /** + * Fix boards that are stuck in migration loop + */ + fixStuckBoards() { + try { + Meteor.call('boardMigration.fixStuckBoards', (error, result) => { + if (error) { + console.error('Failed to fix stuck boards:', error); + } else { + console.log('Fix stuck boards result:', result); + } + }); + } catch (error) { + console.error('Error fixing stuck boards:', error); + } + } + /** * Start migration process using cron system */ diff --git a/server/boardMigrationDetector.js b/server/boardMigrationDetector.js index b1dfb2f1e..dac558e5d 100644 --- a/server/boardMigrationDetector.js +++ b/server/boardMigrationDetector.js @@ -314,10 +314,11 @@ class BoardMigrationDetector { */ markBoardAsMigrated(boardId, migrationType) { try { - // Update migration markers + // Update migration markers and version const updateQuery = {}; updateQuery[`migrationMarkers.${migrationType}Migrated`] = true; updateQuery['migrationMarkers.lastMigration'] = new Date(); + updateQuery['migrationVersion'] = 1; // Set migration version to prevent re-migration Boards.update(boardId, { $set: updateQuery }); @@ -392,5 +393,42 @@ Meteor.methods({ } return boardMigrationDetector.startBoardMigration(boardId); + }, + + 'boardMigration.fixStuckBoards'() { + if (!this.userId) { + throw new Meteor.Error('not-authorized'); + } + + // Find boards that have migration markers but no migrationVersion + const stuckBoards = Boards.find({ + 'migrationMarkers.fullMigrationCompleted': true, + $or: [ + { migrationVersion: { $exists: false } }, + { migrationVersion: { $lt: 1 } } + ] + }).fetch(); + + let fixedCount = 0; + stuckBoards.forEach(board => { + try { + Boards.update(board._id, { + $set: { + migrationVersion: 1, + 'migrationMarkers.lastMigration': new Date() + } + }); + fixedCount++; + console.log(`Fixed stuck board: ${board._id} (${board.title})`); + } catch (error) { + console.error(`Error fixing board ${board._id}:`, error); + } + }); + + return { + message: `Fixed ${fixedCount} stuck boards`, + fixedCount, + totalStuck: stuckBoards.length + }; } }); diff --git a/server/cronMigrationManager.js b/server/cronMigrationManager.js index 34c4e7781..a830f4ab4 100644 --- a/server/cronMigrationManager.js +++ b/server/cronMigrationManager.js @@ -607,11 +607,12 @@ class CronMigrationManager { */ markBoardAsMigrated(boardId, migrationType) { try { - // Update board with migration markers + // Update board with migration markers and version const updateQuery = { 'migrationMarkers.fullMigrationCompleted': true, 'migrationMarkers.lastMigration': new Date(), - 'migrationMarkers.migrationType': migrationType + 'migrationMarkers.migrationType': migrationType, + 'migrationVersion': 1 // Set migration version to prevent re-migration }; // Update the board document