@stream-io/feeds-client 0.2.18 → 0.2.20
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/CHANGELOG.md +23 -0
- package/dist/cjs/index.js +94 -25
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react-bindings.js +26 -55
- package/dist/cjs/react-bindings.js.map +1 -1
- package/dist/es/index.mjs +86 -17
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/react-bindings.mjs +19 -48
- package/dist/es/react-bindings.mjs.map +1 -1
- package/dist/{index-Zde8UE5f.mjs → feeds-client-BObWT4vl.mjs} +191 -92
- package/dist/feeds-client-BObWT4vl.mjs.map +1 -0
- package/dist/{index--koeDtxd.js → feeds-client-BlR_3zy2.js} +178 -79
- package/dist/feeds-client-BlR_3zy2.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.d.ts +2 -32
- package/dist/types/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.d.ts.map +1 -1
- package/dist/types/common/real-time/event-models.d.ts +7 -2
- package/dist/types/common/real-time/event-models.d.ts.map +1 -1
- package/dist/types/common/types.d.ts +1 -0
- package/dist/types/common/types.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/activity/handle-activity-added.d.ts.map +1 -1
- package/dist/types/feed/event-handlers/activity/handle-activity-updated.d.ts.map +1 -1
- package/dist/types/feed/feed.d.ts +1 -1
- package/dist/types/feed/feed.d.ts.map +1 -1
- package/dist/types/feeds-client/feeds-client.d.ts +9 -1
- package/dist/types/feeds-client/feeds-client.d.ts.map +1 -1
- package/dist/types/utils/throttling/index.d.ts +3 -0
- package/dist/types/utils/throttling/index.d.ts.map +1 -0
- package/dist/types/utils/throttling/throttle.d.ts +34 -0
- package/dist/types/utils/throttling/throttle.d.ts.map +1 -0
- package/dist/types/utils/throttling/throttled-get-batched-own-capabilities.d.ts +14 -0
- package/dist/types/utils/throttling/throttled-get-batched-own-capabilities.d.ts.map +1 -0
- package/package.json +7 -3
- package/react-bindings.d.ts +11 -0
- package/react-bindings.js +7 -0
- package/react-bindings.mjs +11 -0
- package/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts +21 -73
- package/src/common/real-time/event-models.ts +8 -2
- package/src/common/types.ts +1 -0
- package/src/feed/event-handlers/activity/handle-activity-added.ts +9 -1
- package/src/feed/event-handlers/activity/handle-activity-updated.ts +4 -0
- package/src/feed/feed.ts +18 -3
- package/src/feeds-client/feeds-client.ts +106 -3
- package/src/utils/throttling/index.ts +2 -0
- package/src/utils/throttling/throttle.ts +123 -0
- package/src/utils/throttling/throttled-get-batched-own-capabilities.ts +44 -0
- package/dist/index--koeDtxd.js.map +0 -1
- package/dist/index-Zde8UE5f.mjs.map +0 -1
- package/src/feed/event-handlers/activity/activity-marked-utils.test.ts +0 -208
- package/src/feed/event-handlers/activity/activity-reaction-utils.test.ts +0 -371
- package/src/feed/event-handlers/activity/handle-activity-added.test.ts +0 -97
- package/src/feed/event-handlers/activity/handle-activity-deleted.test.ts +0 -117
- package/src/feed/event-handlers/activity/handle-activity-pinned.test.ts +0 -60
- package/src/feed/event-handlers/activity/handle-activity-reaction-added.test.ts +0 -257
- package/src/feed/event-handlers/activity/handle-activity-reaction-deleted.test.ts +0 -317
- package/src/feed/event-handlers/activity/handle-activity-reaction-updated.test.ts +0 -282
- package/src/feed/event-handlers/activity/handle-activity-unpinned.test.ts +0 -95
- package/src/feed/event-handlers/activity/handle-activity-updated.test.ts +0 -245
- package/src/feed/event-handlers/add-aggregated-activities-to-state.test.ts +0 -510
- package/src/feed/event-handlers/bookmark/bookmark-utils.test.ts +0 -521
- package/src/feed/event-handlers/bookmark/handle-bookmark-added.test.ts +0 -178
- package/src/feed/event-handlers/bookmark/handle-bookmark-deleted.test.ts +0 -188
- package/src/feed/event-handlers/bookmark/handle-bookmark-updated.test.ts +0 -196
- package/src/feed/event-handlers/comment/handle-comment-added.test.ts +0 -271
- package/src/feed/event-handlers/comment/handle-comment-deleted.test.ts +0 -255
- package/src/feed/event-handlers/comment/handle-comment-reaction-added.test.ts +0 -329
- package/src/feed/event-handlers/comment/handle-comment-reaction-deleted.test.ts +0 -343
- package/src/feed/event-handlers/comment/handle-comment-reaction-updated.test.ts +0 -350
- package/src/feed/event-handlers/comment/handle-comment-updated.test.ts +0 -267
- package/src/feed/event-handlers/comment/utils/update-comment-count.test.ts +0 -322
- package/src/feed/event-handlers/feed-member/handle-feed-member-added.test.ts +0 -75
- package/src/feed/event-handlers/feed-member/handle-feed-member-removed.test.ts +0 -82
- package/src/feed/event-handlers/feed-member/handle-feed-member-updated.test.ts +0 -84
- package/src/feed/event-handlers/follow/follow-state-update-queue.test.ts +0 -219
- package/src/feed/event-handlers/follow/handle-follow-created.test.ts +0 -250
- package/src/feed/event-handlers/follow/handle-follow-deleted.test.ts +0 -268
- package/src/feed/event-handlers/follow/handle-follow-updated.test.ts +0 -131
- package/src/feed/event-handlers/notification-feed/handle-notification-feed-updated.test.ts +0 -182
- package/src/feed/event-handlers/story-feeds/handle-story-feeds-updated.test.ts +0 -45
- package/src/feed/feed.test.ts +0 -90
- package/src/feeds-client/event-handlers/user/handle-user-updated.test.ts +0 -53
- package/src/utils/event-triggered-by-connected-user.test.ts +0 -73
- package/src/utils/state-update-queue.test.ts +0 -129
- package/src/utils/unique-array-merge.test.ts +0 -179
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
FollowBatchRequest,
|
|
15
15
|
FollowRequest,
|
|
16
16
|
ImageUploadRequest,
|
|
17
|
+
OwnCapabilitiesBatchRequest,
|
|
17
18
|
OwnUser,
|
|
18
19
|
PollResponse,
|
|
19
20
|
PollVotesResponse,
|
|
@@ -66,15 +67,26 @@ import {
|
|
|
66
67
|
handleWatchStopped,
|
|
67
68
|
} from '../feed';
|
|
68
69
|
import { handleUserUpdated } from './event-handlers';
|
|
69
|
-
import
|
|
70
|
-
|
|
70
|
+
import {
|
|
71
|
+
type SyncFailure,
|
|
72
|
+
UnhandledErrorType,
|
|
73
|
+
} from '../common/real-time/event-models';
|
|
71
74
|
import { updateCommentCount } from '../feed/event-handlers/comment/utils';
|
|
72
75
|
import { configureLoggers } from '../utils';
|
|
73
76
|
import { handleCommentReactionUpdated } from '../feed/event-handlers/comment/handle-comment-reaction-updated';
|
|
77
|
+
import {
|
|
78
|
+
throttle,
|
|
79
|
+
DEFAULT_BATCH_OWN_CAPABILITIES_THROTTLING_INTERVAL,
|
|
80
|
+
type GetBatchedOwnCapabilitiesThrottledCallback,
|
|
81
|
+
queueBatchedOwnCapabilities,
|
|
82
|
+
type ThrottledGetBatchedOwnCapabilities,
|
|
83
|
+
clearQueuedFeeds,
|
|
84
|
+
} from '../utils/throttling';
|
|
74
85
|
|
|
75
86
|
export type FeedsClientState = {
|
|
76
87
|
connected_user: OwnUser | undefined;
|
|
77
88
|
is_ws_connection_healthy: boolean;
|
|
89
|
+
own_capabilities_by_fid: Record<string, FeedResponse['own_capabilities']>;
|
|
78
90
|
};
|
|
79
91
|
|
|
80
92
|
type FID = string;
|
|
@@ -97,6 +109,10 @@ export class FeedsClient extends FeedsApi {
|
|
|
97
109
|
|
|
98
110
|
private healthyConnectionChangedEventCount = 0;
|
|
99
111
|
|
|
112
|
+
protected throttledGetBatchOwnCapabilities!: ThrottledGetBatchedOwnCapabilities;
|
|
113
|
+
private cancelGetBatchOwnCapabilitiesTimer!: () => void;
|
|
114
|
+
private query_batch_own_capabilties_throttling_interval!: number;
|
|
115
|
+
|
|
100
116
|
constructor(apiKey: string, options?: FeedsClientOptions) {
|
|
101
117
|
const tokenManager = new TokenManager();
|
|
102
118
|
const connectionIdManager = new ConnectionIdManager();
|
|
@@ -110,12 +126,17 @@ export class FeedsClient extends FeedsApi {
|
|
|
110
126
|
this.state = new StateStore<FeedsClientState>({
|
|
111
127
|
connected_user: undefined,
|
|
112
128
|
is_ws_connection_healthy: false,
|
|
129
|
+
own_capabilities_by_fid: {},
|
|
113
130
|
});
|
|
114
131
|
this.moderation = new ModerationClient(apiClient);
|
|
115
132
|
this.tokenManager = tokenManager;
|
|
116
133
|
this.connectionIdManager = connectionIdManager;
|
|
117
134
|
this.polls_by_id = new Map();
|
|
118
135
|
|
|
136
|
+
this.query_batch_own_capabilties_throttling_interval =
|
|
137
|
+
options?.query_batch_own_capabilties_throttling_interval ??
|
|
138
|
+
DEFAULT_BATCH_OWN_CAPABILITIES_THROTTLING_INTERVAL;
|
|
139
|
+
|
|
119
140
|
configureLoggers(options?.configure_loggers_options);
|
|
120
141
|
|
|
121
142
|
this.on('all', (event) => {
|
|
@@ -231,6 +252,32 @@ export class FeedsClient extends FeedsApi {
|
|
|
231
252
|
});
|
|
232
253
|
}
|
|
233
254
|
|
|
255
|
+
private setGetBatchOwnCapabilitiesThrottlingInterval = (
|
|
256
|
+
throttlingMs: number,
|
|
257
|
+
) => {
|
|
258
|
+
const {
|
|
259
|
+
throttledFn: throttledGetBatchOwnCapabilities,
|
|
260
|
+
cancelTimer: cancel,
|
|
261
|
+
} = throttle<GetBatchedOwnCapabilitiesThrottledCallback>(
|
|
262
|
+
(feeds, callback) => {
|
|
263
|
+
this.ownCapabilitiesBatch({
|
|
264
|
+
feeds,
|
|
265
|
+
}).catch((error) => {
|
|
266
|
+
this.eventDispatcher.dispatch({
|
|
267
|
+
type: 'errors.unhandled',
|
|
268
|
+
error_type: UnhandledErrorType.FetchingOwnCapabilitiesOnNewActivity,
|
|
269
|
+
error,
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
callback(feeds);
|
|
273
|
+
},
|
|
274
|
+
throttlingMs,
|
|
275
|
+
{ trailing: true },
|
|
276
|
+
);
|
|
277
|
+
this.throttledGetBatchOwnCapabilities = throttledGetBatchOwnCapabilities;
|
|
278
|
+
this.cancelGetBatchOwnCapabilitiesTimer = cancel;
|
|
279
|
+
};
|
|
280
|
+
|
|
234
281
|
private recoverOnReconnect = async () => {
|
|
235
282
|
this.healthyConnectionChangedEventCount++;
|
|
236
283
|
|
|
@@ -276,6 +323,34 @@ export class FeedsClient extends FeedsApi {
|
|
|
276
323
|
}
|
|
277
324
|
}
|
|
278
325
|
|
|
326
|
+
public hydrateCapabilitiesCache(
|
|
327
|
+
feedResponses: Array<Pick<FeedResponse, 'feed' | 'own_capabilities'>>,
|
|
328
|
+
) {
|
|
329
|
+
let ownCapabilitiesCache =
|
|
330
|
+
this.state.getLatestValue().own_capabilities_by_fid;
|
|
331
|
+
|
|
332
|
+
const capabilitiesToFetchQueue: string[] = [];
|
|
333
|
+
|
|
334
|
+
for (const feedResponse of feedResponses) {
|
|
335
|
+
const { feed, own_capabilities } = feedResponse;
|
|
336
|
+
|
|
337
|
+
if (!Object.prototype.hasOwnProperty.call(ownCapabilitiesCache, feed)) {
|
|
338
|
+
if (own_capabilities) {
|
|
339
|
+
ownCapabilitiesCache = {
|
|
340
|
+
...ownCapabilitiesCache,
|
|
341
|
+
[feed]: own_capabilities,
|
|
342
|
+
};
|
|
343
|
+
} else {
|
|
344
|
+
capabilitiesToFetchQueue.push(feed);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
queueBatchedOwnCapabilities.bind(this)({ feeds: capabilitiesToFetchQueue });
|
|
350
|
+
|
|
351
|
+
this.state.partialNext({ own_capabilities_by_fid: ownCapabilitiesCache });
|
|
352
|
+
}
|
|
353
|
+
|
|
279
354
|
connectUser = async (user: UserRequest, tokenProvider: TokenOrProvider) => {
|
|
280
355
|
if (
|
|
281
356
|
this.state.getLatestValue().connected_user !== undefined ||
|
|
@@ -286,6 +361,10 @@ export class FeedsClient extends FeedsApi {
|
|
|
286
361
|
|
|
287
362
|
this.tokenManager.setTokenOrProvider(tokenProvider);
|
|
288
363
|
|
|
364
|
+
this.setGetBatchOwnCapabilitiesThrottlingInterval(
|
|
365
|
+
this.query_batch_own_capabilties_throttling_interval,
|
|
366
|
+
);
|
|
367
|
+
|
|
289
368
|
try {
|
|
290
369
|
addConnectionEventListeners(this.updateNetworkConnectionStatus);
|
|
291
370
|
this.wsConnection = new StableWSConnection(
|
|
@@ -516,10 +595,18 @@ export class FeedsClient extends FeedsApi {
|
|
|
516
595
|
|
|
517
596
|
this.connectionIdManager.reset();
|
|
518
597
|
this.tokenManager.reset();
|
|
598
|
+
|
|
599
|
+
// clear all caches
|
|
600
|
+
this.polls_by_id.clear();
|
|
601
|
+
|
|
519
602
|
this.state.partialNext({
|
|
520
603
|
connected_user: undefined,
|
|
521
604
|
is_ws_connection_healthy: false,
|
|
605
|
+
own_capabilities_by_fid: {},
|
|
522
606
|
});
|
|
607
|
+
|
|
608
|
+
this.cancelGetBatchOwnCapabilitiesTimer();
|
|
609
|
+
clearQueuedFeeds();
|
|
523
610
|
};
|
|
524
611
|
|
|
525
612
|
on = this.eventDispatcher.on;
|
|
@@ -542,7 +629,9 @@ export class FeedsClient extends FeedsApi {
|
|
|
542
629
|
async queryFeeds(request?: QueryFeedsRequest) {
|
|
543
630
|
const response = await this._queryFeeds(request);
|
|
544
631
|
|
|
545
|
-
const
|
|
632
|
+
const feedResponses = response.feeds;
|
|
633
|
+
|
|
634
|
+
const feeds = feedResponses.map((feedResponse) =>
|
|
546
635
|
this.getOrCreateActiveFeed(
|
|
547
636
|
feedResponse.group_id,
|
|
548
637
|
feedResponse.id,
|
|
@@ -551,6 +640,8 @@ export class FeedsClient extends FeedsApi {
|
|
|
551
640
|
),
|
|
552
641
|
);
|
|
553
642
|
|
|
643
|
+
this.hydrateCapabilitiesCache(feedResponses);
|
|
644
|
+
|
|
554
645
|
return {
|
|
555
646
|
feeds,
|
|
556
647
|
next: response.next,
|
|
@@ -560,6 +651,18 @@ export class FeedsClient extends FeedsApi {
|
|
|
560
651
|
};
|
|
561
652
|
}
|
|
562
653
|
|
|
654
|
+
async ownCapabilitiesBatch(request: OwnCapabilitiesBatchRequest) {
|
|
655
|
+
const response = await super.ownCapabilitiesBatch(request);
|
|
656
|
+
const feedResponses = Object.entries(response.capabilities).map(
|
|
657
|
+
([feed, own_capabilities]) => ({
|
|
658
|
+
feed,
|
|
659
|
+
own_capabilities,
|
|
660
|
+
}),
|
|
661
|
+
);
|
|
662
|
+
this.hydrateCapabilitiesCache(feedResponses);
|
|
663
|
+
return response;
|
|
664
|
+
}
|
|
665
|
+
|
|
563
666
|
updateNetworkConnectionStatus = (
|
|
564
667
|
event: { type: 'online' | 'offline' } | Event,
|
|
565
668
|
) => {
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
export type ThrottledCallback = (...args: unknown[]) => unknown;
|
|
2
|
+
|
|
3
|
+
export type ThrottledFunction<T extends unknown[]> = (...args: T) => void;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Throttle a function so it runs at most once per `timeout` ms.
|
|
7
|
+
*
|
|
8
|
+
* - `leading`: fire immediately when the window opens
|
|
9
|
+
* - `trailing`: remember the latest args/this and fire once when the window closes
|
|
10
|
+
*
|
|
11
|
+
* defaults: `{ leading: true, trailing: false }`
|
|
12
|
+
*
|
|
13
|
+
* notes:
|
|
14
|
+
* - make one throttled instance and reuse it; re-creating it resets internal state
|
|
15
|
+
*
|
|
16
|
+
* @typeParam T - the function type being throttled
|
|
17
|
+
* @param fn - function to throttle
|
|
18
|
+
* @param timeout - minimum time between invocations (ms)
|
|
19
|
+
* @param options - behavior switches
|
|
20
|
+
* @param options.leading - call on the leading edge (default: true)
|
|
21
|
+
* @param options.trailing - call once at the end of the window with the latest args (default: false)
|
|
22
|
+
* @returns a throttled function with the same call signature as `fn`
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const send = (payload: Data) => api.post('/endpoint', payload);
|
|
26
|
+
* const sendThrottled = throttle(send, 2000, { leading: true, trailing: true });
|
|
27
|
+
* // call `sendThrottled` freely; it won’t invoke `send` more than once every 2s
|
|
28
|
+
*/
|
|
29
|
+
export const throttle = <T extends unknown[]>(
|
|
30
|
+
fn: (...args: T) => void,
|
|
31
|
+
timeout = 200,
|
|
32
|
+
{
|
|
33
|
+
leading = true,
|
|
34
|
+
trailing = false,
|
|
35
|
+
}: { leading?: boolean; trailing?: boolean } = {},
|
|
36
|
+
) => {
|
|
37
|
+
let timer: NodeJS.Timeout | null = null;
|
|
38
|
+
let storedArgs: T | null = null;
|
|
39
|
+
let storedThis: unknown = null;
|
|
40
|
+
let lastInvokeTime: number | undefined; // timestamp of last actual invocation
|
|
41
|
+
|
|
42
|
+
const invoke = (args: T, thisArg: unknown) => {
|
|
43
|
+
lastInvokeTime = Date.now();
|
|
44
|
+
fn.apply(thisArg, args);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const scheduleTrailing = (delay: number) => {
|
|
48
|
+
if (timer) return;
|
|
49
|
+
timer = setTimeout(() => {
|
|
50
|
+
timer = null;
|
|
51
|
+
if (trailing && storedArgs) {
|
|
52
|
+
invoke(storedArgs, storedThis);
|
|
53
|
+
storedArgs = null;
|
|
54
|
+
storedThis = null;
|
|
55
|
+
}
|
|
56
|
+
}, delay);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
throttledFn: function (this: unknown, ...args: T) {
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
|
|
63
|
+
const hasBeenInvoked = lastInvokeTime != null;
|
|
64
|
+
|
|
65
|
+
// if we have never invoked and `leading` is `false`, treat `lastInvokeTime` as now
|
|
66
|
+
if (!hasBeenInvoked && !leading) lastInvokeTime = now;
|
|
67
|
+
|
|
68
|
+
const timeSinceLast = hasBeenInvoked ? now - lastInvokeTime! : timeout;
|
|
69
|
+
const remaining = timeout - timeSinceLast;
|
|
70
|
+
|
|
71
|
+
// capture latest args for possible trailing invocation
|
|
72
|
+
if (trailing) {
|
|
73
|
+
storedArgs = args;
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
75
|
+
storedThis = this;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// if enough time has passed, invoke immediately
|
|
79
|
+
if (remaining <= 0) {
|
|
80
|
+
// if there's a pending timer, clear it because we're invoking now
|
|
81
|
+
if (timer) {
|
|
82
|
+
clearTimeout(timer);
|
|
83
|
+
timer = null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// leading: call now
|
|
87
|
+
if (leading) {
|
|
88
|
+
// if trailing is also `true`, we've already stored args above;
|
|
89
|
+
// make sure we don't call the same args twice
|
|
90
|
+
if (trailing) {
|
|
91
|
+
// if the `storedArgs` are exactly the args we're about to call,
|
|
92
|
+
// clear storedArgs to avoid double invocation by trailing (comparing
|
|
93
|
+
// by reference is fine because the `args` array is new each call)
|
|
94
|
+
if (storedArgs === args) {
|
|
95
|
+
storedArgs = null;
|
|
96
|
+
storedThis = null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
invoke(args, this);
|
|
100
|
+
} else {
|
|
101
|
+
// not leading but trailing: schedule a trailing call after `timeout`
|
|
102
|
+
if (trailing) scheduleTrailing(timeout);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// not enough time passed: we're in cooldown, so if
|
|
109
|
+
// trailing is requested, ensure a trailing invocation
|
|
110
|
+
// is scheduled at the end of the remaining time
|
|
111
|
+
if (trailing && !timer) {
|
|
112
|
+
scheduleTrailing(remaining);
|
|
113
|
+
}
|
|
114
|
+
// if `trailing` is `false`, we simply drop the call (throttle)
|
|
115
|
+
},
|
|
116
|
+
cancelTimer: () => {
|
|
117
|
+
if (timer) {
|
|
118
|
+
clearTimeout(timer);
|
|
119
|
+
timer = null;
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { FeedsClient } from '@self';
|
|
2
|
+
import type { ThrottledFunction } from './throttle';
|
|
3
|
+
|
|
4
|
+
const BATCH_OWN_CAPABILITIES_API_LIMIT = 100;
|
|
5
|
+
|
|
6
|
+
export type GetBatchedOwnCapabilities = {
|
|
7
|
+
feeds: string[];
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type GetBatchedOwnCapabilitiesThrottledCallback = [
|
|
11
|
+
feeds: string[],
|
|
12
|
+
callback: (feedsToClear: string[]) => void | Promise<void>,
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
export type ThrottledGetBatchedOwnCapabilities =
|
|
16
|
+
ThrottledFunction<GetBatchedOwnCapabilitiesThrottledCallback>;
|
|
17
|
+
|
|
18
|
+
export const DEFAULT_BATCH_OWN_CAPABILITIES_THROTTLING_INTERVAL = 2000;
|
|
19
|
+
|
|
20
|
+
const queuedFeeds: Set<string> = new Set();
|
|
21
|
+
|
|
22
|
+
export function queueBatchedOwnCapabilities(
|
|
23
|
+
this: FeedsClient,
|
|
24
|
+
{ feeds }: GetBatchedOwnCapabilities,
|
|
25
|
+
) {
|
|
26
|
+
for (const feed of feeds) {
|
|
27
|
+
queuedFeeds.add(feed);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (queuedFeeds.size > 0) {
|
|
31
|
+
this.throttledGetBatchOwnCapabilities(
|
|
32
|
+
[...queuedFeeds].slice(0, BATCH_OWN_CAPABILITIES_API_LIMIT),
|
|
33
|
+
(feedsToClear: string[]) => {
|
|
34
|
+
for (const feed of feedsToClear) {
|
|
35
|
+
queuedFeeds.delete(feed);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function clearQueuedFeeds() {
|
|
43
|
+
queuedFeeds.clear();
|
|
44
|
+
}
|