mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2025-12-20 05:01:30 +00:00
Fixed:
- Freezing LiveSync on mobile devices.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "obsidian-livesync",
|
"id": "obsidian-livesync",
|
||||||
"name": "Self-hosted LiveSync",
|
"name": "Self-hosted LiveSync",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"minAppVersion": "0.9.12",
|
"minAppVersion": "0.9.12",
|
||||||
"description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
"description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
||||||
"author": "vorotamoroz",
|
"author": "vorotamoroz",
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"diff-match-patch": "^1.0.5",
|
"diff-match-patch": "^1.0.5",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
"description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ import { path2id } from "./utils";
|
|||||||
import { Logger } from "./lib/src/logger";
|
import { Logger } from "./lib/src/logger";
|
||||||
import { checkRemoteVersion, connectRemoteCouchDB, getLastPostFailedBySize } from "./utils_couchdb";
|
import { checkRemoteVersion, connectRemoteCouchDB, getLastPostFailedBySize } from "./utils_couchdb";
|
||||||
|
|
||||||
|
type ReplicationCallback = (e: PouchDB.Core.ExistingDocument<EntryDoc>[]) => Promise<void>;
|
||||||
|
|
||||||
export class LocalPouchDB {
|
export class LocalPouchDB {
|
||||||
auth: Credential;
|
auth: Credential;
|
||||||
dbname: string;
|
dbname: string;
|
||||||
@@ -52,7 +54,7 @@ export class LocalPouchDB {
|
|||||||
remoteLockedAndDeviceNotAccepted = false;
|
remoteLockedAndDeviceNotAccepted = false;
|
||||||
|
|
||||||
changeHandler: PouchDB.Core.Changes<EntryDoc> = null;
|
changeHandler: PouchDB.Core.Changes<EntryDoc> = null;
|
||||||
syncHandler: PouchDB.Replication.Sync<EntryDoc> = null;
|
syncHandler: PouchDB.Replication.Sync<EntryDoc> | PouchDB.Replication.Replication<EntryDoc> = null;
|
||||||
|
|
||||||
leafArrivedCallbacks: { [key: string]: (() => void)[] } = {};
|
leafArrivedCallbacks: { [key: string]: (() => void)[] } = {};
|
||||||
|
|
||||||
@@ -61,6 +63,8 @@ export class LocalPouchDB {
|
|||||||
docSent = 0;
|
docSent = 0;
|
||||||
docSeq = "";
|
docSeq = "";
|
||||||
|
|
||||||
|
isMobile = false;
|
||||||
|
|
||||||
cancelHandler<T extends PouchDB.Core.Changes<EntryDoc> | PouchDB.Replication.Sync<EntryDoc> | PouchDB.Replication.Replication<EntryDoc>>(handler: T): T {
|
cancelHandler<T extends PouchDB.Core.Changes<EntryDoc> | PouchDB.Replication.Sync<EntryDoc> | PouchDB.Replication.Replication<EntryDoc>>(handler: T): T {
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler.removeAllListeners();
|
handler.removeAllListeners();
|
||||||
@@ -77,7 +81,7 @@ export class LocalPouchDB {
|
|||||||
this.localDatabase.removeAllListeners();
|
this.localDatabase.removeAllListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(settings: RemoteDBSettings, dbname: string) {
|
constructor(settings: RemoteDBSettings, dbname: string, isMobile: boolean) {
|
||||||
this.auth = {
|
this.auth = {
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
@@ -85,6 +89,7 @@ export class LocalPouchDB {
|
|||||||
this.dbname = dbname;
|
this.dbname = dbname;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.cancelHandler = this.cancelHandler.bind(this);
|
this.cancelHandler = this.cancelHandler.bind(this);
|
||||||
|
this.isMobile = isMobile;
|
||||||
|
|
||||||
// this.initializeDatabase();
|
// this.initializeDatabase();
|
||||||
}
|
}
|
||||||
@@ -699,73 +704,18 @@ export class LocalPouchDB {
|
|||||||
replicateAllToServer(setting: RemoteDBSettings, showingNotice?: boolean) {
|
replicateAllToServer(setting: RemoteDBSettings, showingNotice?: boolean) {
|
||||||
return new Promise(async (res, rej) => {
|
return new Promise(async (res, rej) => {
|
||||||
await this.waitForGCComplete();
|
await this.waitForGCComplete();
|
||||||
this.closeReplication();
|
this.openOneshotReplication(
|
||||||
Logger("send all data to server", LOG_LEVEL.NOTICE);
|
setting,
|
||||||
let notice: WrappedNotice = null;
|
showingNotice,
|
||||||
if (showingNotice) {
|
async (e) => {},
|
||||||
notice = NewNotice("Initializing", 0);
|
false,
|
||||||
}
|
(e) => {
|
||||||
this.syncStatus = "STARTED";
|
if (e === true) res(e);
|
||||||
this.updateInfo();
|
|
||||||
const uri = setting.couchDB_URI + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
|
|
||||||
const auth: Credential = {
|
|
||||||
username: setting.couchDB_USER,
|
|
||||||
password: setting.couchDB_PASSWORD,
|
|
||||||
};
|
|
||||||
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
|
||||||
if (typeof dbret === "string") {
|
|
||||||
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
|
||||||
if (notice != null) notice.hide();
|
|
||||||
return rej(`could not connect to ${uri}:${dbret}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const syncOptionBase: PouchDB.Replication.SyncOptions = {
|
|
||||||
pull: {
|
|
||||||
checkpoint: "target",
|
|
||||||
},
|
|
||||||
push: {
|
|
||||||
checkpoint: "source",
|
|
||||||
},
|
|
||||||
batches_limit: setting.batches_limit,
|
|
||||||
batch_size: setting.batch_size,
|
|
||||||
};
|
|
||||||
|
|
||||||
const db = dbret.db;
|
|
||||||
const totalCount = (await this.localDatabase.info()).doc_count;
|
|
||||||
//replicate once
|
|
||||||
const replicate = this.localDatabase.replicate.to(db, { checkpoint: "source", ...syncOptionBase });
|
|
||||||
replicate
|
|
||||||
.on("active", () => {
|
|
||||||
this.syncStatus = "CONNECTED";
|
|
||||||
this.updateInfo();
|
|
||||||
if (notice) {
|
|
||||||
notice.setMessage("CONNECTED");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on("change", (e) => {
|
|
||||||
// no op.
|
|
||||||
this.docSent += e.docs.length;
|
|
||||||
this.updateInfo();
|
|
||||||
notice.setMessage(`SENDING:${e.docs_written}/${totalCount}`);
|
|
||||||
Logger(`replicateAllToServer: sending..:${e.docs.length}`);
|
|
||||||
})
|
|
||||||
.on("complete", (info) => {
|
|
||||||
this.syncStatus = "COMPLETED";
|
|
||||||
this.updateInfo();
|
|
||||||
Logger("replicateAllToServer: Completed", LOG_LEVEL.NOTICE);
|
|
||||||
this.cancelHandler(replicate);
|
|
||||||
if (notice != null) notice.hide();
|
|
||||||
res(true);
|
|
||||||
})
|
|
||||||
.on("error", (e) => {
|
|
||||||
this.syncStatus = "ERRORED";
|
|
||||||
this.updateInfo();
|
|
||||||
Logger("replicateAllToServer: Pulling Replication error", LOG_LEVEL.INFO);
|
|
||||||
Logger(e);
|
|
||||||
this.cancelHandler(replicate);
|
|
||||||
if (notice != null) notice.hide();
|
|
||||||
rej(e);
|
rej(e);
|
||||||
});
|
},
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -789,7 +739,8 @@ export class LocalPouchDB {
|
|||||||
Logger("Another replication running.");
|
Logger("Another replication running.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
|
||||||
|
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI || this.isMobile);
|
||||||
if (typeof dbret === "string") {
|
if (typeof dbret === "string") {
|
||||||
Logger(`could not connect to ${uri}: ${dbret}`, LOG_LEVEL.NOTICE);
|
Logger(`could not connect to ${uri}: ${dbret}`, LOG_LEVEL.NOTICE);
|
||||||
return false;
|
return false;
|
||||||
@@ -830,53 +781,20 @@ export class LocalPouchDB {
|
|||||||
return { db: dbret.db, info: dbret.info, syncOptionBase, syncOption };
|
return { db: dbret.db, info: dbret.info, syncOptionBase, syncOption };
|
||||||
}
|
}
|
||||||
|
|
||||||
async openReplication(setting: RemoteDBSettings, keepAlive: boolean, showResult: boolean, callback: (e: PouchDB.Core.ExistingDocument<EntryDoc>[]) => Promise<void>): Promise<boolean> {
|
openReplication(setting: RemoteDBSettings, keepAlive: boolean, showResult: boolean, callback: (e: PouchDB.Core.ExistingDocument<EntryDoc>[]) => Promise<void>) {
|
||||||
return await runWithLock("replicate", false, () => {
|
if (keepAlive) {
|
||||||
return this._openReplication(setting, keepAlive, showResult, callback, false);
|
this.openContinuousReplication(setting, showResult, callback, false);
|
||||||
});
|
} else {
|
||||||
|
this.openOneshotReplication(setting, showResult, callback, false, null, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
originalSetting: RemoteDBSettings = null;
|
|
||||||
// last_seq: number = 200;
|
|
||||||
async _openReplication(setting: RemoteDBSettings, keepAlive: boolean, showResult: boolean, callback: (e: PouchDB.Core.ExistingDocument<EntryDoc>[]) => Promise<void>, retrying: boolean): Promise<boolean> {
|
|
||||||
const ret = await this.checkReplicationConnectivity(setting, keepAlive, retrying);
|
|
||||||
if (ret === false) return false;
|
|
||||||
let notice: WrappedNotice = null;
|
|
||||||
if (showResult) {
|
|
||||||
notice = NewNotice("Looking for the point last synchronized point.", 0);
|
|
||||||
}
|
}
|
||||||
const { db, syncOptionBase, syncOption } = ret;
|
replicationActivated(notice: WrappedNotice) {
|
||||||
//replicate once
|
|
||||||
this.syncStatus = "STARTED";
|
|
||||||
this.updateInfo();
|
|
||||||
|
|
||||||
let resolved = false;
|
|
||||||
const docArrivedOnStart = this.docArrived;
|
|
||||||
const docSentOnStart = this.docSent;
|
|
||||||
|
|
||||||
const _openReplicationSync = () => {
|
|
||||||
Logger("Sync Main Started");
|
|
||||||
if (!retrying) {
|
|
||||||
this.originalSetting = setting;
|
|
||||||
}
|
|
||||||
this.syncHandler = this.cancelHandler(this.syncHandler);
|
|
||||||
this.syncHandler = this.localDatabase.sync<EntryDoc>(db, {
|
|
||||||
...syncOption,
|
|
||||||
pull: {
|
|
||||||
checkpoint: "target",
|
|
||||||
},
|
|
||||||
push: {
|
|
||||||
checkpoint: "source",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.syncHandler
|
|
||||||
.on("active", () => {
|
|
||||||
this.syncStatus = "CONNECTED";
|
this.syncStatus = "CONNECTED";
|
||||||
this.updateInfo();
|
this.updateInfo();
|
||||||
Logger("Replication activated");
|
Logger("Replication activated");
|
||||||
if (notice != null) notice.setMessage(`Activated..`);
|
if (notice != null) notice.setMessage(`Activated..`);
|
||||||
})
|
}
|
||||||
.on("change", async (e) => {
|
async replicationChangeDetected(e: PouchDB.Replication.SyncResult<EntryDoc>, notice: WrappedNotice, docSentOnStart: number, docArrivedOnStart: number, callback: ReplicationCallback) {
|
||||||
try {
|
try {
|
||||||
if (e.direction == "pull") {
|
if (e.direction == "pull") {
|
||||||
await callback(e.change.docs);
|
await callback(e.change.docs);
|
||||||
@@ -892,126 +810,226 @@ export class LocalPouchDB {
|
|||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
Logger("Replication callback error", LOG_LEVEL.NOTICE);
|
Logger("Replication callback error", LOG_LEVEL.NOTICE);
|
||||||
Logger(ex, LOG_LEVEL.NOTICE);
|
Logger(ex, LOG_LEVEL.NOTICE);
|
||||||
}
|
//
|
||||||
// re-connect to retry with original setting
|
|
||||||
if (retrying) {
|
|
||||||
if (this.docSent - docSentOnStart + (this.docArrived - docArrivedOnStart) > this.originalSetting.batch_size * 2) {
|
|
||||||
// restore sync values
|
|
||||||
Logger("Back into original settings once.");
|
|
||||||
if (notice != null) notice.hide();
|
|
||||||
this.syncHandler = this.cancelHandler(this.syncHandler);
|
|
||||||
this._openReplication(this.originalSetting, keepAlive, showResult, callback, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
replicationCompleted(notice: WrappedNotice, showResult: boolean) {
|
||||||
.on("complete", (e) => {
|
|
||||||
this.syncStatus = "COMPLETED";
|
this.syncStatus = "COMPLETED";
|
||||||
this.updateInfo();
|
this.updateInfo();
|
||||||
Logger("Replication completed", showResult ? LOG_LEVEL.NOTICE : LOG_LEVEL.INFO);
|
Logger("Replication completed", showResult ? LOG_LEVEL.NOTICE : LOG_LEVEL.INFO);
|
||||||
if (notice != null) notice.hide();
|
if (notice != null) notice.hide();
|
||||||
if (!keepAlive) {
|
|
||||||
this.syncHandler = this.cancelHandler(this.syncHandler);
|
this.syncHandler = this.cancelHandler(this.syncHandler);
|
||||||
// if keep alive runnning, resolve here,
|
|
||||||
}
|
}
|
||||||
})
|
replicationDeniend(notice: WrappedNotice, e: any) {
|
||||||
.on("denied", (e) => {
|
|
||||||
this.syncStatus = "ERRORED";
|
this.syncStatus = "ERRORED";
|
||||||
this.updateInfo();
|
this.updateInfo();
|
||||||
this.syncHandler = this.cancelHandler(this.syncHandler);
|
this.syncHandler = this.cancelHandler(this.syncHandler);
|
||||||
if (notice != null) notice.hide();
|
if (notice != null) notice.hide();
|
||||||
Logger("Replication denied", LOG_LEVEL.NOTICE);
|
Logger("Replication denied", LOG_LEVEL.NOTICE);
|
||||||
Logger(e);
|
Logger(e);
|
||||||
})
|
}
|
||||||
.on("error", (e) => {
|
replicationErrored(notice: WrappedNotice, e: any) {
|
||||||
this.syncStatus = "ERRORED";
|
this.syncStatus = "ERRORED";
|
||||||
this.syncHandler = this.cancelHandler(this.syncHandler);
|
this.syncHandler = this.cancelHandler(this.syncHandler);
|
||||||
this.updateInfo();
|
this.updateInfo();
|
||||||
|
}
|
||||||
|
replicationPaused(notice: WrappedNotice) {
|
||||||
|
this.syncStatus = "PAUSED";
|
||||||
|
this.updateInfo();
|
||||||
|
if (notice != null) notice.hide();
|
||||||
|
Logger("replication paused", LOG_LEVEL.VERBOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
async openOneshotReplication(
|
||||||
|
setting: RemoteDBSettings,
|
||||||
|
showResult: boolean,
|
||||||
|
callback: (e: PouchDB.Core.ExistingDocument<EntryDoc>[]) => Promise<void>,
|
||||||
|
retrying: boolean,
|
||||||
|
callbackDone: (e: boolean | any) => void,
|
||||||
|
pushOnly: boolean,
|
||||||
|
pullOnly: boolean
|
||||||
|
): Promise<boolean> {
|
||||||
|
if (this.syncHandler != null) {
|
||||||
|
Logger("Replication is already in progress.", showResult ? LOG_LEVEL.NOTICE : LOG_LEVEL.INFO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Logger("Oneshot Sync begin...");
|
||||||
|
let thisCallback = callbackDone;
|
||||||
|
const ret = await this.checkReplicationConnectivity(setting, true, retrying);
|
||||||
|
let notice: WrappedNotice = null;
|
||||||
|
if (ret === false) {
|
||||||
|
Logger("Could not connect to server.", LOG_LEVEL.NOTICE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (showResult) {
|
||||||
|
notice = NewNotice("Looking for the point last synchronized point.", 0);
|
||||||
|
}
|
||||||
|
const { db, syncOptionBase } = ret;
|
||||||
|
this.syncStatus = "STARTED";
|
||||||
|
this.updateInfo();
|
||||||
|
const docArrivedOnStart = this.docArrived;
|
||||||
|
const docSentOnStart = this.docSent;
|
||||||
|
if (!retrying) {
|
||||||
|
// If initial replication, save setting to rollback
|
||||||
|
this.originalSetting = setting;
|
||||||
|
}
|
||||||
|
this.syncHandler = this.cancelHandler(this.syncHandler);
|
||||||
|
if (!pushOnly && !pullOnly) {
|
||||||
|
this.syncHandler = this.localDatabase.sync(db, { checkpoint: "target", ...syncOptionBase });
|
||||||
|
this.syncHandler
|
||||||
|
.on("change", async (e) => {
|
||||||
|
await this.replicationChangeDetected(e, notice, docSentOnStart, docArrivedOnStart, callback);
|
||||||
|
if (retrying) {
|
||||||
|
if (this.docSent - docSentOnStart + (this.docArrived - docArrivedOnStart) > this.originalSetting.batch_size * 2) {
|
||||||
|
// restore configration.
|
||||||
|
Logger("Back into original settings once.");
|
||||||
|
if (notice != null) notice.hide();
|
||||||
|
this.syncHandler = this.cancelHandler(this.syncHandler);
|
||||||
|
this.openOneshotReplication(this.originalSetting, showResult, callback, false, callbackDone, pushOnly, pullOnly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on("complete", (e) => {
|
||||||
|
this.replicationCompleted(notice, showResult);
|
||||||
|
if (thisCallback != null) {
|
||||||
|
thisCallback(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (pullOnly) {
|
||||||
|
this.syncHandler = this.localDatabase.replicate.to(db, { checkpoint: "target", ...syncOptionBase });
|
||||||
|
this.syncHandler
|
||||||
|
.on("change", async (e) => {
|
||||||
|
await this.replicationChangeDetected({ direction: "pull", change: e }, notice, docSentOnStart, docArrivedOnStart, callback);
|
||||||
|
if (retrying) {
|
||||||
|
if (this.docSent - docSentOnStart + (this.docArrived - docArrivedOnStart) > this.originalSetting.batch_size * 2) {
|
||||||
|
// restore configration.
|
||||||
|
Logger("Back into original settings once.");
|
||||||
|
if (notice != null) notice.hide();
|
||||||
|
this.syncHandler = this.cancelHandler(this.syncHandler);
|
||||||
|
this.openOneshotReplication(this.originalSetting, showResult, callback, false, callbackDone, pushOnly, pullOnly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on("complete", (e) => {
|
||||||
|
this.replicationCompleted(notice, showResult);
|
||||||
|
if (thisCallback != null) {
|
||||||
|
thisCallback(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (pushOnly) {
|
||||||
|
this.syncHandler = this.localDatabase.replicate.to(db, { checkpoint: "target", ...syncOptionBase });
|
||||||
|
this.syncHandler.on("complete", (e) => {
|
||||||
|
this.replicationCompleted(notice, showResult);
|
||||||
|
if (thisCallback != null) {
|
||||||
|
thisCallback(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.syncHandler
|
||||||
|
.on("active", () => this.replicationActivated(notice))
|
||||||
|
.on("denied", (e) => {
|
||||||
|
this.replicationDeniend(notice, e);
|
||||||
|
if (thisCallback != null) {
|
||||||
|
thisCallback(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on("error", (e) => {
|
||||||
|
this.replicationErrored(notice, e);
|
||||||
|
Logger("Replication stopped.", showResult ? LOG_LEVEL.NOTICE : LOG_LEVEL.INFO);
|
||||||
if (notice != null) notice.hide();
|
if (notice != null) notice.hide();
|
||||||
if (getLastPostFailedBySize()) {
|
if (getLastPostFailedBySize()) {
|
||||||
if (keepAlive) {
|
|
||||||
Logger("Replication stopped.", LOG_LEVEL.NOTICE);
|
|
||||||
} else {
|
|
||||||
// Duplicate settings for smaller batch.
|
// Duplicate settings for smaller batch.
|
||||||
const xsetting: RemoteDBSettings = JSON.parse(JSON.stringify(setting));
|
const xsetting: RemoteDBSettings = JSON.parse(JSON.stringify(setting));
|
||||||
xsetting.batch_size = Math.ceil(xsetting.batch_size / 2);
|
xsetting.batch_size = Math.ceil(xsetting.batch_size / 2) + 2;
|
||||||
xsetting.batches_limit = Math.ceil(xsetting.batches_limit / 2);
|
xsetting.batches_limit = Math.ceil(xsetting.batches_limit / 2) + 2;
|
||||||
if (xsetting.batch_size <= 3 || xsetting.batches_limit <= 3) {
|
if (xsetting.batch_size <= 5 && xsetting.batches_limit <= 5) {
|
||||||
Logger("We can't replicate more lower value.", showResult ? LOG_LEVEL.NOTICE : LOG_LEVEL.INFO);
|
Logger("We can't replicate more lower value.", showResult ? LOG_LEVEL.NOTICE : LOG_LEVEL.INFO);
|
||||||
} else {
|
} else {
|
||||||
Logger(`Retry with lower batch size:${xsetting.batch_size}/${xsetting.batches_limit}`, showResult ? LOG_LEVEL.NOTICE : LOG_LEVEL.INFO);
|
Logger(`Retry with lower batch size:${xsetting.batch_size}/${xsetting.batches_limit}`, showResult ? LOG_LEVEL.NOTICE : LOG_LEVEL.INFO);
|
||||||
this._openReplication(xsetting, keepAlive, showResult, callback, true);
|
thisCallback = null;
|
||||||
}
|
this.openOneshotReplication(xsetting, showResult, callback, true, callbackDone, pushOnly, pullOnly);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Logger("Replication error", LOG_LEVEL.NOTICE);
|
Logger("Replication error", LOG_LEVEL.NOTICE);
|
||||||
Logger(e);
|
Logger(e);
|
||||||
}
|
}
|
||||||
})
|
if (thisCallback != null) {
|
||||||
.on("paused", (e) => {
|
thisCallback(e);
|
||||||
this.syncStatus = "PAUSED";
|
|
||||||
this.updateInfo();
|
|
||||||
if (notice != null) notice.hide();
|
|
||||||
Logger("replication paused", LOG_LEVEL.VERBOSE);
|
|
||||||
if (keepAlive && !resolved) {
|
|
||||||
// if keep alive runnning, resolve here,
|
|
||||||
resolved = true;
|
|
||||||
}
|
}
|
||||||
// Logger(e);
|
})
|
||||||
});
|
.on("paused", (e) => this.replicationPaused(notice));
|
||||||
return this.syncHandler;
|
}
|
||||||
};
|
|
||||||
if (!keepAlive) {
|
openContinuousReplication(setting: RemoteDBSettings, showResult: boolean, callback: (e: PouchDB.Core.ExistingDocument<EntryDoc>[]) => Promise<void>, retrying: boolean) {
|
||||||
await _openReplicationSync();
|
if (this.syncHandler != null) {
|
||||||
return true;
|
Logger("Replication is already in progress.", showResult ? LOG_LEVEL.NOTICE : LOG_LEVEL.INFO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Logger("Before LiveSync, start OneShot once...");
|
||||||
|
this.openOneshotReplication(
|
||||||
|
setting,
|
||||||
|
showResult,
|
||||||
|
callback,
|
||||||
|
false,
|
||||||
|
async () => {
|
||||||
|
Logger("LiveSync begin...");
|
||||||
|
const ret = await this.checkReplicationConnectivity(setting, true, true);
|
||||||
|
let notice: WrappedNotice = null;
|
||||||
|
if (ret === false) {
|
||||||
|
Logger("Could not connect to server.", showResult ? LOG_LEVEL.NOTICE : LOG_LEVEL.INFO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (showResult) {
|
||||||
|
notice = NewNotice("Looking for the point last synchronized point.", 0);
|
||||||
|
}
|
||||||
|
const { db, syncOption } = ret;
|
||||||
|
this.syncStatus = "STARTED";
|
||||||
|
this.updateInfo();
|
||||||
|
const docArrivedOnStart = this.docArrived;
|
||||||
|
const docSentOnStart = this.docSent;
|
||||||
|
if (!retrying) {
|
||||||
|
//TODO if successfly saven, roll back org setting.
|
||||||
|
this.originalSetting = setting;
|
||||||
}
|
}
|
||||||
this.syncHandler = this.cancelHandler(this.syncHandler);
|
this.syncHandler = this.cancelHandler(this.syncHandler);
|
||||||
Logger("Pull before replicate.");
|
this.syncHandler = this.localDatabase.sync<EntryDoc>(db, {
|
||||||
Logger(await this.localDatabase.info(), LOG_LEVEL.VERBOSE);
|
...syncOption,
|
||||||
Logger(await db.info(), LOG_LEVEL.VERBOSE);
|
pull: {
|
||||||
let replicate: PouchDB.Replication.Replication<EntryDoc>;
|
checkpoint: "target",
|
||||||
try {
|
},
|
||||||
replicate = this.localDatabase.replicate.from(db, { checkpoint: "target", ...syncOptionBase });
|
push: {
|
||||||
replicate
|
checkpoint: "source",
|
||||||
.on("active", () => {
|
},
|
||||||
this.syncStatus = "CONNECTED";
|
});
|
||||||
this.updateInfo();
|
this.syncHandler
|
||||||
Logger("Replication pull activated.");
|
.on("active", () => this.replicationActivated(notice))
|
||||||
})
|
|
||||||
.on("change", async (e) => {
|
.on("change", async (e) => {
|
||||||
// when in first run, replication will send us tombstone data
|
await this.replicationChangeDetected(e, notice, docSentOnStart, docArrivedOnStart, callback);
|
||||||
// and in normal cases, all leavs should sent before the entry that contains these item.
|
if (retrying) {
|
||||||
// so skip to completed all, we should treat all changes.
|
if (this.docSent - docSentOnStart + (this.docArrived - docArrivedOnStart) > this.originalSetting.batch_size * 2) {
|
||||||
try {
|
// restore sync values
|
||||||
await callback(e.docs);
|
Logger("Back into original settings once.");
|
||||||
this.docArrived += e.docs.length;
|
|
||||||
this.updateInfo();
|
|
||||||
Logger(`pulled ${e.docs.length} doc(s)`);
|
|
||||||
if (notice != null) {
|
|
||||||
notice.setMessage(`Replication pulled:${e.docs_read}`);
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
Logger("Replication callback error", LOG_LEVEL.NOTICE);
|
|
||||||
Logger(ex, LOG_LEVEL.NOTICE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.syncStatus = "COMPLETED";
|
|
||||||
this.updateInfo();
|
|
||||||
this.cancelHandler(replicate);
|
|
||||||
this.syncHandler = this.cancelHandler(this.syncHandler);
|
|
||||||
Logger("Replication pull completed.");
|
|
||||||
_openReplicationSync();
|
|
||||||
return true;
|
|
||||||
} catch (ex) {
|
|
||||||
this.syncStatus = "ERRORED";
|
|
||||||
this.updateInfo();
|
|
||||||
Logger("Pulling Replication error:", LOG_LEVEL.NOTICE);
|
|
||||||
Logger(ex, LOG_LEVEL.NOTICE);
|
|
||||||
this.cancelHandler(replicate);
|
|
||||||
this.syncHandler = this.cancelHandler(this.syncHandler);
|
|
||||||
if (notice != null) notice.hide();
|
if (notice != null) notice.hide();
|
||||||
throw ex;
|
this.syncHandler = this.cancelHandler(this.syncHandler);
|
||||||
|
this.openContinuousReplication(this.originalSetting, showResult, callback, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.on("complete", (e) => this.replicationCompleted(notice, showResult))
|
||||||
|
.on("denied", (e) => this.replicationDeniend(notice, e))
|
||||||
|
.on("error", (e) => {
|
||||||
|
this.replicationErrored(notice, e);
|
||||||
|
Logger("Replication stopped.", LOG_LEVEL.NOTICE);
|
||||||
|
})
|
||||||
|
.on("paused", (e) => this.replicationPaused(notice));
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
originalSetting: RemoteDBSettings = null;
|
||||||
|
|
||||||
closeReplication() {
|
closeReplication() {
|
||||||
this.syncStatus = "CLOSED";
|
this.syncStatus = "CLOSED";
|
||||||
@@ -1039,7 +1057,7 @@ export class LocalPouchDB {
|
|||||||
username: setting.couchDB_USER,
|
username: setting.couchDB_USER,
|
||||||
password: setting.couchDB_PASSWORD,
|
password: setting.couchDB_PASSWORD,
|
||||||
};
|
};
|
||||||
const con = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
const con = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI || this.isMobile);
|
||||||
if (typeof con == "string") return;
|
if (typeof con == "string") return;
|
||||||
try {
|
try {
|
||||||
await con.db.destroy();
|
await con.db.destroy();
|
||||||
@@ -1057,7 +1075,7 @@ export class LocalPouchDB {
|
|||||||
username: setting.couchDB_USER,
|
username: setting.couchDB_USER,
|
||||||
password: setting.couchDB_PASSWORD,
|
password: setting.couchDB_PASSWORD,
|
||||||
};
|
};
|
||||||
const con2 = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
const con2 = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI || this.isMobile);
|
||||||
if (typeof con2 === "string") return;
|
if (typeof con2 === "string") return;
|
||||||
Logger("Remote Database Created or Connected", LOG_LEVEL.NOTICE);
|
Logger("Remote Database Created or Connected", LOG_LEVEL.NOTICE);
|
||||||
}
|
}
|
||||||
@@ -1067,7 +1085,7 @@ export class LocalPouchDB {
|
|||||||
username: setting.couchDB_USER,
|
username: setting.couchDB_USER,
|
||||||
password: setting.couchDB_PASSWORD,
|
password: setting.couchDB_PASSWORD,
|
||||||
};
|
};
|
||||||
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI || this.isMobile);
|
||||||
if (typeof dbret === "string") {
|
if (typeof dbret === "string") {
|
||||||
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
||||||
return;
|
return;
|
||||||
@@ -1101,7 +1119,7 @@ export class LocalPouchDB {
|
|||||||
username: setting.couchDB_USER,
|
username: setting.couchDB_USER,
|
||||||
password: setting.couchDB_PASSWORD,
|
password: setting.couchDB_PASSWORD,
|
||||||
};
|
};
|
||||||
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI || this.isMobile);
|
||||||
if (typeof dbret === "string") {
|
if (typeof dbret === "string") {
|
||||||
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -171,12 +171,18 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
new Setting(containerRemoteDatabaseEl).setName("Use the old connecting method").addToggle((toggle) =>
|
|
||||||
|
new Setting(containerRemoteDatabaseEl)
|
||||||
|
.setDesc("This feature is locked in mobile")
|
||||||
|
.setName("Use the old connecting method")
|
||||||
|
.addToggle((toggle) => {
|
||||||
toggle.setValue(this.plugin.settings.disableRequestURI).onChange(async (value) => {
|
toggle.setValue(this.plugin.settings.disableRequestURI).onChange(async (value) => {
|
||||||
this.plugin.settings.disableRequestURI = value;
|
this.plugin.settings.disableRequestURI = value;
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
|
});
|
||||||
|
toggle.setDisabled(this.plugin.isMobile);
|
||||||
|
return toggle;
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
new Setting(containerRemoteDatabaseEl)
|
new Setting(containerRemoteDatabaseEl)
|
||||||
|
|||||||
33
src/main.ts
33
src/main.ts
@@ -64,6 +64,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
statusBar2: HTMLElement;
|
statusBar2: HTMLElement;
|
||||||
suspended: boolean;
|
suspended: boolean;
|
||||||
deviceAndVaultName: string;
|
deviceAndVaultName: string;
|
||||||
|
isMobile = false;
|
||||||
|
|
||||||
setInterval(handler: () => any, timeout?: number): number {
|
setInterval(handler: () => any, timeout?: number): number {
|
||||||
const timer = window.setInterval(handler, timeout);
|
const timer = window.setInterval(handler, timeout);
|
||||||
@@ -93,6 +94,11 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
const lsname = "obsidian-live-sync-ver" + this.app.vault.getName();
|
const lsname = "obsidian-live-sync-ver" + this.app.vault.getName();
|
||||||
const last_version = localStorage.getItem(lsname);
|
const last_version = localStorage.getItem(lsname);
|
||||||
await this.loadSettings();
|
await this.loadSettings();
|
||||||
|
//@ts-ignore
|
||||||
|
if (this.app.isMobile) {
|
||||||
|
this.isMobile = true;
|
||||||
|
this.settings.disableRequestURI = true;
|
||||||
|
}
|
||||||
if (last_version && Number(last_version) < VER) {
|
if (last_version && Number(last_version) < VER) {
|
||||||
this.settings.liveSync = false;
|
this.settings.liveSync = false;
|
||||||
this.settings.syncOnSave = false;
|
this.settings.syncOnSave = false;
|
||||||
@@ -180,7 +186,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
await this.realizeSettingSyncMode();
|
await this.realizeSettingSyncMode();
|
||||||
this.registerWatchEvents();
|
this.registerWatchEvents();
|
||||||
if (this.settings.syncOnStart) {
|
if (this.settings.syncOnStart) {
|
||||||
await this.localDatabase.openReplication(this.settings, false, false, this.parseReplicationResult);
|
this.localDatabase.openReplication(this.settings, false, false, this.parseReplicationResult);
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
Logger("Error while loading Self-hosted LiveSync", LOG_LEVEL.NOTICE);
|
Logger("Error while loading Self-hosted LiveSync", LOG_LEVEL.NOTICE);
|
||||||
@@ -190,8 +196,8 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
this.addCommand({
|
this.addCommand({
|
||||||
id: "livesync-replicate",
|
id: "livesync-replicate",
|
||||||
name: "Replicate now",
|
name: "Replicate now",
|
||||||
callback: () => {
|
callback: async () => {
|
||||||
this.replicate();
|
await this.replicate();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.addCommand({
|
this.addCommand({
|
||||||
@@ -306,7 +312,9 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
const vaultName = this.app.vault.getName();
|
const vaultName = this.app.vault.getName();
|
||||||
Logger("Open Database...");
|
Logger("Open Database...");
|
||||||
this.localDatabase = new LocalPouchDB(this.settings, vaultName);
|
//@ts-ignore
|
||||||
|
const isMobile = this.app.isMobile;
|
||||||
|
this.localDatabase = new LocalPouchDB(this.settings, vaultName, isMobile);
|
||||||
this.localDatabase.updateInfo = () => {
|
this.localDatabase.updateInfo = () => {
|
||||||
this.refreshStatusText();
|
this.refreshStatusText();
|
||||||
};
|
};
|
||||||
@@ -389,10 +397,10 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
await this.sweepPlugin(false);
|
await this.sweepPlugin(false);
|
||||||
}
|
}
|
||||||
if (this.settings.liveSync) {
|
if (this.settings.liveSync) {
|
||||||
await this.localDatabase.openReplication(this.settings, true, false, this.parseReplicationResult);
|
this.localDatabase.openReplication(this.settings, true, false, this.parseReplicationResult);
|
||||||
}
|
}
|
||||||
if (this.settings.syncOnStart) {
|
if (this.settings.syncOnStart) {
|
||||||
await this.localDatabase.openReplication(this.settings, false, false, this.parseReplicationResult);
|
this.localDatabase.openReplication(this.settings, false, false, this.parseReplicationResult);
|
||||||
}
|
}
|
||||||
if (this.settings.periodicReplication) {
|
if (this.settings.periodicReplication) {
|
||||||
this.setPeriodicSync();
|
this.setPeriodicSync();
|
||||||
@@ -408,7 +416,9 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
|
|
||||||
async watchWorkspaceOpenAsync(file: TFile) {
|
async watchWorkspaceOpenAsync(file: TFile) {
|
||||||
await this.applyBatchChange();
|
await this.applyBatchChange();
|
||||||
if (file == null) return;
|
if (file == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.settings.syncOnFileOpen && !this.suspended) {
|
if (this.settings.syncOnFileOpen && !this.suspended) {
|
||||||
await this.replicate();
|
await this.replicate();
|
||||||
}
|
}
|
||||||
@@ -449,7 +459,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
|
|
||||||
async applyBatchChange() {
|
async applyBatchChange() {
|
||||||
if (!this.settings.batchSave || this.batchFileChange.length == 0) {
|
if (!this.settings.batchSave || this.batchFileChange.length == 0) {
|
||||||
return [];
|
return;
|
||||||
}
|
}
|
||||||
return await runWithLock("batchSave", false, async () => {
|
return await runWithLock("batchSave", false, async () => {
|
||||||
const batchItems = JSON.parse(JSON.stringify(this.batchFileChange)) as string[];
|
const batchItems = JSON.parse(JSON.stringify(this.batchFileChange)) as string[];
|
||||||
@@ -467,7 +477,8 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.refreshStatusText();
|
this.refreshStatusText();
|
||||||
return await Promise.all(promises);
|
await allSettledWithConcurrencyLimit(promises, 3);
|
||||||
|
return;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,7 +913,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
await this.sweepPlugin(false);
|
await this.sweepPlugin(false);
|
||||||
}
|
}
|
||||||
if (this.settings.liveSync) {
|
if (this.settings.liveSync) {
|
||||||
await this.localDatabase.openReplication(this.settings, true, false, this.parseReplicationResult);
|
this.localDatabase.openReplication(this.settings, true, false, this.parseReplicationResult);
|
||||||
this.refreshStatusText();
|
this.refreshStatusText();
|
||||||
}
|
}
|
||||||
this.setPeriodicSync();
|
this.setPeriodicSync();
|
||||||
@@ -971,7 +982,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
if (this.settings.autoSweepPlugins) {
|
if (this.settings.autoSweepPlugins) {
|
||||||
await this.sweepPlugin(false);
|
await this.sweepPlugin(false);
|
||||||
}
|
}
|
||||||
await this.localDatabase.openReplication(this.settings, false, showMessage, this.parseReplicationResult);
|
this.localDatabase.openReplication(this.settings, false, showMessage, this.parseReplicationResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
async initializeDatabase(showingNotice?: boolean) {
|
async initializeDatabase(showingNotice?: boolean) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
import { PouchDB } from "../pouchdb-browser-webpack/dist/pouchdb-browser.js";
|
import { PouchDB as PouchDB_ } from "../pouchdb-browser-webpack/dist/pouchdb-browser.js";
|
||||||
console.dir(PouchDB)
|
|
||||||
export { PouchDB };
|
const Pouch: PouchDB.Static = PouchDB_;
|
||||||
|
export { Pouch as PouchDB };
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ export const connectRemoteCouchDB = async (uri: string, auth: { username: string
|
|||||||
adapter: "http",
|
adapter: "http",
|
||||||
auth,
|
auth,
|
||||||
fetch: async function (url: string | Request, opts: RequestInit) {
|
fetch: async function (url: string | Request, opts: RequestInit) {
|
||||||
let size_ok = true;
|
|
||||||
let size = "";
|
let size = "";
|
||||||
const localURL = url.toString().substring(uri.length);
|
const localURL = url.toString().substring(uri.length);
|
||||||
const method = opts.method ?? "GET";
|
const method = opts.method ?? "GET";
|
||||||
@@ -49,7 +48,6 @@ export const connectRemoteCouchDB = async (uri: string, auth: { username: string
|
|||||||
const opts_length = opts.body.toString().length;
|
const opts_length = opts.body.toString().length;
|
||||||
if (opts_length > 1024 * 1024 * 10) {
|
if (opts_length > 1024 * 1024 * 10) {
|
||||||
// over 10MB
|
// over 10MB
|
||||||
size_ok = false;
|
|
||||||
if (uri.contains(".cloudantnosqldb.")) {
|
if (uri.contains(".cloudantnosqldb.")) {
|
||||||
last_post_successed = false;
|
last_post_successed = false;
|
||||||
Logger("This request should fail on IBM Cloudant.", LOG_LEVEL.VERBOSE);
|
Logger("This request should fail on IBM Cloudant.", LOG_LEVEL.VERBOSE);
|
||||||
@@ -93,7 +91,8 @@ export const connectRemoteCouchDB = async (uri: string, auth: { username: string
|
|||||||
});
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
Logger(`HTTP:${method}${size} to:${localURL} -> failed`, LOG_LEVEL.VERBOSE);
|
Logger(`HTTP:${method}${size} to:${localURL} -> failed`, LOG_LEVEL.VERBOSE);
|
||||||
if (!size_ok && (method == "POST" || method == "PUT")) {
|
// limit only in bulk_docs.
|
||||||
|
if (url.toString().indexOf("_bulk_docs") !== -1) {
|
||||||
last_post_successed = false;
|
last_post_successed = false;
|
||||||
}
|
}
|
||||||
Logger(ex);
|
Logger(ex);
|
||||||
@@ -114,7 +113,8 @@ export const connectRemoteCouchDB = async (uri: string, auth: { username: string
|
|||||||
return responce;
|
return responce;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
Logger(`HTTP:${method}${size} to:${localURL} -> failed`, LOG_LEVEL.VERBOSE);
|
Logger(`HTTP:${method}${size} to:${localURL} -> failed`, LOG_LEVEL.VERBOSE);
|
||||||
if (!size_ok && (method == "POST" || method == "PUT")) {
|
// limit only in bulk_docs.
|
||||||
|
if (url.toString().indexOf("_bulk_docs") !== -1) {
|
||||||
last_post_successed = false;
|
last_post_successed = false;
|
||||||
}
|
}
|
||||||
Logger(ex);
|
Logger(ex);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"types": ["svelte", "node"],
|
|
||||||
// "importsNotUsedAsValues": "error",
|
// "importsNotUsedAsValues": "error",
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
"alwaysStrict": true,
|
"alwaysStrict": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user