@vrtmrz/livesync-commonlib 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -33,6 +33,7 @@ export declare class LiveSyncCouchDBReplicator extends LiveSyncAbstractReplicato
|
|
|
33
33
|
sendChunks(setting: RemoteDBSettings, remoteDB: PouchDB.Database<EntryDoc> | undefined, showResult: boolean, fromSeq?: number | string): Promise<boolean>;
|
|
34
34
|
openOneShotReplication(setting: RemoteDBSettings, showResult: boolean, retrying: boolean, syncMode: "sync" | "pullOnly" | "pushOnly", ignoreCleanLock?: boolean): Promise<boolean>;
|
|
35
35
|
private closeRemoteDatabase;
|
|
36
|
+
private withRemoteDatabase;
|
|
36
37
|
replicateAllToServer(setting: RemoteDBSettings, showingNotice?: boolean): Promise<boolean>;
|
|
37
38
|
replicateAllFromServer(setting: RemoteDBSettings, showingNotice?: boolean): Promise<boolean>;
|
|
38
39
|
checkReplicationConnectivity(setting: RemoteDBSettings, keepAlive: boolean, skipCheck: boolean, showResult: boolean, ignoreCleanLock?: boolean): Promise<false | {
|
|
@@ -379,9 +379,12 @@ class LiveSyncCouchDBReplicator extends LiveSyncAbstractReplicator {
|
|
|
379
379
|
);
|
|
380
380
|
return false;
|
|
381
381
|
}
|
|
382
|
-
|
|
382
|
+
return await this.withRemoteDatabase(d.db, async (db) => this.sendChunks(setting, db, showResult, fromSeq));
|
|
383
|
+
}
|
|
384
|
+
const connectivity = await this.checkReplicationConnectivity(setting, false, false, false, false);
|
|
385
|
+
if (connectivity !== false) {
|
|
386
|
+
await this.closeRemoteDatabase(connectivity.db);
|
|
383
387
|
}
|
|
384
|
-
await this.checkReplicationConnectivity(setting, false, false, false, false);
|
|
385
388
|
Logger(`Bulk sending chunks to remote database...`, showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO, "fetch");
|
|
386
389
|
const remoteMilestone = await remoteDB.get(MILESTONE_DOCID);
|
|
387
390
|
const remoteID = remoteMilestone?.created ?? 0;
|
|
@@ -628,6 +631,13 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
628
631
|
Logger(ex, LOG_LEVEL_VERBOSE, "sync");
|
|
629
632
|
}
|
|
630
633
|
}
|
|
634
|
+
async withRemoteDatabase(db, task) {
|
|
635
|
+
try {
|
|
636
|
+
return await task(db);
|
|
637
|
+
} finally {
|
|
638
|
+
await this.closeRemoteDatabase(db);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
631
641
|
replicateAllToServer(setting, showingNotice) {
|
|
632
642
|
return this.openOneShotReplication(setting, showingNotice ?? false, false, "pushOnly");
|
|
633
643
|
}
|
|
@@ -763,58 +773,62 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
763
773
|
Logger(this.translate("liveSyncReplicator.checkingLastSyncPoint"), LOG_LEVEL_NOTICE, "sync");
|
|
764
774
|
}
|
|
765
775
|
const { db, syncOption } = ret;
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
const syncHandler = localDB.sync(db, {
|
|
777
|
-
...syncOption
|
|
778
|
-
});
|
|
779
|
-
const syncMode = "sync";
|
|
780
|
-
const syncResult = await this.processSync(
|
|
781
|
-
syncHandler,
|
|
782
|
-
showResult,
|
|
783
|
-
docSentOnStart,
|
|
784
|
-
docArrivedOnStart,
|
|
785
|
-
syncMode,
|
|
786
|
-
retrying
|
|
787
|
-
);
|
|
788
|
-
if (syncResult == "DONE") {
|
|
789
|
-
return true;
|
|
790
|
-
}
|
|
791
|
-
if (syncResult == "FAILED") {
|
|
792
|
-
return false;
|
|
793
|
-
}
|
|
794
|
-
if (syncResult == "NEED_RESURRECT") {
|
|
776
|
+
try {
|
|
777
|
+
this.syncStatus = "STARTED";
|
|
778
|
+
this.maxPullSeq = Number(`${ret.info.update_seq}`.split("-")[0]);
|
|
779
|
+
this.maxPushSeq = Number(`${(await localDB.info()).update_seq}`.split("-")[0]);
|
|
780
|
+
this.updateInfo();
|
|
781
|
+
const docArrivedOnStart = this.docArrived;
|
|
782
|
+
const docSentOnStart = this.docSent;
|
|
783
|
+
if (!retrying) {
|
|
784
|
+
this.originalSetting = setting;
|
|
785
|
+
}
|
|
795
786
|
this.terminateSync();
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
const
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
787
|
+
const syncHandler = localDB.sync(db, {
|
|
788
|
+
...syncOption
|
|
789
|
+
});
|
|
790
|
+
const syncMode = "sync";
|
|
791
|
+
const syncResult = await this.processSync(
|
|
792
|
+
syncHandler,
|
|
793
|
+
showResult,
|
|
794
|
+
docSentOnStart,
|
|
795
|
+
docArrivedOnStart,
|
|
796
|
+
syncMode,
|
|
797
|
+
retrying
|
|
798
|
+
);
|
|
799
|
+
if (syncResult == "DONE") {
|
|
800
|
+
return true;
|
|
801
|
+
}
|
|
802
|
+
if (syncResult == "FAILED") {
|
|
807
803
|
return false;
|
|
808
|
-
} else {
|
|
809
|
-
Logger(
|
|
810
|
-
this.translate("liveSyncReplicator.retryLowerBatchSize", {
|
|
811
|
-
batch_size: tempSetting.batch_size.toString(),
|
|
812
|
-
batches_limit: tempSetting.batches_limit.toString()
|
|
813
|
-
}),
|
|
814
|
-
showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
|
|
815
|
-
);
|
|
816
|
-
return async () => await this.openContinuousReplication(tempSetting, showResult, true);
|
|
817
804
|
}
|
|
805
|
+
if (syncResult == "NEED_RESURRECT") {
|
|
806
|
+
this.terminateSync();
|
|
807
|
+
return async () => await this.openContinuousReplication(this.originalSetting, showResult, false);
|
|
808
|
+
}
|
|
809
|
+
if (syncResult == "NEED_RETRY") {
|
|
810
|
+
const tempSetting = JSON.parse(JSON.stringify(setting));
|
|
811
|
+
tempSetting.batch_size = Math.ceil(tempSetting.batch_size / 2) + 2;
|
|
812
|
+
tempSetting.batches_limit = Math.ceil(tempSetting.batches_limit / 2) + 2;
|
|
813
|
+
if (tempSetting.batch_size <= 5 && tempSetting.batches_limit <= 5) {
|
|
814
|
+
Logger(
|
|
815
|
+
this.translate("liveSyncReplicator.cantReplicateLowerValue"),
|
|
816
|
+
showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
|
|
817
|
+
);
|
|
818
|
+
return false;
|
|
819
|
+
} else {
|
|
820
|
+
Logger(
|
|
821
|
+
this.translate("liveSyncReplicator.retryLowerBatchSize", {
|
|
822
|
+
batch_size: tempSetting.batch_size.toString(),
|
|
823
|
+
batches_limit: tempSetting.batches_limit.toString()
|
|
824
|
+
}),
|
|
825
|
+
showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
|
|
826
|
+
);
|
|
827
|
+
return async () => await this.openContinuousReplication(tempSetting, showResult, true);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
} finally {
|
|
831
|
+
await this.closeRemoteDatabase(db);
|
|
818
832
|
}
|
|
819
833
|
}
|
|
820
834
|
return false;
|
|
@@ -839,12 +853,16 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
839
853
|
const con = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
|
|
840
854
|
if (typeof con == "string") return;
|
|
841
855
|
try {
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
856
|
+
try {
|
|
857
|
+
await con.db.destroy();
|
|
858
|
+
Logger(this.translate("liveSyncReplicator.remoteDbDestroyed"), LOG_LEVEL_NOTICE);
|
|
859
|
+
await this.tryCreateRemoteDatabase(setting);
|
|
860
|
+
} catch (ex) {
|
|
861
|
+
Logger(this.translate("liveSyncReplicator.remoteDbDestroyError"), LOG_LEVEL_NOTICE);
|
|
862
|
+
Logger(ex, LOG_LEVEL_NOTICE);
|
|
863
|
+
}
|
|
864
|
+
} finally {
|
|
865
|
+
await this.closeRemoteDatabase(con.db);
|
|
848
866
|
}
|
|
849
867
|
clearHandlers();
|
|
850
868
|
await this.ensurePBKDF2Salt(setting, true, false);
|
|
@@ -853,6 +871,7 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
853
871
|
this.closeReplication();
|
|
854
872
|
const con2 = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
|
|
855
873
|
if (typeof con2 === "string") return;
|
|
874
|
+
await this.closeRemoteDatabase(con2.db);
|
|
856
875
|
clearHandlers();
|
|
857
876
|
await this.ensurePBKDF2Salt(setting, true, false);
|
|
858
877
|
Logger(this.translate("liveSyncReplicator.remoteDbCreatedOrConnected"), LOG_LEVEL_NOTICE);
|
|
@@ -864,35 +883,37 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
864
883
|
Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
|
|
865
884
|
return;
|
|
866
885
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
886
|
+
await this.withRemoteDatabase(dbRet.db, async (db) => {
|
|
887
|
+
if (!await checkRemoteVersion(db, this.migrate.bind(this), VER)) {
|
|
888
|
+
Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
const defInitPoint = {
|
|
892
|
+
_id: MILESTONE_DOCID,
|
|
893
|
+
type: "milestoneinfo",
|
|
894
|
+
created: Date.now(),
|
|
895
|
+
locked,
|
|
896
|
+
cleaned: lockByClean,
|
|
897
|
+
accepted_nodes: [this.nodeid],
|
|
898
|
+
node_chunk_info: { [this.nodeid]: currentVersionRange },
|
|
899
|
+
node_info: {},
|
|
900
|
+
tweak_values: {}
|
|
901
|
+
};
|
|
902
|
+
const remoteMilestone = {
|
|
903
|
+
...defInitPoint,
|
|
904
|
+
...await resolveWithIgnoreKnownError(db.get(MILESTONE_DOCID), defInitPoint)
|
|
905
|
+
};
|
|
906
|
+
remoteMilestone.node_chunk_info = { ...defInitPoint.node_chunk_info, ...remoteMilestone.node_chunk_info };
|
|
907
|
+
remoteMilestone.accepted_nodes = [this.nodeid];
|
|
908
|
+
remoteMilestone.locked = locked;
|
|
909
|
+
remoteMilestone.cleaned = remoteMilestone.cleaned || lockByClean;
|
|
910
|
+
if (locked) {
|
|
911
|
+
Logger(this.translate("liveSyncReplicator.lockRemoteDb"), LOG_LEVEL_NOTICE);
|
|
912
|
+
} else {
|
|
913
|
+
Logger(this.translate("liveSyncReplicator.unlockRemoteDb"), LOG_LEVEL_NOTICE);
|
|
914
|
+
}
|
|
915
|
+
await db.put(remoteMilestone);
|
|
916
|
+
});
|
|
896
917
|
}
|
|
897
918
|
async markRemoteResolved(setting) {
|
|
898
919
|
const uri = setting.couchDB_URI.replace(/\/+$/, "") + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
|
|
@@ -901,33 +922,35 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
901
922
|
Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
|
|
902
923
|
return;
|
|
903
924
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
925
|
+
await this.withRemoteDatabase(dbRet.db, async (db) => {
|
|
926
|
+
if (!await checkRemoteVersion(db, this.migrate.bind(this), VER)) {
|
|
927
|
+
Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
const defInitPoint = {
|
|
931
|
+
_id: MILESTONE_DOCID,
|
|
932
|
+
type: "milestoneinfo",
|
|
933
|
+
created: Date.now(),
|
|
934
|
+
locked: false,
|
|
935
|
+
accepted_nodes: [this.nodeid],
|
|
936
|
+
node_info: {},
|
|
937
|
+
node_chunk_info: { [this.nodeid]: currentVersionRange },
|
|
938
|
+
tweak_values: {}
|
|
939
|
+
};
|
|
940
|
+
const remoteMilestone = {
|
|
941
|
+
...defInitPoint,
|
|
942
|
+
...await resolveWithIgnoreKnownError(db.get(MILESTONE_DOCID), defInitPoint)
|
|
943
|
+
};
|
|
944
|
+
remoteMilestone.node_chunk_info = { ...defInitPoint.node_chunk_info, ...remoteMilestone.node_chunk_info };
|
|
945
|
+
remoteMilestone.accepted_nodes = Array.from(/* @__PURE__ */ new Set([...remoteMilestone.accepted_nodes, this.nodeid]));
|
|
946
|
+
Logger(this.translate("liveSyncReplicator.markDeviceResolved"), LOG_LEVEL_NOTICE);
|
|
947
|
+
const result = await db.put(remoteMilestone);
|
|
948
|
+
if (result.ok) {
|
|
949
|
+
Logger(this.translate("liveSyncReplicator.remoteDbMarkedResolved"), LOG_LEVEL_VERBOSE);
|
|
950
|
+
} else {
|
|
951
|
+
Logger(this.translate("liveSyncReplicator.couldNotMarkResolveRemoteDb"), LOG_LEVEL_NOTICE);
|
|
952
|
+
}
|
|
953
|
+
});
|
|
931
954
|
}
|
|
932
955
|
connectRemoteCouchDBWithSetting(settings, isMobile, performSetup = false, skipInfo = false) {
|
|
933
956
|
if (settings.encrypt && settings.passphrase == "" && !settings.permitEmptyPassphrase) {
|
|
@@ -976,14 +999,19 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
976
999
|
* @throws {Error} Other errors that may occur during the fetch operation.
|
|
977
1000
|
*/
|
|
978
1001
|
async fetchRemoteDocument(settings, id, db) {
|
|
1002
|
+
const ownsConnection = db === void 0;
|
|
1003
|
+
const connDB = db ?? await this._ensureConnection(settings);
|
|
979
1004
|
try {
|
|
980
|
-
const connDB = db ?? await this._ensureConnection(settings);
|
|
981
1005
|
return await connDB.get(id);
|
|
982
1006
|
} catch (ex) {
|
|
983
1007
|
if (ex && ex.status == 404) {
|
|
984
1008
|
return false;
|
|
985
1009
|
}
|
|
986
1010
|
throw ex;
|
|
1011
|
+
} finally {
|
|
1012
|
+
if (ownsConnection) {
|
|
1013
|
+
await this.closeRemoteDatabase(connDB);
|
|
1014
|
+
}
|
|
987
1015
|
}
|
|
988
1016
|
}
|
|
989
1017
|
/**
|
|
@@ -995,8 +1023,15 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
995
1023
|
* @throws {Error} If the document could not be put.
|
|
996
1024
|
*/
|
|
997
1025
|
async putRemoteDocument(settings, doc, db) {
|
|
1026
|
+
const ownsConnection = db === void 0;
|
|
998
1027
|
const connDB = db ?? await this._ensureConnection(settings, true);
|
|
999
|
-
|
|
1028
|
+
try {
|
|
1029
|
+
return await connDB.put(doc);
|
|
1030
|
+
} finally {
|
|
1031
|
+
if (ownsConnection) {
|
|
1032
|
+
await this.closeRemoteDatabase(connDB);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1000
1035
|
}
|
|
1001
1036
|
async fetchRemoteChunks(missingChunks, showResult) {
|
|
1002
1037
|
const ret = await this.connectRemoteCouchDBWithSetting(this.currentSettings, this.isMobile(), false, true);
|
|
@@ -1008,19 +1043,23 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
1008
1043
|
);
|
|
1009
1044
|
return false;
|
|
1010
1045
|
}
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1046
|
+
return await this.withRemoteDatabase(ret.db, async (db) => {
|
|
1047
|
+
const remoteChunks = await db.allDocs({ keys: missingChunks, include_docs: true });
|
|
1048
|
+
const errorRows = remoteChunks.rows.filter((e) => "error" in e);
|
|
1049
|
+
if (errorRows.length > 0) {
|
|
1050
|
+
Logger(
|
|
1051
|
+
`Some requested chunks were not found in the remote database.`,
|
|
1052
|
+
showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO,
|
|
1053
|
+
"fetch"
|
|
1054
|
+
);
|
|
1055
|
+
Logger(`Requested chunks: ${missingChunks.join(",")}`, LOG_LEVEL_VERBOSE);
|
|
1056
|
+
Logger(
|
|
1057
|
+
`Error chunks: ${errorRows.map((e) => e.key).join(",")}`,
|
|
1058
|
+
LOG_LEVEL_VERBOSE
|
|
1059
|
+
);
|
|
1060
|
+
}
|
|
1061
|
+
return remoteChunks.rows.filter((e) => !("error" in e)).map((e) => e.doc).filter((e) => e !== void 0);
|
|
1062
|
+
});
|
|
1024
1063
|
}
|
|
1025
1064
|
async tryConnectRemote(setting, showResult = true) {
|
|
1026
1065
|
const db = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
|
|
@@ -1035,8 +1074,10 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
1035
1074
|
);
|
|
1036
1075
|
return false;
|
|
1037
1076
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1077
|
+
return await this.withRemoteDatabase(db.db, async () => {
|
|
1078
|
+
Logger(`Connected to ${db.info.db_name} successfully`, LOG_LEVEL_NOTICE);
|
|
1079
|
+
return true;
|
|
1080
|
+
});
|
|
1040
1081
|
}
|
|
1041
1082
|
async resetRemoteTweakSettings(setting) {
|
|
1042
1083
|
const uri = setting.couchDB_URI.replace(/\/+$/, "") + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
|
|
@@ -1045,19 +1086,21 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
1045
1086
|
Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
|
|
1046
1087
|
return;
|
|
1047
1088
|
}
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1089
|
+
await this.withRemoteDatabase(dbRet.db, async (db) => {
|
|
1090
|
+
if (!await checkRemoteVersion(db, this.migrate.bind(this), VER)) {
|
|
1091
|
+
Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
try {
|
|
1095
|
+
const remoteMilestone = await db.get(MILESTONE_DOCID);
|
|
1096
|
+
remoteMilestone.tweak_values = {};
|
|
1097
|
+
await db.put(remoteMilestone);
|
|
1098
|
+
Logger(`tweak values on the remote database have been cleared`, LOG_LEVEL_VERBOSE);
|
|
1099
|
+
} catch (ex) {
|
|
1100
|
+
Logger(`Could not retrieve remote milestone`, LOG_LEVEL_NOTICE);
|
|
1101
|
+
throw ex;
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1061
1104
|
}
|
|
1062
1105
|
async setPreferredRemoteTweakSettings(setting) {
|
|
1063
1106
|
const uri = setting.couchDB_URI.replace(/\/+$/, "") + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
|
|
@@ -1066,19 +1109,21 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
1066
1109
|
Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
|
|
1067
1110
|
return;
|
|
1068
1111
|
}
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1112
|
+
await this.withRemoteDatabase(dbRet.db, async (db) => {
|
|
1113
|
+
if (!await checkRemoteVersion(db, this.migrate.bind(this), VER)) {
|
|
1114
|
+
Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
try {
|
|
1118
|
+
const remoteMilestone = await db.get(MILESTONE_DOCID);
|
|
1119
|
+
remoteMilestone.tweak_values[DEVICE_ID_PREFERRED] = extractObject(TweakValuesTemplate, { ...setting });
|
|
1120
|
+
await db.put(remoteMilestone);
|
|
1121
|
+
Logger(`Preferred tweak values has been registered`, LOG_LEVEL_VERBOSE);
|
|
1122
|
+
} catch (ex) {
|
|
1123
|
+
Logger(`Could not retrieve remote milestone`, LOG_LEVEL_NOTICE);
|
|
1124
|
+
throw ex;
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
1082
1127
|
}
|
|
1083
1128
|
async getRemotePreferredTweakValues(setting) {
|
|
1084
1129
|
const uri = setting.couchDB_URI.replace(/\/+$/, "") + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
|
|
@@ -1100,56 +1145,58 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
1100
1145
|
error: new Error(dbRet)
|
|
1101
1146
|
};
|
|
1102
1147
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1148
|
+
return await this.withRemoteDatabase(dbRet.db, async (db) => {
|
|
1149
|
+
try {
|
|
1150
|
+
if (!await checkRemoteVersion(db, this.migrate.bind(this), VER)) {
|
|
1151
|
+
const error = new Error("The remote database version is not compatible");
|
|
1152
|
+
Logger(this.translate("liveSyncReplicator.remoteDbCorrupted"), LOG_LEVEL_NOTICE);
|
|
1153
|
+
return {
|
|
1154
|
+
status: RemotePreferredTweakStatuses.UNAVAILABLE,
|
|
1155
|
+
error
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
} catch (ex) {
|
|
1159
|
+
Logger(`Could not check the remote database version`, LOG_LEVEL_NOTICE);
|
|
1160
|
+
Logger(ex, LOG_LEVEL_VERBOSE);
|
|
1107
1161
|
return {
|
|
1108
1162
|
status: RemotePreferredTweakStatuses.UNAVAILABLE,
|
|
1109
|
-
error
|
|
1163
|
+
error: ex
|
|
1110
1164
|
};
|
|
1111
1165
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
const preferred = remoteMilestone.tweak_values?.[DEVICE_ID_PREFERRED];
|
|
1129
|
-
if (!preferred) {
|
|
1166
|
+
try {
|
|
1167
|
+
const remoteMilestone = await db.get(MILESTONE_DOCID);
|
|
1168
|
+
if (!remoteMilestone) {
|
|
1169
|
+
return {
|
|
1170
|
+
status: RemotePreferredTweakStatuses.NOT_CONFIGURED,
|
|
1171
|
+
reason: RemotePreferredTweakNotConfiguredReasons.MILESTONE_MISSING
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
const preferred = remoteMilestone.tweak_values?.[DEVICE_ID_PREFERRED];
|
|
1175
|
+
if (!preferred) {
|
|
1176
|
+
return {
|
|
1177
|
+
status: RemotePreferredTweakStatuses.NOT_CONFIGURED,
|
|
1178
|
+
reason: RemotePreferredTweakNotConfiguredReasons.PREFERRED_VALUES_MISSING
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1130
1181
|
return {
|
|
1131
|
-
status: RemotePreferredTweakStatuses.
|
|
1132
|
-
|
|
1182
|
+
status: RemotePreferredTweakStatuses.AVAILABLE,
|
|
1183
|
+
values: preferred
|
|
1133
1184
|
};
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1185
|
+
} catch (ex) {
|
|
1186
|
+
if (isErrorOfMissingDoc(ex)) {
|
|
1187
|
+
return {
|
|
1188
|
+
status: RemotePreferredTweakStatuses.NOT_CONFIGURED,
|
|
1189
|
+
reason: RemotePreferredTweakNotConfiguredReasons.MILESTONE_MISSING
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
Logger(`Could not retrieve remote milestone`, LOG_LEVEL_NOTICE);
|
|
1193
|
+
Logger(ex, LOG_LEVEL_VERBOSE);
|
|
1141
1194
|
return {
|
|
1142
|
-
status: RemotePreferredTweakStatuses.
|
|
1143
|
-
|
|
1195
|
+
status: RemotePreferredTweakStatuses.UNAVAILABLE,
|
|
1196
|
+
error: ex
|
|
1144
1197
|
};
|
|
1145
1198
|
}
|
|
1146
|
-
|
|
1147
|
-
Logger(ex, LOG_LEVEL_VERBOSE);
|
|
1148
|
-
return {
|
|
1149
|
-
status: RemotePreferredTweakStatuses.UNAVAILABLE,
|
|
1150
|
-
error: ex
|
|
1151
|
-
};
|
|
1152
|
-
}
|
|
1199
|
+
});
|
|
1153
1200
|
}
|
|
1154
1201
|
async compactRemote(setting) {
|
|
1155
1202
|
const uri = setting.couchDB_URI.replace(/\/+$/, "") + (setting.couchDB_DBNAME == "" ? "" : "/" + setting.couchDB_DBNAME);
|
|
@@ -1158,8 +1205,7 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
1158
1205
|
Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
|
|
1159
1206
|
return false;
|
|
1160
1207
|
}
|
|
1161
|
-
|
|
1162
|
-
return ret.ok;
|
|
1208
|
+
return await this.withRemoteDatabase(dbRet.db, async (db) => (await db.compact({ interval: 1e3 })).ok);
|
|
1163
1209
|
}
|
|
1164
1210
|
async getRemoteStatus(setting) {
|
|
1165
1211
|
const dbRet = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
|
|
@@ -1168,11 +1214,13 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
1168
1214
|
Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
|
|
1169
1215
|
return false;
|
|
1170
1216
|
}
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1217
|
+
return await this.withRemoteDatabase(dbRet.db, async (db) => {
|
|
1218
|
+
const info = await db.info();
|
|
1219
|
+
return {
|
|
1220
|
+
...info,
|
|
1221
|
+
estimatedSize: info?.sizes?.file || 0
|
|
1222
|
+
};
|
|
1223
|
+
});
|
|
1176
1224
|
}
|
|
1177
1225
|
async countCompromisedChunks(setting = this.currentSettings) {
|
|
1178
1226
|
const dbRet = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
|
|
@@ -1181,8 +1229,7 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
1181
1229
|
Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
|
|
1182
1230
|
return false;
|
|
1183
1231
|
}
|
|
1184
|
-
|
|
1185
|
-
return compromised;
|
|
1232
|
+
return await this.withRemoteDatabase(dbRet.db, countCompromisedChunks);
|
|
1186
1233
|
}
|
|
1187
1234
|
async getConnectedDeviceList(setting = this.currentSettings) {
|
|
1188
1235
|
const dbRet = await this.connectRemoteCouchDBWithSetting(setting, this.isMobile(), true);
|
|
@@ -1191,14 +1238,16 @@ ${sendingDocs}/(${sentDocsCount} done)`,
|
|
|
1191
1238
|
Logger(this.translate("liveSyncReplicator.couldNotConnectToURI", { uri, dbRet }), LOG_LEVEL_NOTICE);
|
|
1192
1239
|
return false;
|
|
1193
1240
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1241
|
+
return await this.withRemoteDatabase(dbRet.db, async (db) => {
|
|
1242
|
+
const milestoneDoc = await db.get(MILESTONE_DOCID);
|
|
1243
|
+
if (!milestoneDoc) {
|
|
1244
|
+
Logger("Could not retrieve remote milestone", LOG_LEVEL_NOTICE);
|
|
1245
|
+
return false;
|
|
1246
|
+
}
|
|
1247
|
+
const nodeInfo = milestoneDoc.node_info;
|
|
1248
|
+
const acceptedNodes = milestoneDoc.accepted_nodes || [];
|
|
1249
|
+
return { node_info: nodeInfo, accepted_nodes: acceptedNodes };
|
|
1250
|
+
});
|
|
1202
1251
|
}
|
|
1203
1252
|
}
|
|
1204
1253
|
export {
|
|
@@ -203,6 +203,12 @@ class RemoteService extends ServiceBase {
|
|
|
203
203
|
const exMsg = ex instanceof Error ? ex : LiveSyncError.fromError(ex);
|
|
204
204
|
const msg = `${exMsg.name}:${exMsg.message}`;
|
|
205
205
|
this._log(ex, LOG_LEVEL_VERBOSE);
|
|
206
|
+
try {
|
|
207
|
+
await db.close();
|
|
208
|
+
} catch (closeError) {
|
|
209
|
+
this._log("Failed to close remote database after connection failure.", LOG_LEVEL_INFO);
|
|
210
|
+
this._log(closeError, LOG_LEVEL_VERBOSE);
|
|
211
|
+
}
|
|
206
212
|
return msg;
|
|
207
213
|
}
|
|
208
214
|
}
|
package/package.json
CHANGED