Compare commits

...

2 Commits

Author SHA1 Message Date
vorotamoroz
133f5a7109 bump 2024-04-30 11:49:16 +01:00
vorotamoroz
daa3feebf1 Fixed:
- Journal Sync will not hang up during big replication, especially the initial one.
- All changes which have been replicated while rebuilding will not be postponed (Previous behaviour).
Improved:
- Now Journal Sync works efficiently in download and parse, or pack and upload.
- Less server storage and faster packing/unpacking usage by the new chunk format.
2024-04-30 11:48:27 +01:00
9 changed files with 50 additions and 28 deletions

View File

@@ -1,7 +1,7 @@
{ {
"id": "obsidian-livesync", "id": "obsidian-livesync",
"name": "Self-hosted LiveSync", "name": "Self-hosted LiveSync",
"version": "0.23.1", "version": "0.23.2",
"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
View File

@@ -1,12 +1,12 @@
{ {
"name": "obsidian-livesync", "name": "obsidian-livesync",
"version": "0.23.1", "version": "0.23.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "obsidian-livesync", "name": "obsidian-livesync",
"version": "0.23.1", "version": "0.23.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "^3.556.0", "@aws-sdk/client-s3": "^3.556.0",

View File

@@ -1,6 +1,6 @@
{ {
"name": "obsidian-livesync", "name": "obsidian-livesync",
"version": "0.23.1", "version": "0.23.2",
"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",

View File

@@ -1,4 +1,4 @@
import { type EntryDoc, type ObsidianLiveSyncSettings, DEFAULT_SETTINGS, LOG_LEVEL_NOTICE, REMOTE_COUCHDB } from "./lib/src/types"; import { type EntryDoc, type ObsidianLiveSyncSettings, DEFAULT_SETTINGS, LOG_LEVEL_NOTICE, REMOTE_COUCHDB, REMOTE_MINIO } from "./lib/src/types";
import { configURIBase } from "./types"; import { configURIBase } from "./types";
import { Logger } from "./lib/src/logger"; import { Logger } from "./lib/src/logger";
import { PouchDB } from "./lib/src/pouchdb-browser.js"; import { PouchDB } from "./lib/src/pouchdb-browser.js";
@@ -312,7 +312,7 @@ Of course, we are able to disable these features.`
} }
async suspendReflectingDatabase() { async suspendReflectingDatabase() {
if (this.plugin.settings.doNotSuspendOnFetching) return; if (this.plugin.settings.doNotSuspendOnFetching) return;
// if (this.plugin.settings.remoteType == REMOTE_MINIO) return; if (this.plugin.settings.remoteType == REMOTE_MINIO) return;
Logger(`Suspending reflection: Database and storage changes will not be reflected in each other until completely finished the fetching.`, LOG_LEVEL_NOTICE); Logger(`Suspending reflection: Database and storage changes will not be reflected in each other until completely finished the fetching.`, LOG_LEVEL_NOTICE);
this.plugin.settings.suspendParseReplicationResult = true; this.plugin.settings.suspendParseReplicationResult = true;
this.plugin.settings.suspendFileWatching = true; this.plugin.settings.suspendFileWatching = true;
@@ -320,7 +320,7 @@ Of course, we are able to disable these features.`
} }
async resumeReflectingDatabase() { async resumeReflectingDatabase() {
if (this.plugin.settings.doNotSuspendOnFetching) return; if (this.plugin.settings.doNotSuspendOnFetching) return;
// if (this.plugin.settings.remoteType == REMOTE_MINIO) return; if (this.plugin.settings.remoteType == REMOTE_MINIO) return;
Logger(`Database and storage reflection has been resumed!`, LOG_LEVEL_NOTICE); Logger(`Database and storage reflection has been resumed!`, LOG_LEVEL_NOTICE);
this.plugin.settings.suspendParseReplicationResult = false; this.plugin.settings.suspendParseReplicationResult = false;
this.plugin.settings.suspendFileWatching = false; this.plugin.settings.suspendFileWatching = false;

View File

@@ -1,8 +1,8 @@
import { deleteDB, type IDBPDatabase, openDB } from "idb"; import { deleteDB, type IDBPDatabase, openDB } from "idb";
export interface KeyValueDatabase { export interface KeyValueDatabase {
get<T>(key: string): Promise<T>; get<T>(key: IDBValidKey): Promise<T>;
set<T>(key: string, value: T): Promise<IDBValidKey>; set<T>(key: IDBValidKey, value: T): Promise<IDBValidKey>;
del(key: string): Promise<void>; del(key: IDBValidKey): Promise<void>;
clear(): Promise<void>; clear(): Promise<void>;
keys(query?: IDBValidKey | IDBKeyRange, count?: number): Promise<IDBValidKey[]>; keys(query?: IDBValidKey | IDBKeyRange, count?: number): Promise<IDBValidKey[]>;
close(): void; close(): void;
@@ -23,20 +23,20 @@ export const OpenKeyValueDatabase = async (dbKey: string): Promise<KeyValueDatab
const db = await dbPromise; const db = await dbPromise;
databaseCache[dbKey] = db; databaseCache[dbKey] = db;
return { return {
get<T>(key: string): Promise<T> { async get<T>(key: IDBValidKey): Promise<T> {
return db.get(storeKey, key); return await db.get(storeKey, key);
}, },
set<T>(key: string, value: T) { async set<T>(key: IDBValidKey, value: T) {
return db.put(storeKey, value, key); return await db.put(storeKey, value, key);
}, },
del(key: string) { async del(key: IDBValidKey) {
return db.delete(storeKey, key); return await db.delete(storeKey, key);
}, },
clear() { async clear() {
return db.clear(storeKey); return await db.clear(storeKey);
}, },
keys(query?: IDBValidKey | IDBKeyRange, count?: number) { async keys(query?: IDBValidKey | IDBKeyRange, count?: number) {
return db.getAllKeys(storeKey, query, count); return await db.getAllKeys(storeKey, query, count);
}, },
close() { close() {
delete databaseCache[dbKey]; delete databaseCache[dbKey];

View File

@@ -2331,7 +2331,7 @@ ${stringifyYaml(pluginConfig)}`;
.setWarning() .setWarning()
.setDisabled(false) .setDisabled(false)
.onClick(async () => { .onClick(async () => {
await this.plugin.getMinioJournalSyncClient().updateCheckPointInfo((info) => ({ ...info, receivedFiles: [], knownIDs: [] })); await this.plugin.getMinioJournalSyncClient().updateCheckPointInfo((info) => ({ ...info, receivedFiles: new Set(), knownIDs: new Set() }));
Logger(`Journal received history has been cleared.`, LOG_LEVEL_NOTICE); Logger(`Journal received history has been cleared.`, LOG_LEVEL_NOTICE);
}) })
) )
@@ -2344,7 +2344,7 @@ ${stringifyYaml(pluginConfig)}`;
.setWarning() .setWarning()
.setDisabled(false) .setDisabled(false)
.onClick(async () => { .onClick(async () => {
await this.plugin.getMinioJournalSyncClient().updateCheckPointInfo((info) => ({ ...info, lastLocalSeq: 0, sentIDs: [], sentFiles: [] })); await this.plugin.getMinioJournalSyncClient().updateCheckPointInfo((info) => ({ ...info, lastLocalSeq: 0, sentIDs: new Set(), sentFiles: new Set() }));
Logger(`Journal sent history has been cleared.`, LOG_LEVEL_NOTICE); Logger(`Journal sent history has been cleared.`, LOG_LEVEL_NOTICE);
}) })
) )
@@ -2357,10 +2357,24 @@ ${stringifyYaml(pluginConfig)}`;
.setWarning() .setWarning()
.setDisabled(false) .setDisabled(false)
.onClick(async () => { .onClick(async () => {
await this.plugin.getMinioJournalSyncClient().updateCheckPointInfo((info) => ({ ...info, receivedFiles: [], knownIDs: [], lastLocalSeq: 0, sentIDs: [], sentFiles: [] })); await this.plugin.getMinioJournalSyncClient().resetCheckpointInfo();
Logger(`Journal exchange history has been cleared.`, LOG_LEVEL_NOTICE); Logger(`Journal exchange history has been cleared.`, LOG_LEVEL_NOTICE);
}) })
) )
new Setting(containerMaintenanceEl)
.setName("Purge all journal counter")
.setDesc("Purge all sending and downloading cache.")
.addButton((button) =>
button
.setButtonText("Reset all")
.setWarning()
.setDisabled(false)
.onClick(async () => {
await this.plugin.getMinioJournalSyncClient().resetAllCaches();
Logger(`Journal sending and downloading cache has been cleared.`, LOG_LEVEL_NOTICE);
})
)
new Setting(containerMaintenanceEl) new Setting(containerMaintenanceEl)
.setName("Make empty the bucket") .setName("Make empty the bucket")
.setDesc("Delete all data on the remote.") .setDesc("Delete all data on the remote.")
@@ -2370,7 +2384,7 @@ ${stringifyYaml(pluginConfig)}`;
.setWarning() .setWarning()
.setDisabled(false) .setDisabled(false)
.onClick(async () => { .onClick(async () => {
await this.plugin.getMinioJournalSyncClient().updateCheckPointInfo((info) => ({ ...info, receivedFiles: [], knownIDs: [], lastLocalSeq: 0, sentIDs: [], sentFiles: [] })); await this.plugin.getMinioJournalSyncClient().updateCheckPointInfo((info) => ({ ...info, receivedFiles: new Set(), knownIDs: new Set(), lastLocalSeq: 0, sentIDs: new Set(), sentFiles: new Set() }));
await this.plugin.resetRemoteBucket(); await this.plugin.resetRemoteBucket();
Logger(`the bucket has been cleared.`, LOG_LEVEL_NOTICE); Logger(`the bucket has been cleared.`, LOG_LEVEL_NOTICE);
}) })

Submodule src/lib updated: 0d1ed24e31...da470ddc41

View File

@@ -4,7 +4,7 @@ import { type Diff, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch, stri
import { Notice, Plugin, TFile, addIcon, TFolder, normalizePath, TAbstractFile, Editor, MarkdownView, type RequestUrlParam, type RequestUrlResponse, requestUrl, type MarkdownFileInfo } from "./deps"; import { Notice, Plugin, TFile, addIcon, TFolder, normalizePath, TAbstractFile, Editor, MarkdownView, type RequestUrlParam, type RequestUrlResponse, requestUrl, type MarkdownFileInfo } from "./deps";
import { type EntryDoc, type LoadedEntry, type ObsidianLiveSyncSettings, type diff_check_result, type diff_result_leaf, type EntryBody, LOG_LEVEL, VER, DEFAULT_SETTINGS, type diff_result, FLAGMD_REDFLAG, SYNCINFO_ID, SALT_OF_PASSPHRASE, type ConfigPassphraseStore, type CouchDBConnection, FLAGMD_REDFLAG2, FLAGMD_REDFLAG3, PREFIXMD_LOGFILE, type DatabaseConnectingStatus, type EntryHasPath, type DocumentID, type FilePathWithPrefix, type FilePath, type AnyEntry, LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_URGENT, LOG_LEVEL_VERBOSE, type SavingEntry, MISSING_OR_ERROR, NOT_CONFLICTED, AUTO_MERGED, CANCELLED, LEAVE_TO_SUBSEQUENT, FLAGMD_REDFLAG2_HR, FLAGMD_REDFLAG3_HR, REMOTE_MINIO, REMOTE_COUCHDB, type BucketSyncSetting, } from "./lib/src/types"; import { type EntryDoc, type LoadedEntry, type ObsidianLiveSyncSettings, type diff_check_result, type diff_result_leaf, type EntryBody, LOG_LEVEL, VER, DEFAULT_SETTINGS, type diff_result, FLAGMD_REDFLAG, SYNCINFO_ID, SALT_OF_PASSPHRASE, type ConfigPassphraseStore, type CouchDBConnection, FLAGMD_REDFLAG2, FLAGMD_REDFLAG3, PREFIXMD_LOGFILE, type DatabaseConnectingStatus, type EntryHasPath, type DocumentID, type FilePathWithPrefix, type FilePath, type AnyEntry, LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_URGENT, LOG_LEVEL_VERBOSE, type SavingEntry, MISSING_OR_ERROR, NOT_CONFLICTED, AUTO_MERGED, CANCELLED, LEAVE_TO_SUBSEQUENT, FLAGMD_REDFLAG2_HR, FLAGMD_REDFLAG3_HR, REMOTE_MINIO, REMOTE_COUCHDB, type BucketSyncSetting, } from "./lib/src/types";
import { type InternalFileInfo, type CacheData, type FileEventItem, FileWatchEventQueueMax } from "./types"; import { type InternalFileInfo, type CacheData, type FileEventItem, FileWatchEventQueueMax } from "./types";
import { arrayToChunkedArray, createBlob, delay, determineTypeFromBlob, fireAndForget, getDocData, isAnyNote, isDocContentSame, isObjectDifferent, readContent, sendValue, throttle } from "./lib/src/utils"; import { arrayToChunkedArray, createBlob, delay, determineTypeFromBlob, fireAndForget, getDocData, isAnyNote, isDocContentSame, isObjectDifferent, readContent, sendValue, throttle, type SimpleStore } from "./lib/src/utils";
import { Logger, setGlobalLogFunction } from "./lib/src/logger"; import { Logger, setGlobalLogFunction } from "./lib/src/logger";
import { PouchDB } from "./lib/src/pouchdb-browser.js"; import { PouchDB } from "./lib/src/pouchdb-browser.js";
import { ConflictResolveModal } from "./ConflictResolveModal"; import { ConflictResolveModal } from "./ConflictResolveModal";
@@ -37,7 +37,7 @@ import { initializeStores } from "./stores.js";
import { JournalSyncMinio } from "./lib/src/JournalSyncMinio.js"; import { JournalSyncMinio } from "./lib/src/JournalSyncMinio.js";
import { LiveSyncJournalReplicator, type LiveSyncJournalReplicatorEnv } from "./lib/src/LiveSyncJournalReplicator.js"; import { LiveSyncJournalReplicator, type LiveSyncJournalReplicatorEnv } from "./lib/src/LiveSyncJournalReplicator.js";
import { LiveSyncCouchDBReplicator, type LiveSyncCouchDBReplicatorEnv } from "./lib/src/LiveSyncReplicator.js"; import { LiveSyncCouchDBReplicator, type LiveSyncCouchDBReplicatorEnv } from "./lib/src/LiveSyncReplicator.js";
import type { CheckPointInfo, SimpleStore } from "./lib/src/JournalSyncTypes.js"; import type { CheckPointInfo } from "./lib/src/JournalSyncTypes.js";
import { ObsHttpHandler } from "./ObsHttpHandler.js"; import { ObsHttpHandler } from "./ObsHttpHandler.js";
setNoticeClass(Notice); setNoticeClass(Notice);
@@ -477,7 +477,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin
}, },
keys: async (from: string | undefined, to: string | undefined, count?: number | undefined): Promise<string[]> => { keys: async (from: string | undefined, to: string | undefined, count?: number | undefined): Promise<string[]> => {
const ret = this.kvDB.keys(IDBKeyRange.bound(`os-${from || ""}`, `os-${to || ""}`), count); const ret = this.kvDB.keys(IDBKeyRange.bound(`os-${from || ""}`, `os-${to || ""}`), count);
return (await ret).map(e => e.toString()); return (await ret).map(e => e.toString()).filter(e => e.startsWith("os-")).map(e => e.substring(3));
} }
} }
getMinioJournalSyncClient() { getMinioJournalSyncClient() {

View File

@@ -18,6 +18,14 @@ I have a lot of respect for that plugin, even though it is sometimes treated as
Hooray for open source, and generous licences, and the sharing of knowledge by experts. Hooray for open source, and generous licences, and the sharing of knowledge by experts.
#### Version history #### Version history
- 0.23.2
- Sorry for all the fixes to experimental features. (These things were also critical for dogfooding). The next release would be the main fixes! Thank you for your patience and understanding!
- Fixed:
- Journal Sync will not hang up during big replication, especially the initial one.
- All changes which have been replicated while rebuilding will not be postponed (Previous behaviour).
- Improved:
- Now Journal Sync works efficiently in download and parse, or pack and upload.
- Less server storage and faster packing/unpacking usage by the new chunk format.
- 0.23.1 - 0.23.1
- Fixed: - Fixed:
- Now journal synchronisation considers untransferred each from sent and received. - Now journal synchronisation considers untransferred each from sent and received.