core: reduce unnecessary syncing during password change

This commit is contained in:
Abdullah Atta
2023-11-02 12:21:01 +05:00
committed by Abdullah Atta
parent 3465a816c6
commit aa3d778ad1
4 changed files with 64 additions and 106 deletions

View File

@@ -33,7 +33,6 @@ import Constants from "../utils/constants";
import { EV, EVENTS } from "../common"; import { EV, EVENTS } from "../common";
import Settings from "./settings"; import Settings from "./settings";
import Migrations from "./migrations"; import Migrations from "./migrations";
import Outbox from "./outbox";
import UserManager from "./user-manager"; import UserManager from "./user-manager";
import http from "../utils/http"; import http from "../utils/http";
import Monographs from "./monographs"; import Monographs from "./monographs";
@@ -90,7 +89,6 @@ class Database {
this.backup = new Backup(this); this.backup = new Backup(this);
this.settings = new Settings(this); this.settings = new Settings(this);
this.migrations = new Migrations(this); this.migrations = new Migrations(this);
this.outbox = new Outbox(this);
this.monographs = new Monographs(this); this.monographs = new Monographs(this);
this.offers = new Offers(); this.offers = new Offers();
this.debug = new Debug(); this.debug = new Debug();
@@ -127,7 +125,6 @@ class Database {
await this.initCollections(); await this.initCollections();
await this.outbox.init();
await this.migrations.init(); await this.migrations.init();
this.isInitialized = true; this.isInitialized = true;
if (this.migrations.required()) { if (this.migrations.required()) {
@@ -275,8 +272,17 @@ class Database {
return (await this.storage.read("lastSynced")) || 0; return (await this.storage.read("lastSynced")) || 0;
} }
sync(full = true, force = false, lastSynced = null) { /**
return this.syncer.start(full, force, lastSynced); *
* @param {{
* type: "full" | "fetch" | "send";
* force?: boolean;
* serverLastSynced?: number;
* }} options
* @returns
*/
sync(options) {
return this.syncer.start(options);
} }
/** /**

View File

@@ -1,57 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class Outbox {
/**
*
* @param {import("./index").default} db
*/
constructor(db) {
this._db = db;
this.outbox = {};
}
async init() {
this.outbox = (await this._db.storage.read("outbox")) || {};
for (var id in this.outbox) {
const data = this.outbox[id];
switch (id) {
case "reset_password":
case "change_password":
if (await this._db.user._updatePassword(id, data))
await this.delete(id);
break;
}
}
}
async add(id, data, action) {
this.outbox[id] = data;
await this._db.storage.write("outbox", this.outbox);
await action();
await this.delete(id);
}
delete(id) {
delete this.outbox[id];
return this._db.storage.write("outbox", this.outbox);
}
}
export default Outbox;

View File

@@ -53,10 +53,10 @@ export default class SyncManager {
this._db = db; this._db = db;
} }
async start(full, force, serverLastSynced) { async start(options) {
try { try {
await this.sync.autoSync.start(); await this.sync.autoSync.start();
await this.sync.start(full, force, serverLastSynced); await this.sync.start(options);
return true; return true;
} catch (e) { } catch (e) {
var isHubException = e.message.includes("HubException:"); var isHubException = e.message.includes("HubException:");
@@ -176,18 +176,20 @@ class Sync {
/** /**
* *
* @param {boolean} full * @param {{
* @param {boolean} force * type: "full" | "fetch" | "send";
* @param {number} serverLastSynced * force?: boolean;
* serverLastSynced?: number;
* }} options
*/ */
async start(full, force, serverLastSynced) { async start(options) {
if (!(await checkSyncStatus(SYNC_CHECK_IDS.sync))) { if (!(await checkSyncStatus(SYNC_CHECK_IDS.sync))) {
await this.connection.stop(); await this.connection.stop();
return; return;
} }
if (!(await this.db.user.getUser())) return; if (!(await this.db.user.getUser())) return;
this.logger.info("Starting sync", { full, force, serverLastSynced }); this.logger.info("Starting sync", options);
this.connection.onclose((error) => { this.connection.onclose((error) => {
this.db.eventManager.publish(EVENTS.syncAborted); this.db.eventManager.publish(EVENTS.syncAborted);
@@ -196,15 +198,21 @@ class Sync {
throw new Error("Connection closed."); throw new Error("Connection closed.");
}); });
const { lastSynced, oldLastSynced } = await this.init(force); const { lastSynced, oldLastSynced } = await this.init(options.force);
this.logger.info("Initialized sync", { lastSynced, oldLastSynced }); this.logger.info("Initialized sync", { lastSynced, oldLastSynced });
const newLastSynced = Date.now(); const newLastSynced = Date.now();
const serverResponse = full ? await this.fetch(lastSynced) : null; const serverResponse =
options.type === "fetch" || options.type === "full"
? await this.fetch(lastSynced)
: null;
this.logger.info("Data fetched", serverResponse); this.logger.info("Data fetched", serverResponse);
if (await this.send(lastSynced, force, newLastSynced)) { if (
(options.type === "send" || options.type === "full") &&
(await this.send(lastSynced, options.force, newLastSynced))
) {
this.logger.info("New data sent"); this.logger.info("New data sent");
await this.stop(newLastSynced); await this.stop(newLastSynced);
} else if (serverResponse) { } else if (serverResponse) {
@@ -212,7 +220,7 @@ class Sync {
await this.stop(serverResponse.lastSynced); await this.stop(serverResponse.lastSynced);
} else { } else {
this.logger.info("Nothing to do."); this.logger.info("Nothing to do.");
await this.stop(serverLastSynced || oldLastSynced); await this.stop(options.serverLastSynced || oldLastSynced);
} }
if (!(await checkSyncStatus(SYNC_CHECK_IDS.autoSync))) { if (!(await checkSyncStatus(SYNC_CHECK_IDS.autoSync))) {

View File

@@ -454,44 +454,45 @@ class UserManager {
const attachmentsKey = await this.getAttachmentsKey(); const attachmentsKey = await this.getAttachmentsKey();
data.encryptionKey = data.encryptionKey || (await this.getEncryptionKey()); data.encryptionKey = data.encryptionKey || (await this.getEncryptionKey());
await this._db.outbox.add(type, data, async () => {
if (data.encryptionKey) await this._db.sync(true, true);
await this._storage.deriveCryptoKey(`_uk_@${email}`, { await this.clearSessions();
password: new_password,
salt
});
if (!(await this.resetUser(false))) return; if (data.encryptionKey) await this._db.sync({ type: "fetch", force: true });
if (attachmentsKey) { await this._storage.deriveCryptoKey(`_uk_@${email}`, {
const userEncryptionKey = await this.getEncryptionKey(); password: new_password,
if (!userEncryptionKey) return; salt
user.attachmentsKey = await this._storage.encrypt(
userEncryptionKey,
JSON.stringify(attachmentsKey)
);
await this.updateUser(user);
}
await this._db.sync(false, true);
if (old_password)
old_password = await this._storage.hash(old_password, email);
if (new_password)
new_password = await this._storage.hash(new_password, email);
await http.patch(
`${constants.AUTH_HOST}${ENDPOINTS.patchUser}`,
{
type,
old_password,
new_password
},
token
);
}); });
if (!(await this.resetUser(false))) return;
await this._db.sync({ type: "send", force: true });
if (attachmentsKey) {
const userEncryptionKey = await this.getEncryptionKey();
if (!userEncryptionKey) return;
user.attachmentsKey = await this._storage.encrypt(
userEncryptionKey,
JSON.stringify(attachmentsKey)
);
await this.updateUser(user);
}
if (old_password)
old_password = await this._storage.hash(old_password, email);
if (new_password)
new_password = await this._storage.hash(new_password, email);
await http.patch(
`${constants.AUTH_HOST}${ENDPOINTS.patchUser}`,
{
type,
old_password,
new_password
},
token
);
return true; return true;
} }
} }