@stream-io/feeds-client 0.3.42 → 0.3.44
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 +14 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react-bindings.js +1 -1
- package/dist/es/index.mjs +2 -2
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/react-bindings.mjs +1 -1
- package/dist/{feeds-client-BIM-XpQr.mjs → feeds-client-B7anS3xV.mjs} +55 -11
- package/dist/feeds-client-B7anS3xV.mjs.map +1 -0
- package/dist/{feeds-client-9wb2RHSS.js → feeds-client-DK7vuKlg.js} +55 -11
- package/dist/feeds-client-DK7vuKlg.js.map +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/types/common/real-time/event-models.d.ts +2 -2
- package/dist/types/common/real-time/event-models.d.ts.map +1 -1
- package/dist/types/feed/feed.d.ts.map +1 -1
- package/dist/types/feeds-client/feeds-client.d.ts.map +1 -1
- package/dist/types/gen/feeds/FeedsApi.d.ts.map +1 -1
- package/dist/types/gen/models/index.d.ts +10 -0
- package/dist/types/gen/models/index.d.ts.map +1 -1
- package/dist/types/utils/retry.d.ts +25 -0
- package/dist/types/utils/retry.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/common/real-time/event-models.ts +2 -2
- package/src/feed/feed.ts +2 -1
- package/src/feeds-client/feeds-client.ts +11 -8
- package/src/gen/feeds/FeedsApi.ts +9 -0
- package/src/gen/models/index.ts +20 -0
- package/src/utils/retry.ts +76 -0
- package/dist/feeds-client-9wb2RHSS.js.map +0 -1
- package/dist/feeds-client-BIM-XpQr.mjs.map +0 -1
|
@@ -92,6 +92,7 @@ import {
|
|
|
92
92
|
type GetBatchedOwnFieldsThrottledCallback,
|
|
93
93
|
DEFAULT_BATCH_OWN_FIELDS_THROTTLING_INTERVAL,
|
|
94
94
|
} from '../utils/throttling';
|
|
95
|
+
import { withRetry } from '../utils/retry';
|
|
95
96
|
import { ActivityWithStateUpdates } from '../activity-with-state-updates/activity-with-state-updates';
|
|
96
97
|
import { getFeed } from '../activity-with-state-updates/get-feed';
|
|
97
98
|
import {
|
|
@@ -291,8 +292,7 @@ export class FeedsClient extends FeedsApi {
|
|
|
291
292
|
}).catch((error) => {
|
|
292
293
|
this.eventDispatcher.dispatch({
|
|
293
294
|
type: 'errors.unhandled',
|
|
294
|
-
error_type:
|
|
295
|
-
UnhandledErrorType.FetchingOwnCapabilitiesOnNewActivity,
|
|
295
|
+
error_type: UnhandledErrorType.FetchingOwnFieldsOnNewActivity,
|
|
296
296
|
error,
|
|
297
297
|
});
|
|
298
298
|
});
|
|
@@ -328,11 +328,13 @@ export class FeedsClient extends FeedsApi {
|
|
|
328
328
|
return [{ feed, reason: result.reason, activity_id: activity?.id }];
|
|
329
329
|
});
|
|
330
330
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
331
|
+
if (failures.length > 0) {
|
|
332
|
+
this.eventDispatcher.dispatch({
|
|
333
|
+
type: 'errors.unhandled',
|
|
334
|
+
error_type: UnhandledErrorType.ReconnectionReconciliation,
|
|
335
|
+
failures,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
336
338
|
}
|
|
337
339
|
};
|
|
338
340
|
|
|
@@ -620,6 +622,7 @@ export class FeedsClient extends FeedsApi {
|
|
|
620
622
|
|
|
621
623
|
this.activeActivities = [];
|
|
622
624
|
this.activeFeeds = {};
|
|
625
|
+
this.healthyConnectionChangedEventCount = 0;
|
|
623
626
|
|
|
624
627
|
this.state.partialNext(this.initialState);
|
|
625
628
|
|
|
@@ -704,7 +707,7 @@ export class FeedsClient extends FeedsApi {
|
|
|
704
707
|
}
|
|
705
708
|
|
|
706
709
|
async ownBatch(request: OwnBatchRequest) {
|
|
707
|
-
const response = await super.ownBatch(request);
|
|
710
|
+
const response = await withRetry(() => super.ownBatch(request));
|
|
708
711
|
Object.entries(response.data).forEach(([fid, ownFields]) => {
|
|
709
712
|
const feed = this.activeFeeds[fid];
|
|
710
713
|
if (feed) {
|
|
@@ -313,6 +313,7 @@ export class FeedsApi {
|
|
|
313
313
|
const body = {
|
|
314
314
|
type: request?.type,
|
|
315
315
|
feeds: request?.feeds,
|
|
316
|
+
copy_custom_to_notification: request?.copy_custom_to_notification,
|
|
316
317
|
create_notification_activity: request?.create_notification_activity,
|
|
317
318
|
expires_at: request?.expires_at,
|
|
318
319
|
id: request?.id,
|
|
@@ -599,6 +600,7 @@ export class FeedsApi {
|
|
|
599
600
|
};
|
|
600
601
|
const body = {
|
|
601
602
|
type: request?.type,
|
|
603
|
+
copy_custom_to_notification: request?.copy_custom_to_notification,
|
|
602
604
|
create_notification_activity: request?.create_notification_activity,
|
|
603
605
|
enforce_unique: request?.enforce_unique,
|
|
604
606
|
skip_push: request?.skip_push,
|
|
@@ -723,6 +725,7 @@ export class FeedsApi {
|
|
|
723
725
|
id: request?.id,
|
|
724
726
|
};
|
|
725
727
|
const body = {
|
|
728
|
+
copy_custom_to_notification: request?.copy_custom_to_notification,
|
|
726
729
|
handle_mention_notifications: request?.handle_mention_notifications,
|
|
727
730
|
run_activity_processors: request?.run_activity_processors,
|
|
728
731
|
unset: request?.unset,
|
|
@@ -752,6 +755,7 @@ export class FeedsApi {
|
|
|
752
755
|
id: request?.id,
|
|
753
756
|
};
|
|
754
757
|
const body = {
|
|
758
|
+
copy_custom_to_notification: request?.copy_custom_to_notification,
|
|
755
759
|
expires_at: request?.expires_at,
|
|
756
760
|
handle_mention_notifications: request?.handle_mention_notifications,
|
|
757
761
|
poll_id: request?.poll_id,
|
|
@@ -1026,6 +1030,7 @@ export class FeedsApi {
|
|
|
1026
1030
|
): Promise<StreamResponse<AddCommentResponse>> {
|
|
1027
1031
|
const body = {
|
|
1028
1032
|
comment: request?.comment,
|
|
1033
|
+
copy_custom_to_notification: request?.copy_custom_to_notification,
|
|
1029
1034
|
create_notification_activity: request?.create_notification_activity,
|
|
1030
1035
|
id: request?.id,
|
|
1031
1036
|
object_id: request?.object_id,
|
|
@@ -1150,6 +1155,7 @@ export class FeedsApi {
|
|
|
1150
1155
|
};
|
|
1151
1156
|
const body = {
|
|
1152
1157
|
comment: request?.comment,
|
|
1158
|
+
copy_custom_to_notification: request?.copy_custom_to_notification,
|
|
1153
1159
|
handle_mention_notifications: request?.handle_mention_notifications,
|
|
1154
1160
|
skip_enrich_url: request?.skip_enrich_url,
|
|
1155
1161
|
skip_push: request?.skip_push,
|
|
@@ -1182,6 +1188,7 @@ export class FeedsApi {
|
|
|
1182
1188
|
};
|
|
1183
1189
|
const body = {
|
|
1184
1190
|
type: request?.type,
|
|
1191
|
+
copy_custom_to_notification: request?.copy_custom_to_notification,
|
|
1185
1192
|
create_notification_activity: request?.create_notification_activity,
|
|
1186
1193
|
enforce_unique: request?.enforce_unique,
|
|
1187
1194
|
skip_push: request?.skip_push,
|
|
@@ -1740,6 +1747,7 @@ export class FeedsApi {
|
|
|
1740
1747
|
const body = {
|
|
1741
1748
|
source: request?.source,
|
|
1742
1749
|
target: request?.target,
|
|
1750
|
+
copy_custom_to_notification: request?.copy_custom_to_notification,
|
|
1743
1751
|
create_notification_activity: request?.create_notification_activity,
|
|
1744
1752
|
follower_role: request?.follower_role,
|
|
1745
1753
|
push_preference: request?.push_preference,
|
|
@@ -1769,6 +1777,7 @@ export class FeedsApi {
|
|
|
1769
1777
|
const body = {
|
|
1770
1778
|
source: request?.source,
|
|
1771
1779
|
target: request?.target,
|
|
1780
|
+
copy_custom_to_notification: request?.copy_custom_to_notification,
|
|
1772
1781
|
create_notification_activity: request?.create_notification_activity,
|
|
1773
1782
|
push_preference: request?.push_preference,
|
|
1774
1783
|
skip_push: request?.skip_push,
|
package/src/gen/models/index.ts
CHANGED
|
@@ -365,6 +365,8 @@ export interface ActivityRequest {
|
|
|
365
365
|
|
|
366
366
|
feeds: string[];
|
|
367
367
|
|
|
368
|
+
copy_custom_to_notification?: boolean;
|
|
369
|
+
|
|
368
370
|
create_notification_activity?: boolean;
|
|
369
371
|
|
|
370
372
|
expires_at?: string;
|
|
@@ -565,6 +567,8 @@ export interface AddActivityRequest {
|
|
|
565
567
|
|
|
566
568
|
feeds: string[];
|
|
567
569
|
|
|
570
|
+
copy_custom_to_notification?: boolean;
|
|
571
|
+
|
|
568
572
|
create_notification_activity?: boolean;
|
|
569
573
|
|
|
570
574
|
expires_at?: string;
|
|
@@ -629,6 +633,8 @@ export interface AddBookmarkResponse {
|
|
|
629
633
|
export interface AddCommentReactionRequest {
|
|
630
634
|
type: string;
|
|
631
635
|
|
|
636
|
+
copy_custom_to_notification?: boolean;
|
|
637
|
+
|
|
632
638
|
create_notification_activity?: boolean;
|
|
633
639
|
|
|
634
640
|
enforce_unique?: boolean;
|
|
@@ -651,6 +657,8 @@ export interface AddCommentReactionResponse {
|
|
|
651
657
|
export interface AddCommentRequest {
|
|
652
658
|
comment?: string;
|
|
653
659
|
|
|
660
|
+
copy_custom_to_notification?: boolean;
|
|
661
|
+
|
|
654
662
|
create_notification_activity?: boolean;
|
|
655
663
|
|
|
656
664
|
id?: string;
|
|
@@ -701,6 +709,8 @@ export interface AddFolderRequest {
|
|
|
701
709
|
export interface AddReactionRequest {
|
|
702
710
|
type: string;
|
|
703
711
|
|
|
712
|
+
copy_custom_to_notification?: boolean;
|
|
713
|
+
|
|
704
714
|
create_notification_activity?: boolean;
|
|
705
715
|
|
|
706
716
|
enforce_unique?: boolean;
|
|
@@ -3144,6 +3154,8 @@ export interface FollowRequest {
|
|
|
3144
3154
|
|
|
3145
3155
|
target: string;
|
|
3146
3156
|
|
|
3157
|
+
copy_custom_to_notification?: boolean;
|
|
3158
|
+
|
|
3147
3159
|
create_notification_activity?: boolean;
|
|
3148
3160
|
|
|
3149
3161
|
push_preference?: 'all' | 'none';
|
|
@@ -5771,6 +5783,8 @@ export interface UnpinActivityResponse {
|
|
|
5771
5783
|
}
|
|
5772
5784
|
|
|
5773
5785
|
export interface UpdateActivityPartialRequest {
|
|
5786
|
+
copy_custom_to_notification?: boolean;
|
|
5787
|
+
|
|
5774
5788
|
handle_mention_notifications?: boolean;
|
|
5775
5789
|
|
|
5776
5790
|
run_activity_processors?: boolean;
|
|
@@ -5787,6 +5801,8 @@ export interface UpdateActivityPartialResponse {
|
|
|
5787
5801
|
}
|
|
5788
5802
|
|
|
5789
5803
|
export interface UpdateActivityRequest {
|
|
5804
|
+
copy_custom_to_notification?: boolean;
|
|
5805
|
+
|
|
5790
5806
|
expires_at?: Date;
|
|
5791
5807
|
|
|
5792
5808
|
handle_mention_notifications?: boolean;
|
|
@@ -5893,6 +5909,8 @@ export interface UpdateCollectionsResponse {
|
|
|
5893
5909
|
export interface UpdateCommentRequest {
|
|
5894
5910
|
comment?: string;
|
|
5895
5911
|
|
|
5912
|
+
copy_custom_to_notification?: boolean;
|
|
5913
|
+
|
|
5896
5914
|
handle_mention_notifications?: boolean;
|
|
5897
5915
|
|
|
5898
5916
|
skip_enrich_url?: boolean;
|
|
@@ -5955,6 +5973,8 @@ export interface UpdateFollowRequest {
|
|
|
5955
5973
|
|
|
5956
5974
|
target: string;
|
|
5957
5975
|
|
|
5976
|
+
copy_custom_to_notification?: boolean;
|
|
5977
|
+
|
|
5958
5978
|
create_notification_activity?: boolean;
|
|
5959
5979
|
|
|
5960
5980
|
follower_role?: string;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { retryInterval, sleep } from '../common/utils';
|
|
2
|
+
import { StreamApiError } from '../common/types';
|
|
3
|
+
|
|
4
|
+
export type RetryOptions = {
|
|
5
|
+
maxRetries?: number;
|
|
6
|
+
shouldRetry?: (error: unknown, attempt: number) => boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const DEFAULT_MAX_RETRIES = 3;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Checks if an error is a client error (4xx HTTP status code) that should not be retried.
|
|
13
|
+
* Client errors indicate issues with the request itself (bad input, unauthorized, not found, etc.)
|
|
14
|
+
* and retrying won't help.
|
|
15
|
+
*
|
|
16
|
+
* @param error - The error to check
|
|
17
|
+
* @returns true if the error should be retried, false if it's a client error
|
|
18
|
+
*/
|
|
19
|
+
export function isRetryableError(error: unknown): boolean {
|
|
20
|
+
if (error instanceof StreamApiError) {
|
|
21
|
+
const statusCode = error.metadata?.response_code;
|
|
22
|
+
// Don't retry on 4xx client errors
|
|
23
|
+
if (statusCode && statusCode >= 400 && statusCode < 500) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Wraps an async function with automatic retry logic using exponential backoff.
|
|
32
|
+
*
|
|
33
|
+
* By default, retries are performed for server errors (5xx) and network errors,
|
|
34
|
+
* but not for client errors (4xx) which indicate issues with the request itself.
|
|
35
|
+
*
|
|
36
|
+
* @param fn - The async function to retry
|
|
37
|
+
* @param options - Retry options
|
|
38
|
+
* @returns The result of the function
|
|
39
|
+
*/
|
|
40
|
+
export async function withRetry<T>(
|
|
41
|
+
fn: () => Promise<T>,
|
|
42
|
+
options: RetryOptions = {},
|
|
43
|
+
): Promise<T> {
|
|
44
|
+
const { maxRetries = DEFAULT_MAX_RETRIES, shouldRetry } = options;
|
|
45
|
+
|
|
46
|
+
let lastError: unknown;
|
|
47
|
+
|
|
48
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
49
|
+
try {
|
|
50
|
+
return await fn();
|
|
51
|
+
} catch (error) {
|
|
52
|
+
lastError = error;
|
|
53
|
+
|
|
54
|
+
const isLastAttempt = attempt === maxRetries;
|
|
55
|
+
|
|
56
|
+
if (isLastAttempt) {
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Use custom shouldRetry if provided, otherwise use default behavior
|
|
61
|
+
const shouldRetryResult = shouldRetry
|
|
62
|
+
? shouldRetry(error, attempt)
|
|
63
|
+
: isRetryableError(error);
|
|
64
|
+
|
|
65
|
+
if (!shouldRetryResult) {
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const delay = retryInterval(attempt + 1);
|
|
70
|
+
await sleep(delay);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// This should never be reached, but TypeScript needs it
|
|
75
|
+
throw lastError;
|
|
76
|
+
}
|