@arcote.tech/arc 0.7.10 → 0.7.11
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/index.js
CHANGED
|
@@ -4597,6 +4597,7 @@ class StreamingQueryCache {
|
|
|
4597
4597
|
views = [];
|
|
4598
4598
|
activeStreams = new Map;
|
|
4599
4599
|
pendingUnsubscribes = new Map;
|
|
4600
|
+
streamScopes = new Map;
|
|
4600
4601
|
static UNSUBSCRIBE_DELAY_MS = 5000;
|
|
4601
4602
|
registerViews(views) {
|
|
4602
4603
|
this.views = views;
|
|
@@ -4655,6 +4656,7 @@ class StreamingQueryCache {
|
|
|
4655
4656
|
if (current && current.refCount <= 0) {
|
|
4656
4657
|
current.unsubscribe();
|
|
4657
4658
|
this.activeStreams.delete(viewName);
|
|
4659
|
+
this.streamScopes.delete(viewName);
|
|
4658
4660
|
}
|
|
4659
4661
|
}, StreamingQueryCache.UNSUBSCRIBE_DELAY_MS);
|
|
4660
4662
|
this.pendingUnsubscribes.set(viewName, timeout);
|
|
@@ -4662,6 +4664,8 @@ class StreamingQueryCache {
|
|
|
4662
4664
|
}
|
|
4663
4665
|
subscribeQuery(descriptor, eventWire, scope) {
|
|
4664
4666
|
const key = descriptor.element;
|
|
4667
|
+
if (scope)
|
|
4668
|
+
this.streamScopes.set(key, scope);
|
|
4665
4669
|
const { unsubscribe } = this.registerStream(key, () => {
|
|
4666
4670
|
const subId = eventWire.subscribeQuery(descriptor, (data) => {
|
|
4667
4671
|
this.setViewData(descriptor.element, data);
|
|
@@ -4670,6 +4674,28 @@ class StreamingQueryCache {
|
|
|
4670
4674
|
});
|
|
4671
4675
|
return unsubscribe;
|
|
4672
4676
|
}
|
|
4677
|
+
invalidateScope(scope) {
|
|
4678
|
+
for (const [viewName, viewScope] of this.streamScopes) {
|
|
4679
|
+
if (viewScope !== scope)
|
|
4680
|
+
continue;
|
|
4681
|
+
const pending = this.pendingUnsubscribes.get(viewName);
|
|
4682
|
+
if (pending) {
|
|
4683
|
+
clearTimeout(pending);
|
|
4684
|
+
this.pendingUnsubscribes.delete(viewName);
|
|
4685
|
+
}
|
|
4686
|
+
const stream = this.activeStreams.get(viewName);
|
|
4687
|
+
if (stream) {
|
|
4688
|
+
try {
|
|
4689
|
+
stream.unsubscribe();
|
|
4690
|
+
} catch {}
|
|
4691
|
+
this.activeStreams.delete(viewName);
|
|
4692
|
+
}
|
|
4693
|
+
this.streamScopes.delete(viewName);
|
|
4694
|
+
const store = this.stores.get(viewName);
|
|
4695
|
+
if (store)
|
|
4696
|
+
store.clear();
|
|
4697
|
+
}
|
|
4698
|
+
}
|
|
4673
4699
|
setViewData(viewName, data) {
|
|
4674
4700
|
const store = this.stores.get(viewName);
|
|
4675
4701
|
if (!store)
|
|
@@ -4717,6 +4743,11 @@ class StreamingQueryCache {
|
|
|
4717
4743
|
stream.unsubscribe();
|
|
4718
4744
|
}
|
|
4719
4745
|
this.activeStreams.clear();
|
|
4746
|
+
this.streamScopes.clear();
|
|
4747
|
+
for (const timeout of this.pendingUnsubscribes.values()) {
|
|
4748
|
+
clearTimeout(timeout);
|
|
4749
|
+
}
|
|
4750
|
+
this.pendingUnsubscribes.clear();
|
|
4720
4751
|
for (const store of this.stores.values()) {
|
|
4721
4752
|
store.clear();
|
|
4722
4753
|
}
|
|
@@ -38,6 +38,15 @@ export declare class StreamingQueryCache {
|
|
|
38
38
|
private views;
|
|
39
39
|
private activeStreams;
|
|
40
40
|
private pendingUnsubscribes;
|
|
41
|
+
/**
|
|
42
|
+
* Tag each active stream with the scope name that subscribed it. Used by
|
|
43
|
+
* `invalidateScope()` to force-close streams when a scope's token changes
|
|
44
|
+
* (workspace switch / re-auth) — without this tag, `registerStream()` would
|
|
45
|
+
* reuse the stale WS subscription (refCount > 0, or within the
|
|
46
|
+
* UNSUBSCRIBE_DELAY_MS grace window) and the client would keep receiving
|
|
47
|
+
* data filtered by the previous token.
|
|
48
|
+
*/
|
|
49
|
+
private streamScopes;
|
|
41
50
|
private static UNSUBSCRIBE_DELAY_MS;
|
|
42
51
|
/**
|
|
43
52
|
* Register views that this cache will handle
|
|
@@ -83,6 +92,23 @@ export declare class StreamingQueryCache {
|
|
|
83
92
|
method: string;
|
|
84
93
|
args: any[];
|
|
85
94
|
}, eventWire: EventWire, scope?: string): () => void;
|
|
95
|
+
/**
|
|
96
|
+
* Force-close every active stream tagged with `scope`. Called when a
|
|
97
|
+
* scope's token changes (workspace switch / re-auth) so the next
|
|
98
|
+
* `subscribeQuery()` creates a fresh WS subscription with the new token
|
|
99
|
+
* instead of reusing the stale one (which would keep pumping data filtered
|
|
100
|
+
* by the previous token until the page reload).
|
|
101
|
+
*
|
|
102
|
+
* Bypasses both `refCount` (other subscribers still mounted) and the
|
|
103
|
+
* UNSUBSCRIBE_DELAY_MS grace window — both became invalid the moment the
|
|
104
|
+
* token changed. React's `useQuery` re-subscribes immediately afterwards
|
|
105
|
+
* via the `subKey` change (token is in the key), getting a fresh stream.
|
|
106
|
+
*
|
|
107
|
+
* Bonus: each affected store is also cleared so any in-progress render
|
|
108
|
+
* that reads `store.find()` between `setToken` and the new WS data
|
|
109
|
+
* arriving gets `[]` rather than stale rows from the previous workspace.
|
|
110
|
+
*/
|
|
111
|
+
invalidateScope(scope: string): void;
|
|
86
112
|
/**
|
|
87
113
|
* Set data for a view. Accepts array or single item (from queryMethod findOne).
|
|
88
114
|
*/
|
package/package.json
CHANGED