@cratis/arc 20.17.1 → 20.17.3
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/Globals.ts +13 -0
- package/dist/cjs/Globals.d.ts +1 -0
- package/dist/cjs/Globals.d.ts.map +1 -1
- package/dist/cjs/Globals.js +1 -0
- package/dist/cjs/Globals.js.map +1 -1
- package/dist/cjs/queries/QueryInstanceCache.d.ts +2 -1
- package/dist/cjs/queries/QueryInstanceCache.d.ts.map +1 -1
- package/dist/cjs/queries/QueryInstanceCache.js +10 -2
- package/dist/cjs/queries/QueryInstanceCache.js.map +1 -1
- package/dist/cjs/queries/ServerSentEventHubConnection.d.ts.map +1 -1
- package/dist/cjs/queries/ServerSentEventHubConnection.js +20 -7
- package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/after_timeout_elapses.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/after_timeout_elapses.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/before_timeout_elapses.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/before_timeout_elapses.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_setting_last_result/with_changed_data.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_setting_last_result/with_changed_data.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_setting_last_result/with_identical_data_as_previous_result.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_setting_last_result/with_identical_data_as_previous_result.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_setting_last_result/without_previous_result.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_setting_last_result/without_previous_result.d.ts.map +1 -0
- package/dist/esm/Globals.d.ts +1 -0
- package/dist/esm/Globals.d.ts.map +1 -1
- package/dist/esm/Globals.js +1 -0
- package/dist/esm/Globals.js.map +1 -1
- package/dist/esm/queries/QueryInstanceCache.d.ts +2 -1
- package/dist/esm/queries/QueryInstanceCache.d.ts.map +1 -1
- package/dist/esm/queries/QueryInstanceCache.js +10 -2
- package/dist/esm/queries/QueryInstanceCache.js.map +1 -1
- package/dist/esm/queries/ServerSentEventHubConnection.d.ts.map +1 -1
- package/dist/esm/queries/ServerSentEventHubConnection.js +20 -7
- package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release.js +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release.js.map +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.js +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.js.map +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.js +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.js.map +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.js +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.js.map +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber.js +14 -3
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber.js.map +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/after_timeout_elapses.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/after_timeout_elapses.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/after_timeout_elapses.js +21 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/after_timeout_elapses.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/before_timeout_elapses.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/before_timeout_elapses.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/{when_acquiring/after_release_in_development_mode.js → when_releasing/with_retention_timeout/before_timeout_elapses.js} +6 -7
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/before_timeout_elapses.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_changed_data.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_changed_data.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_changed_data.js +19 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_changed_data.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_identical_data_as_previous_result.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_identical_data_as_previous_result.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_identical_data_as_previous_result.js +19 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_identical_data_as_previous_result.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/without_previous_result.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/without_previous_result.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/without_previous_result.js +16 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/without_previous_result.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.js +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.js.map +1 -1
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.js +31 -6
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/queries/QueryInstanceCache.ts +21 -9
- package/queries/ServerSentEventHubConnection.ts +28 -7
- package/queries/for_QueryInstanceCache/when_acquiring/after_release.ts +1 -1
- package/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.ts +1 -1
- package/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.ts +1 -1
- package/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.ts +1 -1
- package/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber.ts +16 -3
- package/queries/for_QueryInstanceCache/when_releasing/with_retention_timeout/after_timeout_elapses.ts +28 -0
- package/queries/for_QueryInstanceCache/{when_acquiring/after_release_in_development_mode.ts → when_releasing/with_retention_timeout/before_timeout_elapses.ts} +6 -7
- package/queries/for_QueryInstanceCache/when_setting_last_result/with_changed_data.ts +26 -0
- package/queries/for_QueryInstanceCache/when_setting_last_result/with_identical_data_as_previous_result.ts +27 -0
- package/queries/for_QueryInstanceCache/when_setting_last_result/without_previous_result.ts +22 -0
- package/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.ts +1 -1
- package/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.ts +43 -10
- package/dist/cjs/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts +0 -2
- package/dist/cjs/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts.map +0 -1
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts +0 -2
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts.map +0 -1
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts +0 -2
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts.map +0 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts +0 -2
- package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts.map +0 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.js.map +0 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts +0 -2
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts.map +0 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.js +0 -28
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.js.map +0 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts +0 -2
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts.map +0 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.js +0 -28
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.js.map +0 -1
- package/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.ts +0 -36
- package/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.ts +0 -36
package/package.json
CHANGED
|
@@ -71,13 +71,12 @@ export class QueryInstanceCache {
|
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
73
|
* Initializes a new instance of {@link QueryInstanceCache}.
|
|
74
|
-
* @param
|
|
75
|
-
*
|
|
74
|
+
* @param retentionMs How long in milliseconds to keep a cache entry alive after the last
|
|
75
|
+
* subscriber releases it before evicting the subscription and cached data. A non-zero
|
|
76
|
+
* value lets users navigate away and back without losing cached data. Defaults to
|
|
77
|
+
* 30 000 ms. Pass 0 for immediate eviction.
|
|
76
78
|
*/
|
|
77
|
-
|
|
78
|
-
constructor(development: boolean = false) {
|
|
79
|
-
// The development parameter is kept for API compatibility only.
|
|
80
|
-
// Teardown is always deferred regardless of this flag.
|
|
79
|
+
constructor(private readonly _retentionMs: number = 30_000) {
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
/**
|
|
@@ -170,8 +169,20 @@ export class QueryInstanceCache {
|
|
|
170
169
|
const entry = this._entries.get(key);
|
|
171
170
|
|
|
172
171
|
if (entry) {
|
|
172
|
+
const previousResult = entry.lastResult as QueryResultWithState<TDataType> | undefined;
|
|
173
173
|
entry.lastResult = result as QueryResultWithState<unknown>;
|
|
174
174
|
|
|
175
|
+
// Suppress re-renders when the server re-sends identical data after a reconnect.
|
|
176
|
+
// We only compare `data` and `isSuccess` — other fields (e.g. changeSet) are
|
|
177
|
+
// ephemeral and do not affect what the user sees.
|
|
178
|
+
if (
|
|
179
|
+
previousResult !== undefined &&
|
|
180
|
+
previousResult.isSuccess === result.isSuccess &&
|
|
181
|
+
JSON.stringify(previousResult.data) === JSON.stringify(result.data)
|
|
182
|
+
) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
175
186
|
for (const listener of entry.listeners) {
|
|
176
187
|
(listener as QueryCacheListener<TDataType>)(result);
|
|
177
188
|
}
|
|
@@ -245,8 +256,9 @@ export class QueryInstanceCache {
|
|
|
245
256
|
entry.subscriberCount--;
|
|
246
257
|
|
|
247
258
|
if (entry.subscriberCount <= 0) {
|
|
248
|
-
// Defer both teardown and
|
|
249
|
-
//
|
|
259
|
+
// Defer both teardown and eviction. React StrictMode re-mounts can cancel by
|
|
260
|
+
// calling acquire() before the timeout fires. A non-zero _retentionMs keeps the
|
|
261
|
+
// entry alive so users navigating back quickly see cached data immediately.
|
|
250
262
|
entry.pendingCleanup = setTimeout(() => {
|
|
251
263
|
const current = this._entries.get(key);
|
|
252
264
|
|
|
@@ -257,7 +269,7 @@ export class QueryInstanceCache {
|
|
|
257
269
|
current.pendingCleanup = undefined;
|
|
258
270
|
this._entries.delete(key);
|
|
259
271
|
}
|
|
260
|
-
},
|
|
272
|
+
}, this._retentionMs);
|
|
261
273
|
}
|
|
262
274
|
}
|
|
263
275
|
}
|
|
@@ -300,29 +300,50 @@ export class ServerSentEventHubConnection implements IObservableQueryHubConnecti
|
|
|
300
300
|
sub.callback(QueryResult.unauthorized());
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
-
private sendSubscribe(queryId: string, request: SubscriptionRequest): void {
|
|
304
|
-
if (!this._connectionId) return;
|
|
303
|
+
private sendSubscribe(queryId: string, request: SubscriptionRequest, attempt: number = 0): void {
|
|
304
|
+
if (!this._connectionId || this._disconnected) return;
|
|
305
|
+
|
|
306
|
+
// Capture the connection ID so retries can detect if a reconnect has already fired
|
|
307
|
+
// for a different reason and made this retry obsolete.
|
|
308
|
+
const connectionId = this._connectionId;
|
|
305
309
|
|
|
306
310
|
const body = {
|
|
307
|
-
connectionId
|
|
311
|
+
connectionId,
|
|
308
312
|
queryId,
|
|
309
313
|
request,
|
|
310
314
|
};
|
|
311
315
|
|
|
312
316
|
const customHeaders = Globals.httpHeadersCallback?.() ?? {};
|
|
313
317
|
|
|
318
|
+
// Maximum number of subscribe retries before falling back to a full SSE reconnect.
|
|
319
|
+
// In a round-robin load-balanced deployment the subscribe POST may land on a different
|
|
320
|
+
// backend instance than the one holding the SSE connection. Retrying gives the load
|
|
321
|
+
// balancer the chance to route a subsequent attempt to the correct instance without
|
|
322
|
+
// tearing down the SSE connection unnecessarily. With N backend instances at most
|
|
323
|
+
// N-1 retries are needed, so 3 retries covers deployments with up to 4 replicas.
|
|
324
|
+
const maxRetries = 3;
|
|
325
|
+
const retryDelayMs = 200;
|
|
326
|
+
|
|
314
327
|
fetch(this._subscribeUrl, {
|
|
315
328
|
method: 'POST',
|
|
316
329
|
headers: { 'Content-Type': 'application/json', ...customHeaders },
|
|
317
330
|
body: JSON.stringify(body),
|
|
318
331
|
}).then(response => {
|
|
319
332
|
if (!response.ok) {
|
|
320
|
-
|
|
321
|
-
|
|
333
|
+
if (attempt < maxRetries && this._connectionId === connectionId && !this._disconnected) {
|
|
334
|
+
setTimeout(() => this.sendSubscribe(queryId, request, attempt + 1), retryDelayMs * (attempt + 1));
|
|
335
|
+
} else if (this._connectionId === connectionId && !this._disconnected) {
|
|
336
|
+
console.warn(`SSE hub: subscribe POST for '${queryId}' returned ${response.status} after ${attempt + 1} attempt(s), reconnecting`);
|
|
337
|
+
this.reconnect();
|
|
338
|
+
}
|
|
322
339
|
}
|
|
323
340
|
}).catch(error => {
|
|
324
|
-
|
|
325
|
-
|
|
341
|
+
if (attempt < maxRetries && this._connectionId === connectionId && !this._disconnected) {
|
|
342
|
+
setTimeout(() => this.sendSubscribe(queryId, request, attempt + 1), retryDelayMs * (attempt + 1));
|
|
343
|
+
} else if (this._connectionId === connectionId && !this._disconnected) {
|
|
344
|
+
console.error(`SSE hub: subscribe POST failed for '${queryId}' after ${attempt + 1} attempt(s), reconnecting`, error);
|
|
345
|
+
this.reconnect();
|
|
346
|
+
}
|
|
326
347
|
});
|
|
327
348
|
}
|
|
328
349
|
|
|
@@ -10,7 +10,7 @@ describe('when acquiring after release', () => {
|
|
|
10
10
|
beforeEach(() => {
|
|
11
11
|
vi.useFakeTimers();
|
|
12
12
|
teardownCalled = false;
|
|
13
|
-
cache = new QueryInstanceCache();
|
|
13
|
+
cache = new QueryInstanceCache(0);
|
|
14
14
|
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
15
|
cache.acquire('MyQuery::');
|
|
16
16
|
cache.setTeardown('MyQuery::', () => { teardownCalled = true; });
|
package/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.ts
CHANGED
|
@@ -10,7 +10,7 @@ describe('when canceling deferred dispose before timeout fires', () => {
|
|
|
10
10
|
beforeEach(() => {
|
|
11
11
|
vi.useFakeTimers();
|
|
12
12
|
teardownCalled = false;
|
|
13
|
-
cache = new QueryInstanceCache(
|
|
13
|
+
cache = new QueryInstanceCache(0);
|
|
14
14
|
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
15
|
cache.acquire('MyQuery::');
|
|
16
16
|
cache.setTeardown('MyQuery::', () => { teardownCalled = true; });
|
|
@@ -10,7 +10,7 @@ describe('when deferring dispose without cancellation', () => {
|
|
|
10
10
|
beforeEach(() => {
|
|
11
11
|
vi.useFakeTimers();
|
|
12
12
|
teardownCalled = false;
|
|
13
|
-
cache = new QueryInstanceCache(
|
|
13
|
+
cache = new QueryInstanceCache(0);
|
|
14
14
|
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
15
|
cache.acquire('MyQuery::');
|
|
16
16
|
cache.setTeardown('MyQuery::', () => { teardownCalled = true; });
|
|
@@ -10,7 +10,7 @@ describe('when disposing with pending deferred cleanup', () => {
|
|
|
10
10
|
beforeEach(() => {
|
|
11
11
|
vi.useFakeTimers();
|
|
12
12
|
teardownCalled = 0;
|
|
13
|
-
cache = new QueryInstanceCache(
|
|
13
|
+
cache = new QueryInstanceCache(0);
|
|
14
14
|
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
15
|
cache.acquire('MyQuery::');
|
|
16
16
|
cache.setTeardown('MyQuery::', () => { teardownCalled++; });
|
|
@@ -5,19 +5,32 @@ import { QueryInstanceCache } from '../../QueryInstanceCache';
|
|
|
5
5
|
|
|
6
6
|
describe('when releasing the only subscriber', () => {
|
|
7
7
|
let cache: QueryInstanceCache;
|
|
8
|
+
let teardownCalled: boolean;
|
|
8
9
|
|
|
9
10
|
beforeEach(() => {
|
|
10
11
|
vi.useFakeTimers();
|
|
11
|
-
|
|
12
|
+
teardownCalled = false;
|
|
13
|
+
cache = new QueryInstanceCache(0);
|
|
12
14
|
cache.getOrCreate('MyQuery::', () => ({}));
|
|
13
15
|
cache.acquire('MyQuery::');
|
|
16
|
+
cache.setTeardown('MyQuery::', () => { teardownCalled = true; });
|
|
14
17
|
cache.release('MyQuery::');
|
|
15
|
-
vi.advanceTimersByTime(0);
|
|
16
18
|
});
|
|
17
19
|
|
|
18
20
|
afterEach(() => {
|
|
19
21
|
vi.useRealTimers();
|
|
20
22
|
});
|
|
21
23
|
|
|
22
|
-
it('should
|
|
24
|
+
it('should not call teardown synchronously', () => teardownCalled.should.be.false);
|
|
25
|
+
it('should keep the entry before the timer fires', () => cache.has('MyQuery::').should.be.true);
|
|
26
|
+
it('should still report as subscribed before the timer fires', () => cache.isSubscribed('MyQuery::').should.be.true);
|
|
27
|
+
|
|
28
|
+
describe('and the deferred timer fires', () => {
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
vi.advanceTimersByTime(0);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should call teardown', () => teardownCalled.should.be.true);
|
|
34
|
+
it('should evict the entry', () => cache.has('MyQuery::').should.be.false);
|
|
35
|
+
});
|
|
23
36
|
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { QueryInstanceCache } from '../../../QueryInstanceCache';
|
|
5
|
+
|
|
6
|
+
describe('when releasing the only subscriber with a retention timeout, after the timeout elapses', () => {
|
|
7
|
+
let cache: QueryInstanceCache;
|
|
8
|
+
let teardownCalled: boolean;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
vi.useFakeTimers();
|
|
12
|
+
teardownCalled = false;
|
|
13
|
+
cache = new QueryInstanceCache(5000);
|
|
14
|
+
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
|
+
cache.acquire('MyQuery::');
|
|
16
|
+
cache.setTeardown('MyQuery::', () => { teardownCalled = true; });
|
|
17
|
+
cache.release('MyQuery::');
|
|
18
|
+
|
|
19
|
+
vi.advanceTimersByTime(5000);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
vi.useRealTimers();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should call teardown', () => teardownCalled.should.be.true);
|
|
27
|
+
it('should evict the entry from the cache', () => cache.has('MyQuery::').should.be.false);
|
|
28
|
+
});
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
// Copyright (c) Cratis. All rights reserved.
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
|
-
import { QueryInstanceCache } from '
|
|
4
|
+
import { QueryInstanceCache } from '../../../QueryInstanceCache';
|
|
5
5
|
|
|
6
|
-
describe('when
|
|
6
|
+
describe('when releasing the only subscriber with a retention timeout, before the timeout elapses', () => {
|
|
7
7
|
let cache: QueryInstanceCache;
|
|
8
8
|
let teardownCalled: boolean;
|
|
9
9
|
|
|
10
10
|
beforeEach(() => {
|
|
11
11
|
vi.useFakeTimers();
|
|
12
12
|
teardownCalled = false;
|
|
13
|
-
cache = new QueryInstanceCache(
|
|
13
|
+
cache = new QueryInstanceCache(5000);
|
|
14
14
|
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
15
|
cache.acquire('MyQuery::');
|
|
16
16
|
cache.setTeardown('MyQuery::', () => { teardownCalled = true; });
|
|
17
17
|
cache.release('MyQuery::');
|
|
18
18
|
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
vi.advanceTimersByTime(0);
|
|
19
|
+
// Advance to just before the retention window expires.
|
|
20
|
+
vi.advanceTimersByTime(4999);
|
|
22
21
|
});
|
|
23
22
|
|
|
24
23
|
afterEach(() => {
|
|
@@ -26,6 +25,6 @@ describe('when acquiring after release in development mode', () => {
|
|
|
26
25
|
});
|
|
27
26
|
|
|
28
27
|
it('should not call teardown', () => teardownCalled.should.be.false);
|
|
29
|
-
it('should keep the entry', () => cache.has('MyQuery::').should.be.true);
|
|
28
|
+
it('should keep the entry in the cache', () => cache.has('MyQuery::').should.be.true);
|
|
30
29
|
it('should still report as subscribed', () => cache.isSubscribed('MyQuery::').should.be.true);
|
|
31
30
|
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { QueryInstanceCache } from '../../QueryInstanceCache';
|
|
5
|
+
import { QueryResultWithState } from '../../QueryResultWithState';
|
|
6
|
+
|
|
7
|
+
describe('when setting the last result with changed data', () => {
|
|
8
|
+
let cache: QueryInstanceCache;
|
|
9
|
+
let listenerCallCount: number;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
listenerCallCount = 0;
|
|
13
|
+
cache = new QueryInstanceCache();
|
|
14
|
+
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
|
+
cache.addListener<string[]>('MyQuery::', () => listenerCallCount++);
|
|
16
|
+
|
|
17
|
+
const first = QueryResultWithState.empty<string[]>(['a', 'b']);
|
|
18
|
+
cache.setLastResult('MyQuery::', first);
|
|
19
|
+
listenerCallCount = 0; // reset after initial push
|
|
20
|
+
|
|
21
|
+
const second = QueryResultWithState.empty<string[]>(['a', 'b', 'c']);
|
|
22
|
+
cache.setLastResult('MyQuery::', second);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should notify listeners', () => listenerCallCount.should.equal(1));
|
|
26
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { QueryInstanceCache } from '../../QueryInstanceCache';
|
|
5
|
+
import { QueryResultWithState } from '../../QueryResultWithState';
|
|
6
|
+
|
|
7
|
+
describe('when setting the last result with identical data as the previous result', () => {
|
|
8
|
+
let cache: QueryInstanceCache;
|
|
9
|
+
let listenerCallCount: number;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
listenerCallCount = 0;
|
|
13
|
+
cache = new QueryInstanceCache();
|
|
14
|
+
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
|
+
cache.addListener<string[]>('MyQuery::', () => listenerCallCount++);
|
|
16
|
+
|
|
17
|
+
const first = QueryResultWithState.empty<string[]>(['a', 'b']);
|
|
18
|
+
cache.setLastResult('MyQuery::', first);
|
|
19
|
+
listenerCallCount = 0; // reset after initial push
|
|
20
|
+
|
|
21
|
+
// Second push with data that serializes identically
|
|
22
|
+
const second = QueryResultWithState.empty<string[]>(['a', 'b']);
|
|
23
|
+
cache.setLastResult('MyQuery::', second);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should not notify listeners', () => listenerCallCount.should.equal(0));
|
|
27
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { QueryInstanceCache } from '../../QueryInstanceCache';
|
|
5
|
+
import { QueryResultWithState } from '../../QueryResultWithState';
|
|
6
|
+
|
|
7
|
+
describe('when setting the last result without a previous result', () => {
|
|
8
|
+
let cache: QueryInstanceCache;
|
|
9
|
+
let listenerCallCount: number;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
listenerCallCount = 0;
|
|
13
|
+
cache = new QueryInstanceCache();
|
|
14
|
+
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
|
+
cache.addListener<string[]>('MyQuery::', () => listenerCallCount++);
|
|
16
|
+
|
|
17
|
+
const result = QueryResultWithState.empty<string[]>(['a', 'b']);
|
|
18
|
+
cache.setLastResult('MyQuery::', result);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should notify listeners', () => listenerCallCount.should.equal(1));
|
|
22
|
+
});
|
|
@@ -10,7 +10,7 @@ describe('when tearing down all subscriptions with pending deferred cleanup', ()
|
|
|
10
10
|
beforeEach(() => {
|
|
11
11
|
vi.useFakeTimers();
|
|
12
12
|
teardownCalled = false;
|
|
13
|
-
cache = new QueryInstanceCache(
|
|
13
|
+
cache = new QueryInstanceCache(0);
|
|
14
14
|
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
15
|
cache.acquire('MyQuery::');
|
|
16
16
|
cache.setTeardown('MyQuery::', () => { teardownCalled = true; });
|
package/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.ts
CHANGED
|
@@ -6,46 +6,79 @@ import { a_server_sent_event_hub_connection } from '../given/a_server_sent_event
|
|
|
6
6
|
import { given } from '../../../given';
|
|
7
7
|
import { HubMessageType } from '../../WebSocketHubConnection';
|
|
8
8
|
|
|
9
|
+
async function exhaustRetries(clock: sinon.SinonFakeTimers): Promise<void> {
|
|
10
|
+
// Three retry delays: 200 ms (attempt 1), 400 ms (attempt 2), 600 ms (attempt 3).
|
|
11
|
+
// Two microtask flushes are needed per tick: the first lets a rejected fetch propagate
|
|
12
|
+
// through the .then() step (which passes it forward), and the second lets .catch() fire
|
|
13
|
+
// and schedule the next setTimeout. For resolved-but-not-ok responses a single flush
|
|
14
|
+
// is enough, but two is harmless.
|
|
15
|
+
for (const delay of [200, 400, 600]) {
|
|
16
|
+
clock.tick(delay);
|
|
17
|
+
await Promise.resolve();
|
|
18
|
+
await Promise.resolve();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
9
22
|
describe('when subscribe POST returns a non-OK status', given(a_server_sent_event_hub_connection, context => {
|
|
23
|
+
let clock: sinon.SinonFakeTimers;
|
|
24
|
+
|
|
10
25
|
beforeEach(async () => {
|
|
11
26
|
context.setup();
|
|
27
|
+
clock = sinon.useFakeTimers({ toFake: ['setTimeout'] });
|
|
12
28
|
|
|
13
|
-
// Make the subscribe POST resolve with a 404 (connection not found on server).
|
|
14
29
|
context.fetchStub.resolves({ ok: false, status: 404 });
|
|
15
30
|
|
|
16
31
|
context.connection.subscribe('q1', { queryName: 'MyQuery' }, sinon.stub());
|
|
17
32
|
context.simulateOpen();
|
|
18
33
|
context.simulateMessage({ type: HubMessageType.Connected, payload: 'conn-abc' });
|
|
19
34
|
|
|
20
|
-
//
|
|
21
|
-
await
|
|
35
|
+
// Flush the initial fetch promise chain.
|
|
36
|
+
await Promise.resolve();
|
|
22
37
|
});
|
|
23
38
|
|
|
24
|
-
afterEach(() =>
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
clock.restore();
|
|
41
|
+
sinon.restore();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should not immediately reconnect before retries are exhausted', () => {
|
|
45
|
+
(context.policy.schedule as sinon.SinonStub).called.should.be.false;
|
|
46
|
+
});
|
|
25
47
|
|
|
26
|
-
it('should schedule a reconnect via the policy', () => {
|
|
48
|
+
it('should schedule a reconnect via the policy after exhausting all retries', async () => {
|
|
49
|
+
await exhaustRetries(clock);
|
|
27
50
|
(context.policy.schedule as sinon.SinonStub).calledOnce.should.be.true;
|
|
28
51
|
});
|
|
29
52
|
}));
|
|
30
53
|
|
|
31
54
|
describe('when subscribe POST rejects with a network error', given(a_server_sent_event_hub_connection, context => {
|
|
55
|
+
let clock: sinon.SinonFakeTimers;
|
|
56
|
+
|
|
32
57
|
beforeEach(async () => {
|
|
33
58
|
context.setup();
|
|
59
|
+
clock = sinon.useFakeTimers({ toFake: ['setTimeout'] });
|
|
34
60
|
|
|
35
|
-
// Make the subscribe POST reject (network failure).
|
|
36
61
|
context.fetchStub.rejects(new Error('Network error'));
|
|
37
62
|
|
|
38
63
|
context.connection.subscribe('q1', { queryName: 'MyQuery' }, sinon.stub());
|
|
39
64
|
context.simulateOpen();
|
|
40
65
|
context.simulateMessage({ type: HubMessageType.Connected, payload: 'conn-abc' });
|
|
41
66
|
|
|
42
|
-
//
|
|
43
|
-
await
|
|
67
|
+
// Flush the initial fetch promise chain.
|
|
68
|
+
await Promise.resolve();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
afterEach(() => {
|
|
72
|
+
clock.restore();
|
|
73
|
+
sinon.restore();
|
|
44
74
|
});
|
|
45
75
|
|
|
46
|
-
|
|
76
|
+
it('should not immediately reconnect before retries are exhausted', () => {
|
|
77
|
+
(context.policy.schedule as sinon.SinonStub).called.should.be.false;
|
|
78
|
+
});
|
|
47
79
|
|
|
48
|
-
it('should schedule a reconnect via the policy', () => {
|
|
80
|
+
it('should schedule a reconnect via the policy after exhausting all retries', async () => {
|
|
81
|
+
await exhaustRetries(clock);
|
|
49
82
|
(context.policy.schedule as sinon.SinonStub).calledOnce.should.be.true;
|
|
50
83
|
});
|
|
51
84
|
}));
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"after_release_in_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"the_only_subscriber_in_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"the_only_subscriber_outside_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"after_release_in_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"after_release_in_development_mode.js","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,QAAQ,CAAC,kDAAkD,EAAE,GAAG,EAAE;IAC9D,IAAI,KAAyB,CAAC;IAC9B,IAAI,cAAuB,CAAC;IAE5B,UAAU,CAAC,GAAG,EAAE;QACZ,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,cAAc,GAAG,KAAK,CAAC;QACvB,KAAK,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACrC,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC3B,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,cAAc,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAG3B,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC3B,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACX,EAAE,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACrE,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACzE,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;AAClG,CAAC,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"the_only_subscriber_in_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.ts"],"names":[],"mappings":""}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { QueryInstanceCache } from '../../QueryInstanceCache';
|
|
2
|
-
describe('when releasing the only subscriber in development mode', () => {
|
|
3
|
-
let cache;
|
|
4
|
-
let teardownCalled;
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
vi.useFakeTimers();
|
|
7
|
-
teardownCalled = false;
|
|
8
|
-
cache = new QueryInstanceCache(true);
|
|
9
|
-
cache.getOrCreate('MyQuery::', () => ({}));
|
|
10
|
-
cache.acquire('MyQuery::');
|
|
11
|
-
cache.setTeardown('MyQuery::', () => { teardownCalled = true; });
|
|
12
|
-
cache.release('MyQuery::');
|
|
13
|
-
});
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
vi.useRealTimers();
|
|
16
|
-
});
|
|
17
|
-
it('should not call teardown synchronously', () => teardownCalled.should.be.false);
|
|
18
|
-
it('should keep the entry before the timer fires', () => cache.has('MyQuery::').should.be.true);
|
|
19
|
-
it('should still report as subscribed before the timer fires', () => cache.isSubscribed('MyQuery::').should.be.true);
|
|
20
|
-
describe('and the deferred timer fires', () => {
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
vi.advanceTimersByTime(0);
|
|
23
|
-
});
|
|
24
|
-
it('should call teardown', () => teardownCalled.should.be.true);
|
|
25
|
-
it('should evict the entry', () => cache.has('MyQuery::').should.be.false);
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
//# sourceMappingURL=the_only_subscriber_in_development_mode.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"the_only_subscriber_in_development_mode.js","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,QAAQ,CAAC,wDAAwD,EAAE,GAAG,EAAE;IACpE,IAAI,KAAyB,CAAC;IAC9B,IAAI,cAAuB,CAAC;IAE5B,UAAU,CAAC,GAAG,EAAE;QACZ,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,cAAc,GAAG,KAAK,CAAC;QACvB,KAAK,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACrC,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC3B,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,cAAc,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACX,EAAE,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACnF,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAChG,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAErH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC1C,UAAU,CAAC,GAAG,EAAE;YACZ,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAChE,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"the_only_subscriber_outside_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.ts"],"names":[],"mappings":""}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { QueryInstanceCache } from '../../QueryInstanceCache';
|
|
2
|
-
describe('when releasing the only subscriber outside development mode', () => {
|
|
3
|
-
let cache;
|
|
4
|
-
let teardownCalled;
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
vi.useFakeTimers();
|
|
7
|
-
teardownCalled = false;
|
|
8
|
-
cache = new QueryInstanceCache(false);
|
|
9
|
-
cache.getOrCreate('MyQuery::', () => ({}));
|
|
10
|
-
cache.acquire('MyQuery::');
|
|
11
|
-
cache.setTeardown('MyQuery::', () => { teardownCalled = true; });
|
|
12
|
-
cache.release('MyQuery::');
|
|
13
|
-
});
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
vi.useRealTimers();
|
|
16
|
-
});
|
|
17
|
-
it('should not call teardown synchronously', () => teardownCalled.should.be.false);
|
|
18
|
-
it('should keep the entry before the timer fires', () => cache.has('MyQuery::').should.be.true);
|
|
19
|
-
it('should still report as subscribed before the timer fires', () => cache.isSubscribed('MyQuery::').should.be.true);
|
|
20
|
-
describe('and the deferred timer fires', () => {
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
vi.advanceTimersByTime(0);
|
|
23
|
-
});
|
|
24
|
-
it('should call teardown', () => teardownCalled.should.be.true);
|
|
25
|
-
it('should evict the entry', () => cache.has('MyQuery::').should.be.false);
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
//# sourceMappingURL=the_only_subscriber_outside_development_mode.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"the_only_subscriber_outside_development_mode.js","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,QAAQ,CAAC,6DAA6D,EAAE,GAAG,EAAE;IACzE,IAAI,KAAyB,CAAC;IAC9B,IAAI,cAAuB,CAAC;IAE5B,UAAU,CAAC,GAAG,EAAE;QACZ,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,cAAc,GAAG,KAAK,CAAC;QACvB,KAAK,GAAG,IAAI,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACtC,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC3B,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,cAAc,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACX,EAAE,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACnF,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAChG,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAErH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC1C,UAAU,CAAC,GAAG,EAAE;YACZ,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAChE,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
package/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
-
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
-
|
|
4
|
-
import { QueryInstanceCache } from '../../QueryInstanceCache';
|
|
5
|
-
|
|
6
|
-
describe('when releasing the only subscriber in development mode', () => {
|
|
7
|
-
let cache: QueryInstanceCache;
|
|
8
|
-
let teardownCalled: boolean;
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
vi.useFakeTimers();
|
|
12
|
-
teardownCalled = false;
|
|
13
|
-
cache = new QueryInstanceCache(true);
|
|
14
|
-
cache.getOrCreate('MyQuery::', () => ({}));
|
|
15
|
-
cache.acquire('MyQuery::');
|
|
16
|
-
cache.setTeardown('MyQuery::', () => { teardownCalled = true; });
|
|
17
|
-
cache.release('MyQuery::');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
afterEach(() => {
|
|
21
|
-
vi.useRealTimers();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should not call teardown synchronously', () => teardownCalled.should.be.false);
|
|
25
|
-
it('should keep the entry before the timer fires', () => cache.has('MyQuery::').should.be.true);
|
|
26
|
-
it('should still report as subscribed before the timer fires', () => cache.isSubscribed('MyQuery::').should.be.true);
|
|
27
|
-
|
|
28
|
-
describe('and the deferred timer fires', () => {
|
|
29
|
-
beforeEach(() => {
|
|
30
|
-
vi.advanceTimersByTime(0);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should call teardown', () => teardownCalled.should.be.true);
|
|
34
|
-
it('should evict the entry', () => cache.has('MyQuery::').should.be.false);
|
|
35
|
-
});
|
|
36
|
-
});
|