Spaces:
Running
Running
| const mongoose = require('mongoose'); | |
| const fs = require('fs').promises; | |
| const path = require('path'); | |
| // Atlas MongoDB connection string | |
| const MONGODB_URI = 'mongodb+srv://nothingyu:wSg3lbO1PkHiRMq9@sandbox.ecysggv.mongodb.net/test?retryWrites=true&w=majority&appName=sandbox'; | |
| // Connect to MongoDB Atlas | |
| const connectDB = async () => { | |
| try { | |
| await mongoose.connect(MONGODB_URI); | |
| console.log('β Connected to MongoDB Atlas'); | |
| } catch (error) { | |
| console.error('β MongoDB connection error:', error); | |
| process.exit(1); | |
| } | |
| }; | |
| // Simple Automated Backup System | |
| const automatedBackup = { | |
| // Create backup | |
| async createBackup() { | |
| try { | |
| const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); | |
| const backupName = `auto-backup-${timestamp}`; | |
| console.log(`πΎ Creating automated backup: ${backupName}`); | |
| // Collections to backup | |
| const collections = ['subtitles', 'sourcetexts', 'submissions', 'users']; | |
| const backupData = { | |
| metadata: { | |
| backupName, | |
| timestamp: new Date(), | |
| collections, | |
| totalRecords: 0, | |
| version: '1.0', | |
| type: 'automated' | |
| }, | |
| data: {} | |
| }; | |
| // Export each collection | |
| for (const collection of collections) { | |
| try { | |
| const data = await mongoose.connection.db.collection(collection).find({}).toArray(); | |
| backupData.data[collection] = data; | |
| backupData.metadata.totalRecords += data.length; | |
| console.log(` π¦ Exported ${data.length} records from ${collection}`); | |
| } catch (error) { | |
| console.warn(` β οΈ Could not export ${collection}:`, error.message); | |
| } | |
| } | |
| // Save to backup directory | |
| const backupDir = path.join(__dirname, 'backups'); | |
| await fs.mkdir(backupDir, { recursive: true }); | |
| const backupPath = path.join(backupDir, `${backupName}.json`); | |
| await fs.writeFile(backupPath, JSON.stringify(backupData, null, 2)); | |
| // Save backup record to database | |
| const backupRecord = { | |
| backupName, | |
| timestamp: new Date(), | |
| collections, | |
| totalRecords: backupData.metadata.totalRecords, | |
| filePath: backupPath, | |
| status: 'created', | |
| type: 'automated' | |
| }; | |
| await mongoose.connection.db.collection('backups').insertOne(backupRecord); | |
| console.log(`β Backup created successfully: ${backupName}`); | |
| console.log(`π Total records: ${backupData.metadata.totalRecords}`); | |
| console.log(`πΎ File saved: ${backupPath}`); | |
| return backupName; | |
| } catch (error) { | |
| console.error('β Error creating backup:', error); | |
| throw error; | |
| } | |
| }, | |
| // List backups | |
| async listBackups() { | |
| try { | |
| console.log('π Available backups:'); | |
| // List from database | |
| const dbBackups = await mongoose.connection.db.collection('backups').find({}).sort({ timestamp: -1 }).toArray(); | |
| if (dbBackups.length === 0) { | |
| console.log(' No backups found in database'); | |
| } else { | |
| console.log(' Database backups:'); | |
| dbBackups.forEach(backup => { | |
| const date = new Date(backup.timestamp).toLocaleString(); | |
| console.log(` π¦ ${backup.backupName} (${backup.totalRecords} records, ${date})`); | |
| }); | |
| } | |
| // List from file system | |
| const backupDir = path.join(__dirname, 'backups'); | |
| try { | |
| const files = await fs.readdir(backupDir); | |
| const backupFiles = files.filter(file => file.endsWith('.json')); | |
| if (backupFiles.length > 0) { | |
| console.log(' File system backups:'); | |
| for (const file of backupFiles) { | |
| const filePath = path.join(backupDir, file); | |
| const stats = await fs.stat(filePath); | |
| console.log(` πΎ ${file} (${(stats.size / 1024).toFixed(2)} KB, ${stats.mtime.toLocaleString()})`); | |
| } | |
| } | |
| } catch (error) { | |
| console.log(' No backup directory found'); | |
| } | |
| } catch (error) { | |
| console.error('β Error listing backups:', error); | |
| } | |
| }, | |
| // Clean old backups (keep last 10) | |
| async cleanOldBackups() { | |
| try { | |
| console.log('π§Ή Cleaning old backups...'); | |
| const backupCollection = mongoose.connection.db.collection('backups'); | |
| const allBackups = await backupCollection.find({}).sort({ timestamp: -1 }).toArray(); | |
| if (allBackups.length > 10) { | |
| const backupsToDelete = allBackups.slice(10); | |
| for (const backup of backupsToDelete) { | |
| // Delete file | |
| try { | |
| await fs.unlink(backup.filePath); | |
| console.log(` ποΈ Deleted file: ${backup.backupName}`); | |
| } catch (error) { | |
| console.warn(` β οΈ Could not delete file: ${backup.backupName}`); | |
| } | |
| // Delete database record | |
| await backupCollection.deleteOne({ _id: backup._id }); | |
| console.log(` ποΈ Deleted record: ${backup.backupName}`); | |
| } | |
| console.log(`β Cleaned ${backupsToDelete.length} old backups`); | |
| } else { | |
| console.log('β No old backups to clean (keeping all backups)'); | |
| } | |
| } catch (error) { | |
| console.error('β Error cleaning old backups:', error); | |
| } | |
| }, | |
| // Verify backup integrity | |
| async verifyBackup(backupName) { | |
| try { | |
| console.log(`π Verifying backup: ${backupName}`); | |
| const backupPath = path.join(__dirname, 'backups', `${backupName}.json`); | |
| const backupData = JSON.parse(await fs.readFile(backupPath, 'utf8')); | |
| let verifiedCount = 0; | |
| let failedCount = 0; | |
| for (const [collection, data] of Object.entries(backupData.data)) { | |
| try { | |
| const currentCount = await mongoose.connection.db.collection(collection).countDocuments(); | |
| const backupCount = data.length; | |
| if (currentCount === backupCount) { | |
| verifiedCount++; | |
| console.log(` β ${collection}: ${backupCount} records verified`); | |
| } else { | |
| failedCount++; | |
| console.log(` β ${collection}: ${backupCount} in backup, ${currentCount} in database`); | |
| } | |
| } catch (error) { | |
| failedCount++; | |
| console.log(` β ${collection}: verification failed`); | |
| } | |
| } | |
| console.log(`π Verification complete:`); | |
| console.log(` - Verified: ${verifiedCount} collections`); | |
| console.log(` - Failed: ${failedCount} collections`); | |
| return { verifiedCount, failedCount }; | |
| } catch (error) { | |
| console.error('β Error verifying backup:', error); | |
| } | |
| } | |
| }; | |
| // Main function | |
| const main = async () => { | |
| try { | |
| console.log('π Starting automated backup system...'); | |
| // Create backup | |
| const backupName = await automatedBackup.createBackup(); | |
| // List all backups | |
| await automatedBackup.listBackups(); | |
| // Clean old backups | |
| await automatedBackup.cleanOldBackups(); | |
| // Verify the backup | |
| await automatedBackup.verifyBackup(backupName); | |
| console.log('\nπ Automated backup system ready!'); | |
| console.log('\nπ Available functions:'); | |
| console.log(' - createBackup(): Create new backup'); | |
| console.log(' - listBackups(): List available backups'); | |
| console.log(' - cleanOldBackups(): Keep only last 10 backups'); | |
| console.log(' - verifyBackup(name): Verify backup integrity'); | |
| console.log('\nβ° To enable daily automated backups:'); | |
| console.log(' 1. Set up a cron job or scheduled task'); | |
| console.log(' 2. Run: node simple-automated-backup.js'); | |
| console.log(' 3. Or use MongoDB Atlas automatic backups (already enabled)'); | |
| } catch (error) { | |
| console.error('β Error in automated backup system:', error); | |
| } finally { | |
| await mongoose.disconnect(); | |
| console.log('π Disconnected from MongoDB'); | |
| } | |
| }; | |
| // Run the system | |
| connectDB().then(() => { | |
| main(); | |
| }); |