2017-10-25 10:58:59 +08:00
|
|
|
"use strict";
|
|
|
|
|
2018-04-02 09:27:46 +08:00
|
|
|
const syncService = require('../../services/sync');
|
|
|
|
const syncUpdateService = require('../../services/sync_update');
|
|
|
|
const syncTableService = require('../../services/sync_table');
|
2017-11-01 07:34:58 +08:00
|
|
|
const sql = require('../../services/sql');
|
2018-07-25 02:35:03 +08:00
|
|
|
const sqlInit = require('../../services/sql_init');
|
2018-04-02 09:27:46 +08:00
|
|
|
const optionService = require('../../services/options');
|
|
|
|
const contentHashService = require('../../services/content_hash');
|
2017-12-24 02:16:18 +08:00
|
|
|
const log = require('../../services/log');
|
2018-09-11 16:09:55 +08:00
|
|
|
const syncOptions = require('../../services/sync_options');
|
2019-11-14 05:32:14 +08:00
|
|
|
const dateUtils = require('../../services/date_utils');
|
2019-12-19 05:58:30 +08:00
|
|
|
const entityConstructor = require('../../entities/entity_constructor');
|
|
|
|
const utils = require('../../services/utils');
|
2017-11-22 11:11:27 +08:00
|
|
|
|
2018-07-23 16:29:17 +08:00
|
|
|
async function testSync() {
|
|
|
|
try {
|
2018-09-11 16:09:55 +08:00
|
|
|
if (!await syncOptions.isSyncSetup()) {
|
|
|
|
return { success: false, message: "Sync server host is not configured. Please configure sync first." };
|
|
|
|
}
|
|
|
|
|
2018-09-11 02:22:26 +08:00
|
|
|
await syncService.login();
|
2018-07-23 16:29:17 +08:00
|
|
|
|
2018-09-11 02:22:26 +08:00
|
|
|
// login was successful so we'll kick off sync now
|
|
|
|
// this is important in case when sync server has been just initialized
|
|
|
|
syncService.sync();
|
2018-09-11 02:05:10 +08:00
|
|
|
|
2018-09-11 02:22:26 +08:00
|
|
|
return { success: true, message: "Sync server handshake has been successful, sync has been started." };
|
2018-07-23 16:29:17 +08:00
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
return {
|
2018-09-11 02:05:10 +08:00
|
|
|
success: false,
|
2018-09-11 16:09:55 +08:00
|
|
|
message: e.message
|
2018-07-23 16:29:17 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-24 03:15:32 +08:00
|
|
|
async function getStats() {
|
2018-07-25 15:46:57 +08:00
|
|
|
if (!await sqlInit.schemaExists()) {
|
|
|
|
// fail silently but prevent errors from not existing options table
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2018-07-24 14:12:36 +08:00
|
|
|
return {
|
|
|
|
initialized: await optionService.getOption('initialized') === 'true',
|
|
|
|
stats: syncService.stats
|
|
|
|
};
|
2018-07-24 03:15:32 +08:00
|
|
|
}
|
|
|
|
|
2018-03-31 02:27:41 +08:00
|
|
|
async function checkSync() {
|
|
|
|
return {
|
2019-12-19 05:58:30 +08:00
|
|
|
entityHashes: await contentHashService.getEntityHashes(),
|
2018-04-08 22:09:33 +08:00
|
|
|
maxSyncId: await sql.getValue('SELECT MAX(id) FROM sync')
|
2018-03-31 02:27:41 +08:00
|
|
|
};
|
|
|
|
}
|
2017-10-25 10:58:59 +08:00
|
|
|
|
2018-03-31 02:27:41 +08:00
|
|
|
async function syncNow() {
|
2018-04-02 09:27:46 +08:00
|
|
|
return await syncService.sync();
|
2018-03-31 02:27:41 +08:00
|
|
|
}
|
2017-10-29 23:22:41 +08:00
|
|
|
|
2018-03-31 02:27:41 +08:00
|
|
|
async function fillSyncRows() {
|
2018-04-02 09:27:46 +08:00
|
|
|
await syncTableService.fillAllSyncRows();
|
2017-12-20 11:04:51 +08:00
|
|
|
|
2017-12-24 02:16:18 +08:00
|
|
|
log.info("Sync rows have been filled.");
|
2018-03-31 02:27:41 +08:00
|
|
|
}
|
2017-12-24 02:16:18 +08:00
|
|
|
|
2018-03-31 02:27:41 +08:00
|
|
|
async function forceFullSync() {
|
2018-04-03 09:47:46 +08:00
|
|
|
await optionService.setOption('lastSyncedPull', 0);
|
|
|
|
await optionService.setOption('lastSyncedPush', 0);
|
2017-12-14 12:03:48 +08:00
|
|
|
|
2017-12-24 02:16:18 +08:00
|
|
|
log.info("Forcing full sync.");
|
|
|
|
|
2017-12-14 12:03:48 +08:00
|
|
|
// not awaiting for the job to finish (will probably take a long time)
|
2018-04-02 09:27:46 +08:00
|
|
|
syncService.sync();
|
2018-03-31 02:27:41 +08:00
|
|
|
}
|
2017-12-14 12:03:48 +08:00
|
|
|
|
2018-03-31 02:27:41 +08:00
|
|
|
async function forceNoteSync(req) {
|
2017-12-31 10:44:26 +08:00
|
|
|
const noteId = req.params.noteId;
|
|
|
|
|
2019-11-14 05:32:14 +08:00
|
|
|
const now = dateUtils.utcNowDateTime();
|
|
|
|
|
|
|
|
await sql.execute(`UPDATE notes SET utcDateModified = ? WHERE noteId = ?`, [now, noteId]);
|
2018-04-02 09:27:46 +08:00
|
|
|
await syncTableService.addNoteSync(noteId);
|
2019-11-14 05:32:14 +08:00
|
|
|
|
|
|
|
await sql.execute(`UPDATE note_contents SET utcDateModified = ? WHERE noteId = ?`, [now, noteId]);
|
2019-10-12 03:24:49 +08:00
|
|
|
await syncTableService.addNoteContentSync(noteId);
|
2017-12-31 10:44:26 +08:00
|
|
|
|
2019-11-14 04:53:04 +08:00
|
|
|
for (const branchId of await sql.getColumn("SELECT branchId FROM branches WHERE noteId = ?", [noteId])) {
|
2019-11-14 05:32:14 +08:00
|
|
|
await sql.execute(`UPDATE branches SET utcDateModified = ? WHERE branchId = ?`, [now, branchId]);
|
|
|
|
|
2018-04-02 09:27:46 +08:00
|
|
|
await syncTableService.addBranchSync(branchId);
|
2018-03-31 02:27:41 +08:00
|
|
|
}
|
2017-12-31 10:44:26 +08:00
|
|
|
|
2019-11-14 04:53:04 +08:00
|
|
|
for (const attributeId of await sql.getColumn("SELECT attributeId FROM attributes WHERE noteId = ?", [noteId])) {
|
2019-11-14 05:32:14 +08:00
|
|
|
await sql.execute(`UPDATE attributes SET utcDateModified = ? WHERE attributeId = ?`, [now, attributeId]);
|
|
|
|
|
2019-11-14 04:53:04 +08:00
|
|
|
await syncTableService.addAttributeSync(attributeId);
|
|
|
|
}
|
|
|
|
|
2018-03-31 02:27:41 +08:00
|
|
|
for (const noteRevisionId of await sql.getColumn("SELECT noteRevisionId FROM note_revisions WHERE noteId = ?", [noteId])) {
|
2019-11-14 05:32:14 +08:00
|
|
|
await sql.execute(`UPDATE note_revisions SET utcDateModified = ? WHERE noteRevisionId = ?`, [now, noteRevisionId]);
|
2018-04-02 09:27:46 +08:00
|
|
|
await syncTableService.addNoteRevisionSync(noteRevisionId);
|
2019-11-14 05:32:14 +08:00
|
|
|
|
|
|
|
await sql.execute(`UPDATE note_revision_contents SET utcDateModified = ? WHERE noteRevisionId = ?`, [now, noteRevisionId]);
|
2019-11-14 04:53:04 +08:00
|
|
|
await syncTableService.addNoteRevisionContentSync(noteRevisionId);
|
2018-03-31 02:27:41 +08:00
|
|
|
}
|
2017-12-31 10:44:26 +08:00
|
|
|
|
2019-05-22 03:47:28 +08:00
|
|
|
await syncTableService.addRecentNoteSync(noteId);
|
|
|
|
|
2017-12-31 10:44:26 +08:00
|
|
|
log.info("Forcing note sync for " + noteId);
|
|
|
|
|
|
|
|
// not awaiting for the job to finish (will probably take a long time)
|
2018-04-02 09:27:46 +08:00
|
|
|
syncService.sync();
|
2018-03-31 02:27:41 +08:00
|
|
|
}
|
2017-12-31 10:44:26 +08:00
|
|
|
|
2018-04-07 06:49:37 +08:00
|
|
|
async function getChanged(req) {
|
2017-11-01 07:34:58 +08:00
|
|
|
const lastSyncId = parseInt(req.query.lastSyncId);
|
2017-10-25 10:58:59 +08:00
|
|
|
|
2018-04-08 10:25:28 +08:00
|
|
|
const syncs = await sql.getRows("SELECT * FROM sync WHERE id > ? LIMIT 1000", [lastSyncId]);
|
2018-04-08 09:53:42 +08:00
|
|
|
|
2018-07-24 03:15:32 +08:00
|
|
|
return {
|
|
|
|
syncs: await syncService.getSyncRecords(syncs),
|
|
|
|
maxSyncId: await sql.getValue('SELECT MAX(id) FROM sync')
|
|
|
|
};
|
2018-04-08 09:53:42 +08:00
|
|
|
}
|
|
|
|
|
2018-04-08 10:25:28 +08:00
|
|
|
async function update(req) {
|
|
|
|
const sourceId = req.body.sourceId;
|
|
|
|
const entities = req.body.entities;
|
2018-04-08 09:53:42 +08:00
|
|
|
|
2018-04-08 10:25:28 +08:00
|
|
|
for (const {sync, entity} of entities) {
|
2018-04-13 06:31:29 +08:00
|
|
|
await syncUpdateService.updateEntity(sync, entity, sourceId);
|
2018-04-08 09:53:42 +08:00
|
|
|
}
|
2018-03-31 02:27:41 +08:00
|
|
|
}
|
2017-10-27 09:16:21 +08:00
|
|
|
|
2018-07-25 02:35:03 +08:00
|
|
|
async function syncFinished() {
|
|
|
|
// after first sync finishes, the application is ready to be used
|
|
|
|
// this is meaningless but at the same time harmless (idempotent) for further syncs
|
|
|
|
await sqlInit.dbInitialized();
|
|
|
|
}
|
|
|
|
|
2019-12-19 05:58:30 +08:00
|
|
|
async function queueSector(req) {
|
|
|
|
const entityName = utils.sanitizeSqlIdentifier(req.params.entityName);
|
|
|
|
const sector = utils.sanitizeSqlIdentifier(req.params.sector);
|
|
|
|
|
|
|
|
const entityPrimaryKey = entityConstructor.getEntityFromEntityName(entityName).primaryKeyName;
|
|
|
|
|
|
|
|
await syncTableService.addEntitySyncsForSector(entityName, entityPrimaryKey, sector);
|
|
|
|
}
|
|
|
|
|
2018-03-31 02:27:41 +08:00
|
|
|
module.exports = {
|
2018-07-23 16:29:17 +08:00
|
|
|
testSync,
|
2018-03-31 02:27:41 +08:00
|
|
|
checkSync,
|
|
|
|
syncNow,
|
|
|
|
fillSyncRows,
|
|
|
|
forceFullSync,
|
|
|
|
forceNoteSync,
|
|
|
|
getChanged,
|
2018-07-23 01:56:20 +08:00
|
|
|
update,
|
2018-07-25 02:35:03 +08:00
|
|
|
getStats,
|
2019-12-19 05:58:30 +08:00
|
|
|
syncFinished,
|
|
|
|
queueSector
|
2018-03-31 02:27:41 +08:00
|
|
|
};
|