mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-08-31 15:57:06 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9df2a859f | ||
|
|
b7c2512da6 | ||
|
|
97b0ec25c7 | ||
|
|
bc41355a74 | ||
|
|
3d69142a52 | ||
|
|
2403a66441 |
@@ -0,0 +1,329 @@
|
|||||||
|
# Architectural Decision Record: CouchDB Remote Connection Ownership
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Accepted. The first implementation is deliberately limited to the
|
||||||
|
abort-capable CouchDB connectivity preflight used by one-shot replication.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Commonlib opens a remote CouchDB database through `RemoteService.connect()`.
|
||||||
|
Before this decision, a successful call returned only a PouchDB handle and an
|
||||||
|
information snapshot:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
db: PouchDB.Database<EntryDoc>;
|
||||||
|
info: PouchDB.Core.DatabaseInfo;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The value did not state who must close the handle or how requests which outlive
|
||||||
|
the current operation are cancelled. Callers consequently accumulated their
|
||||||
|
own `try`/`finally` blocks and closing helpers. Commonlib PR 112 made finite
|
||||||
|
handle clean-up substantially safer, but closing a raw PouchDB handle still did
|
||||||
|
not define ownership of its outstanding HTTP work.
|
||||||
|
|
||||||
|
A remote PouchDB HTTP handle is not a dedicated socket. `db.close()` emits
|
||||||
|
PouchDB's normal `closed` event and closes the logical handle, but the HTTP
|
||||||
|
adapter does not establish that a pending browser fetch or response-body read
|
||||||
|
has stopped. `RemoteService.performFetch()` also records a physical request as
|
||||||
|
complete once response headers have arrived, while PouchDB may still be reading
|
||||||
|
and parsing the body. Neither the request counters nor raw `db.close()` can
|
||||||
|
therefore prove that the transport work has settled.
|
||||||
|
|
||||||
|
One-shot CouchDB replication performs the following work before it creates the
|
||||||
|
replication controller:
|
||||||
|
|
||||||
|
1. prepare the encryption security seed;
|
||||||
|
2. construct the remote PouchDB handle and read database information;
|
||||||
|
3. check and, where required, migrate the remote database version;
|
||||||
|
4. read and update compatibility Metadata, including the milestone document;
|
||||||
|
and
|
||||||
|
5. create the PouchDB replication operation.
|
||||||
|
|
||||||
|
The controller owned by `processSync()` begins only at step 5. A request which
|
||||||
|
never settles during steps 2 to 4 is outside that cancellation scope. The
|
||||||
|
shared one-shot result remains pending as well, so later triggers join the same
|
||||||
|
pending operation rather than beginning a fresh attempt.
|
||||||
|
|
||||||
|
Self-hosted LiveSync issue 1116 provides evidence of this failure shape. On one
|
||||||
|
Linux and Electron combination, a one-shot attempt remained pending while
|
||||||
|
writing the remote milestone document. Bypassing that write allowed the
|
||||||
|
attempt to reach later replication requests. A local real-Obsidian exercise
|
||||||
|
reproduced the preceding Fast Fetch state but not the indefinite write. The
|
||||||
|
evidence does not establish a milestone-specific defect, a CouchDB defect, a
|
||||||
|
browser connection-pool defect, or a lock cycle. It does establish that the
|
||||||
|
connectivity preflight lacks an owner which can terminate its abort-capable
|
||||||
|
transport work.
|
||||||
|
|
||||||
|
No code-level circular wait has been identified. `shareRunningResult()` shares
|
||||||
|
a logical promise, the remote-activity counters observe work, and the global
|
||||||
|
replication concurrency controller is entered only after the preflight. Adding
|
||||||
|
a semaphore or another connection lock would let a stalled request retain the
|
||||||
|
permit; it would not make that request settle.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
### Extend the existing connection result
|
||||||
|
|
||||||
|
Commonlib will define the owned connection as the existing flat result with one
|
||||||
|
additional operation:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface RemoteConnectionOpenOptions {
|
||||||
|
readonly signal?: AbortSignal;
|
||||||
|
readonly allowNativeFallback?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OwnedCouchDBConnection<T extends object> {
|
||||||
|
readonly db: PouchDB.Database<T>;
|
||||||
|
readonly info: PouchDB.Core.DatabaseInfo;
|
||||||
|
close(): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CouchDBReplicationConnection extends OwnedCouchDBConnection<EntryDoc> {
|
||||||
|
readonly syncOptionBase: PouchDB.Replication.SyncOptions;
|
||||||
|
readonly syncOption: PouchDB.Replication.SyncOptions;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`RemoteService.connect()` remains the entry point. It returns
|
||||||
|
`OwnedCouchDBConnection` directly; there is no nested resource wrapper, separate
|
||||||
|
lease API, public connection signal, or public `abort()` operation. The
|
||||||
|
connection and checked replication types are owned and documented by
|
||||||
|
Commonlib. Compatibility checks enrich the same connection with replication
|
||||||
|
options instead of creating another lifetime object.
|
||||||
|
|
||||||
|
The following properties are part of the contract:
|
||||||
|
|
||||||
|
- `close()` is idempotent;
|
||||||
|
- `close()` first cancels abort-capable requests scoped to the connection, then
|
||||||
|
calls PouchDB's ordinary `db.close()`;
|
||||||
|
- PouchDB retains its normal `closed` event behaviour;
|
||||||
|
- the optional input signal cancels the same internal request scope;
|
||||||
|
- skipping the information request retains the established placeholder in
|
||||||
|
`info` for source and behaviour compatibility;
|
||||||
|
- a close failure is reported diagnostically but does not replace the primary
|
||||||
|
replication result; and
|
||||||
|
- ownership of the connection does not imply ownership of a dedicated physical
|
||||||
|
HTTP socket.
|
||||||
|
|
||||||
|
The public connection does not expose its internal signal because no caller
|
||||||
|
needs to make a second shutdown decision. Owners either cancel through the
|
||||||
|
input signal or finish through `close()`. This leaves one operation responsible
|
||||||
|
for final clean-up.
|
||||||
|
|
||||||
|
Replacing the existing error-string union with a typed connection-failure
|
||||||
|
result remains desirable, but it is outside this change. Mixing that migration
|
||||||
|
into the first implementation would enlarge the consumer and user-message
|
||||||
|
surface without improving cancellation.
|
||||||
|
|
||||||
|
### Bind cancellation at the custom fetch boundary
|
||||||
|
|
||||||
|
`RemoteService.connect()` creates its internal request scope before PouchDB is
|
||||||
|
constructed, so the initial `db.info()` request is covered. The custom PouchDB
|
||||||
|
fetch implementation combines, without replacing, both applicable signals:
|
||||||
|
|
||||||
|
- the signal supplied by PouchDB for the individual request; and
|
||||||
|
- the signal for the owned connection, which follows its optional owner signal.
|
||||||
|
|
||||||
|
The combined signal remains applicable while the response body is consumed.
|
||||||
|
Receiving response headers is not the end of cancellation ownership.
|
||||||
|
|
||||||
|
Cancellation is not a CORS failure. If the connection scope has been aborted,
|
||||||
|
the request must not enter the diagnostic fallback from the web-compatible
|
||||||
|
fetch path to the native request API. A bounded owner can also disable that
|
||||||
|
fallback explicitly.
|
||||||
|
|
||||||
|
The web-compatible fetch path honours `AbortSignal`. Obsidian's current native
|
||||||
|
`requestUrl` adapter does not expose physical cancellation through
|
||||||
|
`RequestInit.signal`. The implementation must not use `Promise.race()` to
|
||||||
|
declare a native remote write cancelled while it may still complete. A bounded
|
||||||
|
guarantee therefore applies only where the selected request path remains
|
||||||
|
abort-capable.
|
||||||
|
|
||||||
|
### Transfer the same connection between owners
|
||||||
|
|
||||||
|
At every point, exactly one operation is responsible for calling `close()`:
|
||||||
|
|
||||||
|
1. `RemoteService.connect()` owns the connection until it returns successfully;
|
||||||
|
2. the connectivity preflight owns it while checking version and compatibility;
|
||||||
|
3. a successful preflight transfers the same connection to the one-shot or
|
||||||
|
continuous replication operation; and
|
||||||
|
4. the final replication owner closes it after replication settles or is
|
||||||
|
terminated.
|
||||||
|
|
||||||
|
A failed factory or preflight closes the connection in its own failure path. A
|
||||||
|
successful transfer clears the former owner's deadline before replication
|
||||||
|
continues. Borrowing `connection.db` does not transfer close responsibility.
|
||||||
|
|
||||||
|
`shareRunningResult()` owns no connection. It may share the result of an
|
||||||
|
operation which owns one, but that operation must settle and close the
|
||||||
|
connection before the shared entry can be released for a later attempt.
|
||||||
|
|
||||||
|
## Limited Introduction
|
||||||
|
|
||||||
|
The first bounded consumer is the CouchDB connectivity preflight reached from
|
||||||
|
one-shot replication. Its boundary includes:
|
||||||
|
|
||||||
|
- PouchDB construction and the initial `db.info()` request;
|
||||||
|
- the database-version check and migration negotiation; and
|
||||||
|
- compatibility and milestone reads and writes before replication starts.
|
||||||
|
|
||||||
|
The preflight receives an internal 60-second wall-clock deadline. This is a
|
||||||
|
last-resort safety fuse for an owner which would otherwise remain pending
|
||||||
|
indefinitely. It is not the expected completion time, a service-level target, a
|
||||||
|
per-request inactivity timeout, a user setting, a limit on replication
|
||||||
|
duration, or the `useTimeouts` changes-feed setting. Tests inject a shorter
|
||||||
|
deadline.
|
||||||
|
|
||||||
|
When that deadline expires on the web-compatible path:
|
||||||
|
|
||||||
|
1. the owner signal aborts the connection's request scope;
|
||||||
|
2. the preflight closes the connection;
|
||||||
|
3. no PouchDB replication operation is created;
|
||||||
|
4. the shared one-shot result settles as failed; and
|
||||||
|
5. a later trigger may create a fresh connection and attempt.
|
||||||
|
|
||||||
|
On success, the deadline is cleared before the connection is transferred to
|
||||||
|
replication, so an old timer cannot interrupt a healthy long-running transfer.
|
||||||
|
|
||||||
|
The explicitly selected native Request API retains its previous unbounded
|
||||||
|
behaviour because its host adapter cannot honour transport cancellation. The
|
||||||
|
security-seed preparation which precedes the shared one-shot operation is also
|
||||||
|
outside this first boundary. Fast Fetch, setup probes, maintenance commands,
|
||||||
|
status inspection, and other direct CouchDB consumers retain their existing
|
||||||
|
deadline and retry policies. They receive the additive `close()` contract but
|
||||||
|
are not silently given this one-shot deadline.
|
||||||
|
|
||||||
|
The first implementation does not add automatic retry. Retrying before the old
|
||||||
|
request is known to be cancelled could duplicate remote writes or consume more
|
||||||
|
connections without changing the failing condition.
|
||||||
|
|
||||||
|
## Ownership
|
||||||
|
|
||||||
|
The legacy `_ensureConnection()` method retains its raw PouchDB return type for
|
||||||
|
source compatibility. New Commonlib paths use an internal owned-connection
|
||||||
|
helper and do not discard the lifecycle object.
|
||||||
|
|
||||||
|
Commonlib owns:
|
||||||
|
|
||||||
|
- `OwnedCouchDBConnection`, `RemoteConnectionOpenOptions`, and
|
||||||
|
`CouchDBReplicationConnection`;
|
||||||
|
- composition of PouchDB request and connection cancellation signals;
|
||||||
|
- the PouchDB custom-fetch integration;
|
||||||
|
- idempotent connection close behaviour;
|
||||||
|
- ownership transfer within the CouchDB replicator; and
|
||||||
|
- timeout classification at the connectivity-preflight boundary.
|
||||||
|
|
||||||
|
Self-hosted LiveSync owns:
|
||||||
|
|
||||||
|
- the concrete Obsidian fetch adapters and their declared capabilities;
|
||||||
|
- user-facing logs or notices for a timed-out attempt;
|
||||||
|
- integration of an immutable Commonlib release; and
|
||||||
|
- real-Obsidian validation of the affected consumer path.
|
||||||
|
|
||||||
|
No host may claim physical cancellation unless its injected fetch
|
||||||
|
implementation honours the supplied signal.
|
||||||
|
|
||||||
|
## Non-Goals
|
||||||
|
|
||||||
|
This decision does not:
|
||||||
|
|
||||||
|
- identify the exact environmental cause reported in issue 1116;
|
||||||
|
- guarantee that a one-shot attempt succeeds;
|
||||||
|
- special-case the milestone document or its URL;
|
||||||
|
- impose a global connection limit or connection semaphore;
|
||||||
|
- add an automatic retry, fallback, or remote reconciliation policy;
|
||||||
|
- apply a deadline to ordinary replication, continuous changes feeds, Fast
|
||||||
|
Fetch, rebuilds, or bulk transfers;
|
||||||
|
- change CouchDB documents, checkpoints, encryption, the security seed, or
|
||||||
|
compatibility Metadata;
|
||||||
|
- make `close()` equivalent to closing a browser socket;
|
||||||
|
- detach a potentially mutating native request and report it as cancelled; or
|
||||||
|
- migrate every direct PouchDB borrower to the one-shot deadline policy.
|
||||||
|
|
||||||
|
## Alternatives Rejected
|
||||||
|
|
||||||
|
### Time out only the milestone write
|
||||||
|
|
||||||
|
The observed write is where one report stopped, not an established ownership
|
||||||
|
boundary. Another environment could stop at `db.info()`, version Metadata,
|
||||||
|
response-body parsing, or an adjacent compatibility request.
|
||||||
|
|
||||||
|
### Race the preflight without cancelling its transport
|
||||||
|
|
||||||
|
This would release `shareRunningResult()` while the old request remained able
|
||||||
|
to complete. It is especially unsafe for a remote `PUT`, because a later
|
||||||
|
attempt could begin after the first had been reported as failed.
|
||||||
|
|
||||||
|
### Add a global semaphore or lower the connection count
|
||||||
|
|
||||||
|
No connection-limit failure has been demonstrated. A stalled owner would
|
||||||
|
retain its permit indefinitely and turn an unexplained request into an explicit
|
||||||
|
queue deadlock.
|
||||||
|
|
||||||
|
### Add a separate lease wrapper
|
||||||
|
|
||||||
|
A nested `{ connection: { db, close }, info }` result would make ownership
|
||||||
|
visible, but it would duplicate the existing connection shape, force callers
|
||||||
|
through another projection, and expose lifetime operations which have no
|
||||||
|
consumer. Adding `close()` to the existing value preserves source compatibility
|
||||||
|
and keeps the PouchDB handle, information snapshot, and lifetime together.
|
||||||
|
|
||||||
|
### Share one global remote PouchDB handle
|
||||||
|
|
||||||
|
A singleton would couple setup, maintenance, one-shot, and continuous
|
||||||
|
lifecycles, make credential and setting changes harder to isolate, and turn one
|
||||||
|
stalled request into a process-wide resource.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
The regression tests were changed before the implementation. Against the old
|
||||||
|
flat result they demonstrated that:
|
||||||
|
|
||||||
|
- an owner signal left an in-flight request pending;
|
||||||
|
- the result had no `close()` operation capable of interrupting a body read;
|
||||||
|
- a bounded web-compatible request could enter the native fallback; and
|
||||||
|
- the one-shot path still depended on the discarded nested connection API.
|
||||||
|
|
||||||
|
After the change, focused Commonlib tests verify that:
|
||||||
|
|
||||||
|
- an owner signal settles a pending request;
|
||||||
|
- `close()` interrupts a response body read before closing PouchDB;
|
||||||
|
- repeated `close()` calls close the handle once;
|
||||||
|
- an aborted or bounded request does not enter the non-abortable native adapter;
|
||||||
|
- deadline expiry closes the same flat connection and releases the shared
|
||||||
|
one-shot attempt;
|
||||||
|
- a later invocation begins after that release;
|
||||||
|
- a successful preflight clears its deadline and transfers ownership; and
|
||||||
|
- close failures are logged without replacing timeout or replication results.
|
||||||
|
|
||||||
|
Type checking and package-boundary checks verify the Commonlib-owned
|
||||||
|
declarations and compatibility export. Self-hosted LiveSync must then validate
|
||||||
|
the exact packed Commonlib artefact with its focused consumer tests and an
|
||||||
|
ordinary real-Obsidian and CouchDB smoke test. The reporter's environment
|
||||||
|
remains the validation boundary for the original platform-specific symptom.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- A successful remote connection has one explicit close operation without a
|
||||||
|
parallel lease abstraction.
|
||||||
|
- Existing `{ db, info }` consumers remain source-compatible and may adopt
|
||||||
|
`close()` without changing their projections.
|
||||||
|
- One-shot connectivity can become a bounded failure on an abort-capable
|
||||||
|
transport instead of retaining the shared operation indefinitely.
|
||||||
|
- Native `requestUrl` cancellation remains an acknowledged gap rather than a
|
||||||
|
falsely satisfied contract.
|
||||||
|
- Other finite consumers can adopt owner signals and explicit `close()` one at
|
||||||
|
a time, with tests for their own side effects and retry policies.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Bounded Remote Activity](2026_07_bounded_remote_activity.md)
|
||||||
|
- [Fast Fetch Persistence and Completion Semantics](2026_08_fast_fetch_persistence_and_completion.md)
|
||||||
|
- Commonlib PR 112, which closes finite remote PouchDB handles after their
|
||||||
|
logical owners settle
|
||||||
|
- Self-hosted LiveSync issue 1116, which reports a one-shot compatibility write
|
||||||
|
remaining pending on one Linux and Electron environment
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "obsidian-livesync",
|
"id": "obsidian-livesync",
|
||||||
"name": "Self-hosted LiveSync",
|
"name": "Self-hosted LiveSync",
|
||||||
"version": "1.0.14",
|
"version": "1.0.15",
|
||||||
"minAppVersion": "1.7.2",
|
"minAppVersion": "1.7.2",
|
||||||
"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",
|
||||||
|
|||||||
Generated
+9
-9
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "1.0.14",
|
"version": "1.0.15",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "1.0.14",
|
"version": "1.0.15",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"src/apps/cli",
|
"src/apps/cli",
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
"@smithy/types": "^4.14.3",
|
"@smithy/types": "^4.14.3",
|
||||||
"@smithy/util-retry": "^4.4.5",
|
"@smithy/util-retry": "^4.4.5",
|
||||||
"@vrtmrz/browser-ui-kit": "0.1.0",
|
"@vrtmrz/browser-ui-kit": "0.1.0",
|
||||||
"@vrtmrz/livesync-commonlib": "0.1.15",
|
"@vrtmrz/livesync-commonlib": "0.1.16",
|
||||||
"@vrtmrz/obsidian-plugin-kit": "0.1.3",
|
"@vrtmrz/obsidian-plugin-kit": "0.1.3",
|
||||||
"@vrtmrz/ui-interactions": "0.1.2",
|
"@vrtmrz/ui-interactions": "0.1.2",
|
||||||
"diff-match-patch": "^1.0.5",
|
"diff-match-patch": "^1.0.5",
|
||||||
@@ -4771,9 +4771,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vrtmrz/livesync-commonlib": {
|
"node_modules/@vrtmrz/livesync-commonlib": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "https://registry.npmjs.org/@vrtmrz/livesync-commonlib/-/livesync-commonlib-0.1.15.tgz",
|
"resolved": "https://registry.npmjs.org/@vrtmrz/livesync-commonlib/-/livesync-commonlib-0.1.16.tgz",
|
||||||
"integrity": "sha512-uQxxzOdzu0MVcS6g20AxNLNj933Q3N5j/gZ2o6sem36vlsXQPKnsjGjTzrYcYAXNJ9mkR82EvC8qmKnOZvjEPg==",
|
"integrity": "sha512-vQlhLP2Qvf72zc/FedJQgOy/+Ri5zWuX+WKSD9fGaSWkBtX+nWkHx/9fgGdwkNEgighd4eCREVXfPvjcJKWX4w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.808.0",
|
"@aws-sdk/client-s3": "^3.808.0",
|
||||||
@@ -15923,7 +15923,7 @@
|
|||||||
},
|
},
|
||||||
"src/apps/cli": {
|
"src/apps/cli": {
|
||||||
"name": "self-hosted-livesync-cli",
|
"name": "self-hosted-livesync-cli",
|
||||||
"version": "1.0.14-cli",
|
"version": "1.0.15-cli",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^4.0.0",
|
"chokidar": "^4.0.0",
|
||||||
"minimatch": "^10.2.5",
|
"minimatch": "^10.2.5",
|
||||||
@@ -15948,7 +15948,7 @@
|
|||||||
},
|
},
|
||||||
"src/apps/webapp": {
|
"src/apps/webapp": {
|
||||||
"name": "livesync-webapp",
|
"name": "livesync-webapp",
|
||||||
"version": "1.0.14-webapp",
|
"version": "1.0.15-webapp",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"octagonal-wheels": "^0.1.53"
|
"octagonal-wheels": "^0.1.53"
|
||||||
},
|
},
|
||||||
@@ -15960,7 +15960,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/apps/webpeer": {
|
"src/apps/webpeer": {
|
||||||
"version": "1.0.14-webpeer",
|
"version": "1.0.15-webpeer",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"octagonal-wheels": "^0.1.53"
|
"octagonal-wheels": "^0.1.53"
|
||||||
},
|
},
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "1.0.14",
|
"version": "1.0.15",
|
||||||
"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",
|
||||||
@@ -177,7 +177,7 @@
|
|||||||
"@smithy/types": "^4.14.3",
|
"@smithy/types": "^4.14.3",
|
||||||
"@smithy/util-retry": "^4.4.5",
|
"@smithy/util-retry": "^4.4.5",
|
||||||
"@vrtmrz/browser-ui-kit": "0.1.0",
|
"@vrtmrz/browser-ui-kit": "0.1.0",
|
||||||
"@vrtmrz/livesync-commonlib": "0.1.15",
|
"@vrtmrz/livesync-commonlib": "0.1.16",
|
||||||
"@vrtmrz/obsidian-plugin-kit": "0.1.3",
|
"@vrtmrz/obsidian-plugin-kit": "0.1.3",
|
||||||
"@vrtmrz/ui-interactions": "0.1.2",
|
"@vrtmrz/ui-interactions": "0.1.2",
|
||||||
"diff-match-patch": "^1.0.5",
|
"diff-match-patch": "^1.0.5",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "self-hosted-livesync-cli",
|
"name": "self-hosted-livesync-cli",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.14-cli",
|
"version": "1.0.15-cli",
|
||||||
"main": "dist/index.cjs",
|
"main": "dist/index.cjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "livesync-webapp",
|
"name": "livesync-webapp",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.14-webapp",
|
"version": "1.0.15-webapp",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Browser-based Self-hosted LiveSync using FileSystem API",
|
"description": "Browser-based Self-hosted LiveSync using FileSystem API",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "webpeer",
|
"name": "webpeer",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.14-webpeer",
|
"version": "1.0.15-webpeer",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
+11
@@ -16,6 +16,17 @@ Earlier releases remain available in the 1.0 release history, the 1.0 preview hi
|
|||||||
|
|
||||||
#### Improved
|
#### Improved
|
||||||
|
|
||||||
|
- One-shot CouchDB synchronisation now releases stalled web-compatible connection checks before replication starts, so a later synchronisation can make a fresh attempt (Commonlib 0.1.16).
|
||||||
|
- The 60-second safeguard applies only to pre-replication checks. It does not limit ordinary synchronisation, and the **Use Internal API** path is unchanged.
|
||||||
|
|
||||||
|
## 1.0.15
|
||||||
|
|
||||||
|
15th August, 2026
|
||||||
|
|
||||||
|
### Synchronisation and storage
|
||||||
|
|
||||||
|
#### Improved
|
||||||
|
|
||||||
- Start-up offline scanning is now faster, especially for larger Vaults using path obfuscation (Commonlib 0.1.15).
|
- Start-up offline scanning is now faster, especially for larger Vaults using path obfuscation (Commonlib 0.1.15).
|
||||||
|
|
||||||
### Interface and translation
|
### Interface and translation
|
||||||
|
|||||||
+2
-1
@@ -26,5 +26,6 @@
|
|||||||
"1.0.11": "1.7.2",
|
"1.0.11": "1.7.2",
|
||||||
"1.0.12": "1.7.2",
|
"1.0.12": "1.7.2",
|
||||||
"1.0.13": "1.7.2",
|
"1.0.13": "1.7.2",
|
||||||
"1.0.14": "1.7.2"
|
"1.0.14": "1.7.2",
|
||||||
|
"1.0.15": "1.7.2"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user