@abraca/dabra 2.0.7 → 2.0.9
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.
- package/dist/abracadabra-provider.cjs +36 -12
- package/dist/abracadabra-provider.cjs.map +1 -1
- package/dist/abracadabra-provider.esm.js +36 -12
- package/dist/abracadabra-provider.esm.js.map +1 -1
- package/dist/index.d.ts +51 -7
- package/package.json +1 -1
- package/src/AbracadabraClient.ts +3 -0
- package/src/AbracadabraProvider.ts +17 -0
|
@@ -2264,6 +2264,7 @@ var AbracadabraBaseProvider = class extends EventEmitter {
|
|
|
2264
2264
|
this.isSynced = false;
|
|
2265
2265
|
this.unsyncedChanges = 0;
|
|
2266
2266
|
this.isAuthenticated = false;
|
|
2267
|
+
this._hasEverAuthenticated = false;
|
|
2267
2268
|
this.authorizedScope = void 0;
|
|
2268
2269
|
this.manageSocket = false;
|
|
2269
2270
|
this._isAttached = false;
|
|
@@ -2474,6 +2475,7 @@ var AbracadabraBaseProvider = class extends EventEmitter {
|
|
|
2474
2475
|
onClose() {
|
|
2475
2476
|
this.isAuthenticated = false;
|
|
2476
2477
|
this.synced = false;
|
|
2478
|
+
this._hasEverAuthenticated = false;
|
|
2477
2479
|
if (this.awareness) removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter((client) => client !== this.document.clientID), this);
|
|
2478
2480
|
}
|
|
2479
2481
|
destroy() {
|
|
@@ -2530,12 +2532,13 @@ var AbracadabraBaseProvider = class extends EventEmitter {
|
|
|
2530
2532
|
permissionDeniedHandler(reason) {
|
|
2531
2533
|
this.emit("authenticationFailed", { reason });
|
|
2532
2534
|
this.isAuthenticated = false;
|
|
2533
|
-
if (this.manageSocket) try {
|
|
2535
|
+
if (this.manageSocket && !this._hasEverAuthenticated) try {
|
|
2534
2536
|
this.configuration.websocketProvider.disconnect();
|
|
2535
2537
|
} catch {}
|
|
2536
2538
|
}
|
|
2537
2539
|
authenticatedHandler(scope) {
|
|
2538
2540
|
this.isAuthenticated = true;
|
|
2541
|
+
this._hasEverAuthenticated = true;
|
|
2539
2542
|
this.authorizedScope = scope;
|
|
2540
2543
|
this.emit("authenticated", { scope });
|
|
2541
2544
|
}
|
|
@@ -2773,7 +2776,7 @@ function isValidDocId(id) {
|
|
|
2773
2776
|
*/
|
|
2774
2777
|
var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvider {
|
|
2775
2778
|
static {
|
|
2776
|
-
this.DEFAULT_MAX_CHILDREN =
|
|
2779
|
+
this.DEFAULT_MAX_CHILDREN = 64;
|
|
2777
2780
|
}
|
|
2778
2781
|
constructor(configuration) {
|
|
2779
2782
|
const resolved = { ...configuration };
|
|
@@ -2789,6 +2792,7 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
2789
2792
|
this.pendingLoads = /* @__PURE__ */ new Map();
|
|
2790
2793
|
this.childAccessTimes = /* @__PURE__ */ new Map();
|
|
2791
2794
|
this.pinnedChildren = /* @__PURE__ */ new Set();
|
|
2795
|
+
this.transientChildren = /* @__PURE__ */ new Set();
|
|
2792
2796
|
this.boundHandleYSubdocsChange = this.handleYSubdocsChange.bind(this);
|
|
2793
2797
|
this.hasCachedContent = false;
|
|
2794
2798
|
this._client = client;
|
|
@@ -2986,22 +2990,34 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
2986
2990
|
}
|
|
2987
2991
|
/**
|
|
2988
2992
|
* Create (or return cached) a child AbracadabraProvider for a given
|
|
2989
|
-
* child document id. Each child
|
|
2990
|
-
*
|
|
2993
|
+
* child document id. Each child shares the parent's WebSocket via
|
|
2994
|
+
* multiplexing.
|
|
2995
|
+
*
|
|
2996
|
+
* `evictable` (default `true`) controls whether the child enters the
|
|
2997
|
+
* LRU pool. Pass `evictable: false` for transient loads — typically
|
|
2998
|
+
* batch indexers (search, file extraction) that touch every doc in
|
|
2999
|
+
* the tree and would otherwise blow out the cache, silently evicting
|
|
3000
|
+
* subdocs the UI is actively using. Transient children are excluded
|
|
3001
|
+
* from the LRU budget AND don't trigger eviction of other children.
|
|
3002
|
+
* Callers MUST pair `loadChild(id, { evictable: false })` with an
|
|
3003
|
+
* explicit `unloadChild(id)` once they're done.
|
|
2991
3004
|
*/
|
|
2992
|
-
loadChild(childId) {
|
|
3005
|
+
loadChild(childId, options = {}) {
|
|
2993
3006
|
if (!isValidDocId(childId)) return Promise.reject(/* @__PURE__ */ new Error(`loadChild: "${childId}" is not a valid document ID (must be a UUID). If this node was created with an older version of the app, delete it and recreate it.`));
|
|
3007
|
+
if (childId === this.configuration.name) return Promise.resolve(this);
|
|
3008
|
+
const evictable = options.evictable !== false;
|
|
2994
3009
|
if (this.childProviders.has(childId)) {
|
|
2995
3010
|
this.childAccessTimes.set(childId, Date.now());
|
|
3011
|
+
if (evictable) this.transientChildren.delete(childId);
|
|
2996
3012
|
return Promise.resolve(this.childProviders.get(childId));
|
|
2997
3013
|
}
|
|
2998
3014
|
if (this.pendingLoads.has(childId)) return this.pendingLoads.get(childId);
|
|
2999
|
-
const load = this._doLoadChild(childId);
|
|
3015
|
+
const load = this._doLoadChild(childId, evictable);
|
|
3000
3016
|
this.pendingLoads.set(childId, load);
|
|
3001
3017
|
load.finally(() => this.pendingLoads.delete(childId));
|
|
3002
3018
|
return load;
|
|
3003
3019
|
}
|
|
3004
|
-
async _doLoadChild(childId) {
|
|
3020
|
+
async _doLoadChild(childId, evictable) {
|
|
3005
3021
|
const childDoc = new Y.Doc({ guid: childId });
|
|
3006
3022
|
this.registerSubdoc(childDoc);
|
|
3007
3023
|
const childProvider = new AbracadabraProvider({
|
|
@@ -3020,7 +3036,8 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
3020
3036
|
childProvider.attach();
|
|
3021
3037
|
this.childProviders.set(childId, childProvider);
|
|
3022
3038
|
this.childAccessTimes.set(childId, Date.now());
|
|
3023
|
-
this.
|
|
3039
|
+
if (!evictable) this.transientChildren.add(childId);
|
|
3040
|
+
if (evictable) this.evictLRU();
|
|
3024
3041
|
this.emit("subdocLoaded", {
|
|
3025
3042
|
childId,
|
|
3026
3043
|
provider: childProvider
|
|
@@ -3034,6 +3051,7 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
3034
3051
|
this.childProviders.delete(childId);
|
|
3035
3052
|
this.childAccessTimes.delete(childId);
|
|
3036
3053
|
this.pinnedChildren.delete(childId);
|
|
3054
|
+
this.transientChildren.delete(childId);
|
|
3037
3055
|
}
|
|
3038
3056
|
}
|
|
3039
3057
|
/**
|
|
@@ -3051,21 +3069,27 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
3051
3069
|
this.evictLRU();
|
|
3052
3070
|
}
|
|
3053
3071
|
/**
|
|
3054
|
-
* Evict least-recently-used unpinned child providers
|
|
3055
|
-
* at or below MAX_CHILDREN.
|
|
3072
|
+
* Evict least-recently-used unpinned, non-transient child providers
|
|
3073
|
+
* until the cache is at or below MAX_CHILDREN. Transient children
|
|
3074
|
+
* (loaded with `{ evictable: false }`) are excluded from both the
|
|
3075
|
+
* budget *and* the eviction list — they're invisible to the LRU and
|
|
3076
|
+
* only go away when their loader explicitly calls `unloadChild`.
|
|
3056
3077
|
*/
|
|
3057
3078
|
evictLRU() {
|
|
3058
|
-
|
|
3079
|
+
let nonTransientCount = 0;
|
|
3080
|
+
for (const id of this.childProviders.keys()) if (!this.transientChildren.has(id)) nonTransientCount++;
|
|
3081
|
+
if (nonTransientCount <= this.maxChildren) return;
|
|
3059
3082
|
const evictable = [];
|
|
3060
3083
|
for (const [id] of this.childProviders) {
|
|
3061
3084
|
if (this.pinnedChildren.has(id)) continue;
|
|
3085
|
+
if (this.transientChildren.has(id)) continue;
|
|
3062
3086
|
evictable.push({
|
|
3063
3087
|
id,
|
|
3064
3088
|
accessTime: this.childAccessTimes.get(id) ?? 0
|
|
3065
3089
|
});
|
|
3066
3090
|
}
|
|
3067
3091
|
evictable.sort((a, b) => a.accessTime - b.accessTime);
|
|
3068
|
-
let toEvict =
|
|
3092
|
+
let toEvict = nonTransientCount - this.maxChildren;
|
|
3069
3093
|
for (const entry of evictable) {
|
|
3070
3094
|
if (toEvict <= 0) break;
|
|
3071
3095
|
this.unloadChild(entry.id);
|