const utils = require('../libs/utils'); const path = require('path'); const MongoClient = require('mongoose').mongo.MongoClient; const appConfig = require('../config/app'); const SyncSeq = require('./sync-seq'); const { format } = require('date-fns'); const remotedb = 'coloring_ol'; // 远端数据库 const localdb = 'artsite'; // 本地的数据库 /** * sync from remote */ async function run() { const localClient = await new MongoClient(appConfig.mongodbUrl).connect(); const remoteClient = await new MongoClient(appConfig.syncUrl).connect(); let remoteDB = remoteClient.db(remotedb); let localDB = localClient.db(localdb); console.log('Connect to remote mongodb ' + appConfig.syncUrl + ' success!'); // 读取远程syncevent表 const synceventTB = remoteDB.collection('syncevents'); // get current local slave sync seq (use mongoose) let seq = -1; let seqDoc = await SyncSeq.findOne(); if (seqDoc) seq = seqDoc.seq; else seqDoc = new SyncSeq({}); let count, localtb, remotetb, localdoc, remotedoc; setTimeout(async function cycleRun() { try { let eventDocs = await synceventTB.find({ _id: { $gt: seq } }).limit(200).toArray() || []; count = 0; for (let i = 0; i < eventDocs.length; i++) { let eventDoc = eventDocs[i]; console.log(eventDoc); if (eventDoc.tb == 'identitycounters') continue; // skip // 只同步特定的几张表: arts, daily-arts, users, albums, translates if (eventDoc.tb != 'arts' && eventDoc.tb != 'daily-arts' && eventDoc.tb != 'users' && eventDoc.tb != 'albums' && eventDoc.tb != 'videostories' && eventDoc.tb != 'translates') { continue; } if (!eventDoc.db) eventDoc.db = remoteDbs[0]; // 对应的表 remotetb = remoteDB.collection(eventDoc.tb); localtb = localDB.collection(eventDoc.tb); if (!remotetb || !localtb) { console.warn('unkown sync database: ' + eventDoc.db + ', will skip'); continue; } if (eventDoc.op == 'remove') { await localtb.deleteOne({ _id: eventDoc.rid }); console.log("sync remove : " + eventDoc.tb + " " + eventDoc.rid); } else if (eventDoc.op == 'save') { remotedoc = await remotetb.findOne({ _id: eventDoc.rid }); localdoc = await localtb.findOne({ _id: eventDoc.rid }); if (!remotedoc) { console.log("remote doc not found, may be deleted, skip: " + eventDoc.tb + " " + eventDoc.rid); } else if (!localdoc) { console.log("sync add :" + eventDoc.tb + " " + eventDoc.rid); try { await localtb.insertOne(remotedoc); } catch (e) { console.error(e); } } else { console.log("sync update :" + eventDoc.tb + " " + eventDoc.rid); if (eventDoc.tb == 'arts') { // art 表需保留新的title,desc,copy 这几个字段,避免覆盖 remotedoc.title = localdoc.title; remotedoc.desc = localdoc.desc; remotedoc.copy = localdoc.copy; remotedoc.subtitle = localdoc.subtitle; } else if (eventDoc.tb == 'albums' || eventDoc.tb == 'videostories') { // albums 和 videostories 表需保留新增的seoTitle,seoDescription字段,避免覆盖 remotedoc.seoTitle = localdoc.seoTitle; remotedoc.seoDescription = localdoc.seoDescription; } await localtb.replaceOne({ _id: eventDoc.rid }, remotedoc); } } seq = eventDoc._id; seqDoc.seq = seq; await seqDoc.save(); count++; } console.log(`${format(new Date(), 'yyyy-MM-dd HH:mm')} sync event length: ${eventDocs.length}, precessed: ${count}`); } catch (err) { console.error(err); } if (count > 0) setTimeout(cycleRun, 0); // else setTimeout(run, delay); }, 0); } module.exports = { run } if (require.main == module) { run().catch(console.error); }