mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-08-30 15:27:06 +00:00
Define the replication scheduling service boundary
This commit is contained in:
@@ -130,16 +130,38 @@ The selected provider and its active Replicator decide **how**, and whether,
|
||||
that request can be performed. A provider module must not subscribe to the
|
||||
application resume lifecycle merely because it can construct a transport.
|
||||
|
||||
Self-hosted LiveSync will have one LiveSync-owned core ServiceModule as the
|
||||
replication lifecycle coordinator. It uses `AppLifecycleService`, persisted
|
||||
settings, `ReplicationService`, and the active support declaration. It does
|
||||
not branch on `remoteType` or use `instanceof` as a capability test.
|
||||
Commonlib owns the trigger-aware replication contract; the host owns
|
||||
application lifecycle wiring.
|
||||
Self-hosted LiveSync will compose one LiveSync-owned serviceFeature as the
|
||||
replication scheduling boundary. The serviceFeature constructs one private
|
||||
scheduling controller and connects it to `AppLifecycleService`, settings
|
||||
lifecycle events, and the periodic timer. The controller owns only scheduling
|
||||
state and transitions: external-poller ownership, Continuous ownership of
|
||||
recurring work, the daemon's satisfied initial OneShot marker, resume
|
||||
coalescing, and periodic-timer reconciliation. It does not register handlers
|
||||
or acquire `LiveSyncBaseCore`.
|
||||
|
||||
The controller receives narrow collaborators for readiness and suspension
|
||||
queries, current settings, `ReplicationService`, periodic-timer control, and
|
||||
diagnostic logging. The surrounding serviceFeature owns lifecycle registration
|
||||
and adapts those Services to the controller. It returns a focused control view
|
||||
containing only the daemon operations to select external polling and mark the
|
||||
initial OneShot as satisfied. The host may retain that view for the CLI, but
|
||||
must not expose the controller's mutable state or recover it from a core-keyed
|
||||
global or `WeakMap`.
|
||||
|
||||
This boundary is not a ServiceModule merely because it owns state. It neither
|
||||
owns a shared external resource nor supplies a general operational capability
|
||||
to several unrelated consumers. If a future consumer needs a stable shared
|
||||
scheduling capability beyond the focused CLI view, that ownership decision
|
||||
must be reviewed explicitly rather than widening the controller implicitly.
|
||||
|
||||
The scheduling controller uses persisted settings, `ReplicationService`, and
|
||||
the active support declaration. It does not branch on `remoteType` or use
|
||||
`instanceof` as a capability test. Commonlib owns the trigger-aware replication
|
||||
contract; the host owns application lifecycle wiring.
|
||||
|
||||
The existing `onResumed` event remains the eligible-resume boundary after
|
||||
initial readiness, settings application, and visibility recovery. It is not
|
||||
redefined as a once-per-process event. The coordinator coalesces duplicate work
|
||||
redefined as a once-per-process event. The controller coalesces duplicate work
|
||||
within one lifecycle generation and preserves readiness and suspension gates:
|
||||
|
||||
- configured Continuous replication starts only through an active Continuous
|
||||
@@ -155,8 +177,8 @@ within one lifecycle generation and preserves readiness and suspension gates:
|
||||
`ReplicationService` remains responsible for readiness checks, bounded finite
|
||||
activity, failure processing, and replication timing. It exposes distinct
|
||||
user-initiated and unattended entry points, or a typed request which carries
|
||||
interaction authority. The coordinator never calls a concrete Replicator's
|
||||
`openReplication()` directly.
|
||||
interaction authority. The scheduling controller never calls a concrete
|
||||
Replicator's `openReplication()` directly.
|
||||
|
||||
`P2P_AutoStart` remains a separate P2P room policy. It is not central
|
||||
Continuous replication and is not `syncOnStart`; its service lifecycle is
|
||||
@@ -164,14 +186,30 @@ specified in Part 2. Reopening after `EVENT_DATABASE_REBUILT` is a
|
||||
flow-authorised continuation requested by the Rebuilder, not evidence that
|
||||
AutoStart is enabled.
|
||||
|
||||
Correctness must not depend on the registration order of equal-priority resume
|
||||
handlers. P2P AutoStart records persistent room demand, while an unattended P2P
|
||||
OneShot records finite room demand. `P2PRoomSessionOwner` serialises both and
|
||||
retains the room while either demand remains. Provider-specific P2P lifecycle
|
||||
wiring and host replication scheduling may therefore run in either order.
|
||||
Focused owner tests cover AutoStart-before-OneShot and OneShot-before-AutoStart;
|
||||
the host feature-binding test must not encode their current registration order
|
||||
as a scheduling prerequisite.
|
||||
|
||||
The CLI daemon owns its initial finite convergence before its mirror scan.
|
||||
Restored settings mark that convergence as satisfied for the current lifecycle
|
||||
generation, so `syncOnStart` does not repeat it. In `--interval` mode, the
|
||||
daemon poller is the sole recurring remote-poll scheduler. In changes-feed mode,
|
||||
the coordinator starts one configured Continuous session when supported;
|
||||
the controller starts one configured Continuous session when supported;
|
||||
otherwise it may enable the configured generic periodic timer. Continuous has
|
||||
precedence when both are configured.
|
||||
|
||||
The controller starts resume work synchronously far enough to reserve
|
||||
Continuous ownership, then lets the lifecycle handler settle without awaiting
|
||||
network completion. Concurrent resume notifications share one internal
|
||||
operation. Periodic reconciliation therefore observes the reservation before
|
||||
it can enable a competing timer. A failed operation is logged and releases the
|
||||
coalescing slot so a later resume can retry.
|
||||
|
||||
### Use a fixed current-provider definition
|
||||
|
||||
Commonlib defines the canonical current remote kinds, provider contract,
|
||||
@@ -183,7 +221,7 @@ API.
|
||||
|
||||
CouchDB is part of every current host composition. Object Storage and P2P are
|
||||
compile-time composition choices and may be included or omitted without
|
||||
changing the generic lifecycle coordinator. Adding another current provider
|
||||
changing the generic scheduling feature. Adding another current provider
|
||||
requires a Commonlib kind and support declaration, host composition,
|
||||
Setup/profile schema handling, and provider-specific tests. It does not require
|
||||
a runtime plug-in registry or behaviour for unknown provider kinds.
|
||||
|
||||
@@ -60,12 +60,14 @@ Object Storage handling, add a failing test in which a stopped or failed
|
||||
journal transfer must not produce a completed outcome; then propagate the
|
||||
actual journal result.
|
||||
|
||||
Add the LiveSync-owned lifecycle coordinator, remove the resume handler from
|
||||
`ModuleReplicatorCouchDB`, and route CouchDB Continuous and OneShot Sync plus
|
||||
Object Storage `syncOnStart` through `ReplicationService`. Migrate every
|
||||
automatic caller to the unattended entry point in this stage, so periodic and
|
||||
event calls cannot fall back to an interactive P2P role. Migrate manual commands
|
||||
to the user-initiated entry point.
|
||||
Add the LiveSync-owned replication scheduling serviceFeature, remove the resume
|
||||
handler from `ModuleReplicatorCouchDB`, and route CouchDB Continuous and OneShot
|
||||
Sync plus Object Storage `syncOnStart` through `ReplicationService`. Its private
|
||||
controller owns scheduling state and transition order; the serviceFeature owns
|
||||
lifecycle and settings-handler registration. Migrate every automatic caller to
|
||||
the unattended entry point in this stage, so periodic and event calls cannot
|
||||
fall back to an interactive P2P role. Migrate manual commands to the
|
||||
user-initiated entry point.
|
||||
|
||||
Replace the factory-registration-only responsibilities of
|
||||
`ModuleReplicatorCouchDB` and `ModuleReplicatorMinIO` with composed provider
|
||||
@@ -79,10 +81,12 @@ snapshot. This is the minimum publication fence for this stage. Waiting for
|
||||
in-flight adapter work and making acquisitions wait for replacement settlement
|
||||
remain part of the later active-construction migration.
|
||||
|
||||
The lifecycle coordinator coalesces its network work internally, but an
|
||||
The scheduling controller coalesces its network work internally, but an
|
||||
`onResumed` handler settles once that work has been scheduled. It does not hold
|
||||
later resume consumers until a OneShot transfer or Continuous start has
|
||||
settled.
|
||||
settled. Compose the controller with narrow replication, settings, lifecycle,
|
||||
timer, and logging collaborators. Return only the daemon-facing control view;
|
||||
do not retain scheduling state in a core-keyed `WeakMap`.
|
||||
|
||||
At this boundary, existing P2P AutoSync, AutoWatch, and incoming-request
|
||||
entry points receive the same non-interactive readiness and accepted-peer gate.
|
||||
@@ -90,6 +94,12 @@ The no-interaction authority reaches counterpart RPC authorisation and
|
||||
broadcast progress notifications. An unknown peer is blocked rather than
|
||||
prompting.
|
||||
|
||||
Add focused Commonlib owner tests which start an unattended finite room demand
|
||||
before AutoStart demand and after AutoStart demand. Both orders retain one room
|
||||
until every remaining demand has settled. The LiveSync feature-binding test
|
||||
must not rely on the current registration order of equal-priority resume
|
||||
handlers.
|
||||
|
||||
Until Stage 4 supplies target-aware unattended P2P, each host composition
|
||||
declares generic `P2P_SyncOnReplication` as `not-implemented`. Its automatic
|
||||
request settles without UI with an explicit blocked result. Existing AutoSync,
|
||||
@@ -97,7 +107,11 @@ AutoWatch, and accepted incoming-request paths continue with the Stage 2 gate.
|
||||
This is a temporary migration state, not the target matrix in Part 1.
|
||||
|
||||
Apply and test the CLI scheduling precedence defined in Part 1, so the daemon
|
||||
and lifecycle coordinator cannot schedule duplicate initial or recurring work.
|
||||
and scheduling controller cannot schedule duplicate initial or recurring work.
|
||||
Replace `ModuleReplicationLifecycle` and the replication-specific
|
||||
`ModulePeriodicProcess` wiring only after equivalent controller and feature-
|
||||
binding tests pass. Reuse the existing timer implementation behind a narrow
|
||||
timer port; changing other periodic feature owners is outside this stage.
|
||||
|
||||
## Stage 3: make P2P transport ownership truthful
|
||||
|
||||
|
||||
Reference in New Issue
Block a user