@s2-dev/streamstore 0.3.9 → 0.3.13
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/README.md +15 -12
- package/docs/sdks/account/README.md +38 -35
- package/docs/sdks/basin/README.md +38 -35
- package/docs/sdks/stream/README.md +22 -27
- package/funcs/accountCreateBasin.d.ts +2 -1
- package/funcs/accountCreateBasin.d.ts.map +1 -1
- package/funcs/accountCreateBasin.js +3 -4
- package/funcs/accountCreateBasin.js.map +1 -1
- package/funcs/accountDeleteBasin.d.ts +1 -1
- package/funcs/accountDeleteBasin.d.ts.map +1 -1
- package/funcs/accountDeleteBasin.js +3 -2
- package/funcs/accountDeleteBasin.js.map +1 -1
- package/funcs/accountGetBasinConfig.d.ts +2 -1
- package/funcs/accountGetBasinConfig.d.ts.map +1 -1
- package/funcs/accountGetBasinConfig.js +3 -4
- package/funcs/accountGetBasinConfig.js.map +1 -1
- package/funcs/accountListBasins.d.ts +1 -1
- package/funcs/accountListBasins.d.ts.map +1 -1
- package/funcs/accountListBasins.js +2 -4
- package/funcs/accountListBasins.js.map +1 -1
- package/funcs/accountReconfigureBasin.d.ts +2 -1
- package/funcs/accountReconfigureBasin.d.ts.map +1 -1
- package/funcs/accountReconfigureBasin.js +3 -4
- package/funcs/accountReconfigureBasin.js.map +1 -1
- package/funcs/basinCreateStream.d.ts +2 -1
- package/funcs/basinCreateStream.d.ts.map +1 -1
- package/funcs/basinCreateStream.js +14 -4
- package/funcs/basinCreateStream.js.map +1 -1
- package/funcs/basinDeleteStream.d.ts +1 -1
- package/funcs/basinDeleteStream.d.ts.map +1 -1
- package/funcs/basinDeleteStream.js +3 -2
- package/funcs/basinDeleteStream.js.map +1 -1
- package/funcs/basinGetStreamConfig.d.ts +2 -1
- package/funcs/basinGetStreamConfig.d.ts.map +1 -1
- package/funcs/basinGetStreamConfig.js +3 -4
- package/funcs/basinGetStreamConfig.js.map +1 -1
- package/funcs/basinListStreams.d.ts +1 -1
- package/funcs/basinListStreams.d.ts.map +1 -1
- package/funcs/basinListStreams.js +3 -3
- package/funcs/basinListStreams.js.map +1 -1
- package/funcs/basinReconfigureStream.d.ts +2 -1
- package/funcs/basinReconfigureStream.d.ts.map +1 -1
- package/funcs/basinReconfigureStream.js +3 -4
- package/funcs/basinReconfigureStream.js.map +1 -1
- package/funcs/streamAppend.d.ts +2 -1
- package/funcs/streamAppend.d.ts.map +1 -1
- package/funcs/streamAppend.js +3 -4
- package/funcs/streamAppend.js.map +1 -1
- package/funcs/streamCheckTail.d.ts +2 -1
- package/funcs/streamCheckTail.d.ts.map +1 -1
- package/funcs/streamCheckTail.js +3 -4
- package/funcs/streamCheckTail.js.map +1 -1
- package/funcs/streamRead.d.ts +1 -1
- package/funcs/streamRead.d.ts.map +1 -1
- package/funcs/streamRead.js +2 -2
- package/funcs/streamRead.js.map +1 -1
- package/index.extras.d.ts +13 -5
- package/index.extras.d.ts.map +1 -1
- package/index.extras.js +64 -25
- package/index.extras.js.map +1 -1
- package/jsr.json +1 -1
- package/lib/config.d.ts +2 -2
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +2 -2
- package/lib/config.js.map +1 -1
- package/lib/matchers.d.ts +1 -1
- package/lib/matchers.d.ts.map +1 -1
- package/lib/matchers.js +11 -10
- package/lib/matchers.js.map +1 -1
- package/models/components/index.d.ts +0 -1
- package/models/components/index.d.ts.map +1 -1
- package/models/components/index.js +0 -1
- package/models/components/index.js.map +1 -1
- package/models/errors/apierror.d.ts +5 -8
- package/models/errors/apierror.d.ts.map +1 -1
- package/models/errors/apierror.js +9 -3
- package/models/errors/apierror.js.map +1 -1
- package/models/errors/index.d.ts +1 -0
- package/models/errors/index.d.ts.map +1 -1
- package/models/errors/index.js +1 -0
- package/models/errors/index.js.map +1 -1
- package/models/errors/retryableerror.d.ts +31 -0
- package/models/errors/retryableerror.d.ts.map +1 -0
- package/models/errors/retryableerror.js +77 -0
- package/models/errors/retryableerror.js.map +1 -0
- package/models/operations/append.d.ts +0 -27
- package/models/operations/append.d.ts.map +1 -1
- package/models/operations/append.js +1 -40
- package/models/operations/append.js.map +1 -1
- package/models/operations/checktail.d.ts +0 -28
- package/models/operations/checktail.d.ts.map +1 -1
- package/models/operations/checktail.js +1 -42
- package/models/operations/checktail.js.map +1 -1
- package/models/operations/createbasin.d.ts +0 -27
- package/models/operations/createbasin.d.ts.map +1 -1
- package/models/operations/createbasin.js +1 -40
- package/models/operations/createbasin.js.map +1 -1
- package/models/operations/createstream.d.ts +0 -27
- package/models/operations/createstream.d.ts.map +1 -1
- package/models/operations/createstream.js +1 -40
- package/models/operations/createstream.js.map +1 -1
- package/models/operations/deletebasin.d.ts +0 -26
- package/models/operations/deletebasin.d.ts.map +1 -1
- package/models/operations/deletebasin.js +1 -38
- package/models/operations/deletebasin.js.map +1 -1
- package/models/operations/deletestream.d.ts +0 -26
- package/models/operations/deletestream.d.ts.map +1 -1
- package/models/operations/deletestream.js +1 -38
- package/models/operations/deletestream.js.map +1 -1
- package/models/operations/getbasinconfig.d.ts +0 -28
- package/models/operations/getbasinconfig.d.ts.map +1 -1
- package/models/operations/getbasinconfig.js +1 -42
- package/models/operations/getbasinconfig.js.map +1 -1
- package/models/operations/getstreamconfig.d.ts +0 -28
- package/models/operations/getstreamconfig.d.ts.map +1 -1
- package/models/operations/getstreamconfig.js +1 -42
- package/models/operations/getstreamconfig.js.map +1 -1
- package/models/operations/listbasins.d.ts +2 -4
- package/models/operations/listbasins.d.ts.map +1 -1
- package/models/operations/listbasins.js +4 -8
- package/models/operations/listbasins.js.map +1 -1
- package/models/operations/liststreams.d.ts +2 -4
- package/models/operations/liststreams.d.ts.map +1 -1
- package/models/operations/liststreams.js +4 -8
- package/models/operations/liststreams.js.map +1 -1
- package/models/operations/read.d.ts +2 -10
- package/models/operations/read.d.ts.map +1 -1
- package/models/operations/read.js +6 -23
- package/models/operations/read.js.map +1 -1
- package/models/operations/reconfigurebasin.d.ts +0 -27
- package/models/operations/reconfigurebasin.d.ts.map +1 -1
- package/models/operations/reconfigurebasin.js +1 -40
- package/models/operations/reconfigurebasin.js.map +1 -1
- package/models/operations/reconfigurestream.d.ts +0 -27
- package/models/operations/reconfigurestream.d.ts.map +1 -1
- package/models/operations/reconfigurestream.js +1 -40
- package/models/operations/reconfigurestream.js.map +1 -1
- package/package.json +1 -1
- package/sdk/account.d.ts +5 -4
- package/sdk/account.d.ts.map +1 -1
- package/sdk/account.js.map +1 -1
- package/sdk/basin.d.ts +5 -4
- package/sdk/basin.d.ts.map +1 -1
- package/sdk/basin.js.map +1 -1
- package/sdk/stream.d.ts +3 -2
- package/sdk/stream.d.ts.map +1 -1
- package/sdk/stream.js.map +1 -1
- package/src/funcs/accountCreateBasin.ts +12 -10
- package/src/funcs/accountDeleteBasin.ts +12 -8
- package/src/funcs/accountGetBasinConfig.ts +12 -10
- package/src/funcs/accountListBasins.ts +11 -9
- package/src/funcs/accountReconfigureBasin.ts +12 -10
- package/src/funcs/basinCreateStream.ts +23 -10
- package/src/funcs/basinDeleteStream.ts +12 -8
- package/src/funcs/basinGetStreamConfig.ts +12 -10
- package/src/funcs/basinListStreams.ts +11 -7
- package/src/funcs/basinReconfigureStream.ts +12 -10
- package/src/funcs/streamAppend.ts +12 -10
- package/src/funcs/streamCheckTail.ts +12 -10
- package/src/funcs/streamRead.ts +10 -7
- package/src/index.extras.ts +139 -48
- package/src/lib/config.ts +3 -2
- package/src/lib/matchers.ts +16 -10
- package/src/models/components/index.ts +0 -1
- package/src/models/errors/apierror.ts +13 -7
- package/src/models/errors/index.ts +1 -0
- package/src/models/errors/retryableerror.ts +69 -0
- package/src/models/operations/append.ts +0 -68
- package/src/models/operations/checktail.ts +0 -74
- package/src/models/operations/createbasin.ts +0 -72
- package/src/models/operations/createstream.ts +0 -72
- package/src/models/operations/deletebasin.ts +0 -68
- package/src/models/operations/deletestream.ts +0 -68
- package/src/models/operations/getbasinconfig.ts +0 -74
- package/src/models/operations/getstreamconfig.ts +0 -74
- package/src/models/operations/listbasins.ts +6 -12
- package/src/models/operations/liststreams.ts +6 -12
- package/src/models/operations/read.ts +10 -33
- package/src/models/operations/reconfigurebasin.ts +0 -72
- package/src/models/operations/reconfigurestream.ts +0 -72
- package/src/sdk/account.ts +5 -4
- package/src/sdk/basin.ts +5 -4
- package/src/sdk/stream.ts +3 -2
- package/models/components/httpmetadata.d.ts +0 -37
- package/models/components/httpmetadata.d.ts.map +0 -1
- package/models/components/httpmetadata.js +0 -86
- package/models/components/httpmetadata.js.map +0 -1
- package/src/models/components/httpmetadata.ts +0 -87
|
@@ -10,6 +10,7 @@ import { safeParse } from "../lib/schemas.js";
|
|
|
10
10
|
import { RequestOptions } from "../lib/sdks.js";
|
|
11
11
|
import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js";
|
|
12
12
|
import { pathToFunc } from "../lib/url.js";
|
|
13
|
+
import * as components from "../models/components/index.js";
|
|
13
14
|
import { APIError } from "../models/errors/apierror.js";
|
|
14
15
|
import {
|
|
15
16
|
ConnectionError,
|
|
@@ -36,9 +37,10 @@ export async function streamCheckTail(
|
|
|
36
37
|
options?: RequestOptions,
|
|
37
38
|
): Promise<
|
|
38
39
|
Result<
|
|
39
|
-
|
|
40
|
-
| errors.ErrorResponse
|
|
40
|
+
components.CheckTailResponse,
|
|
41
41
|
| errors.ErrorResponse
|
|
42
|
+
| errors.RetryableError
|
|
43
|
+
| errors.RetryableError
|
|
42
44
|
| APIError
|
|
43
45
|
| SDKValidationError
|
|
44
46
|
| UnexpectedClientError
|
|
@@ -110,7 +112,7 @@ export async function streamCheckTail(
|
|
|
110
112
|
|
|
111
113
|
const doResult = await client._do(req, {
|
|
112
114
|
context,
|
|
113
|
-
errorCodes: ["400", "401", "404", "4XX", "500", "5XX"],
|
|
115
|
+
errorCodes: ["400", "401", "404", "499", "4XX", "500", "503", "504", "5XX"],
|
|
114
116
|
retryConfig: context.retryConfig,
|
|
115
117
|
retryCodes: context.retryCodes,
|
|
116
118
|
});
|
|
@@ -124,9 +126,10 @@ export async function streamCheckTail(
|
|
|
124
126
|
};
|
|
125
127
|
|
|
126
128
|
const [result] = await M.match<
|
|
127
|
-
|
|
128
|
-
| errors.ErrorResponse
|
|
129
|
+
components.CheckTailResponse,
|
|
129
130
|
| errors.ErrorResponse
|
|
131
|
+
| errors.RetryableError
|
|
132
|
+
| errors.RetryableError
|
|
130
133
|
| APIError
|
|
131
134
|
| SDKValidationError
|
|
132
135
|
| UnexpectedClientError
|
|
@@ -135,14 +138,13 @@ export async function streamCheckTail(
|
|
|
135
138
|
| RequestTimeoutError
|
|
136
139
|
| ConnectionError
|
|
137
140
|
>(
|
|
138
|
-
M.json(200,
|
|
139
|
-
key: "CheckTailResponse",
|
|
140
|
-
}),
|
|
141
|
+
M.json(200, components.CheckTailResponse$inboundSchema),
|
|
141
142
|
M.jsonErr([400, 401, 404], errors.ErrorResponse$inboundSchema),
|
|
142
|
-
M.jsonErr(
|
|
143
|
+
M.jsonErr(499, errors.RetryableError$inboundSchema),
|
|
144
|
+
M.jsonErr([500, 503, 504], errors.RetryableError$inboundSchema),
|
|
143
145
|
M.fail("4XX"),
|
|
144
146
|
M.fail("5XX"),
|
|
145
|
-
)(response,
|
|
147
|
+
)(response, { extraFields: responseFields });
|
|
146
148
|
if (!result.ok) {
|
|
147
149
|
return result;
|
|
148
150
|
}
|
package/src/funcs/streamRead.ts
CHANGED
|
@@ -43,7 +43,8 @@ export async function streamRead(
|
|
|
43
43
|
Result<
|
|
44
44
|
operations.ReadResponse,
|
|
45
45
|
| errors.ErrorResponse
|
|
46
|
-
| errors.
|
|
46
|
+
| errors.RetryableError
|
|
47
|
+
| errors.RetryableError
|
|
47
48
|
| APIError
|
|
48
49
|
| SDKValidationError
|
|
49
50
|
| UnexpectedClientError
|
|
@@ -126,7 +127,7 @@ export async function streamRead(
|
|
|
126
127
|
|
|
127
128
|
const doResult = await client._do(req, {
|
|
128
129
|
context,
|
|
129
|
-
errorCodes: ["400", "401", "404", "4XX", "500", "5XX"],
|
|
130
|
+
errorCodes: ["400", "401", "404", "499", "4XX", "500", "503", "504", "5XX"],
|
|
130
131
|
retryConfig: context.retryConfig,
|
|
131
132
|
retryCodes: context.retryCodes,
|
|
132
133
|
});
|
|
@@ -142,7 +143,8 @@ export async function streamRead(
|
|
|
142
143
|
const [result] = await M.match<
|
|
143
144
|
operations.ReadResponse,
|
|
144
145
|
| errors.ErrorResponse
|
|
145
|
-
| errors.
|
|
146
|
+
| errors.RetryableError
|
|
147
|
+
| errors.RetryableError
|
|
146
148
|
| APIError
|
|
147
149
|
| SDKValidationError
|
|
148
150
|
| UnexpectedClientError
|
|
@@ -151,13 +153,14 @@ export async function streamRead(
|
|
|
151
153
|
| RequestTimeoutError
|
|
152
154
|
| ConnectionError
|
|
153
155
|
>(
|
|
154
|
-
M.json(200, operations.ReadResponse$inboundSchema
|
|
155
|
-
M.sse(200, operations.ReadResponse$inboundSchema
|
|
156
|
+
M.json(200, operations.ReadResponse$inboundSchema),
|
|
157
|
+
M.sse(200, operations.ReadResponse$inboundSchema),
|
|
156
158
|
M.jsonErr([400, 401, 404], errors.ErrorResponse$inboundSchema),
|
|
157
|
-
M.jsonErr(
|
|
159
|
+
M.jsonErr(499, errors.RetryableError$inboundSchema),
|
|
160
|
+
M.jsonErr([500, 503, 504], errors.RetryableError$inboundSchema),
|
|
158
161
|
M.fail("4XX"),
|
|
159
162
|
M.fail("5XX"),
|
|
160
|
-
)(response,
|
|
163
|
+
)(response, { extraFields: responseFields });
|
|
161
164
|
if (!result.ok) {
|
|
162
165
|
return result;
|
|
163
166
|
}
|
package/src/index.extras.ts
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
StreamConfig,
|
|
15
15
|
StreamInfo,
|
|
16
16
|
} from "./models/components";
|
|
17
|
-
import {
|
|
17
|
+
import { NotFoundError, RetryableError } from "./models/errors";
|
|
18
18
|
import {
|
|
19
19
|
GetBasinConfigRequest,
|
|
20
20
|
ListBasinsRequest,
|
|
@@ -66,13 +66,24 @@ export type S2ClientConfig = {
|
|
|
66
66
|
authToken?: string;
|
|
67
67
|
requestTimeout?: number;
|
|
68
68
|
endpoints?: S2Endpoints;
|
|
69
|
+
appedRetryPolicy?: AppendRetryPolicy;
|
|
70
|
+
maxRetries?: number;
|
|
71
|
+
initialBackoffMs?: number;
|
|
72
|
+
maxBackoffMs?: number;
|
|
69
73
|
};
|
|
70
74
|
|
|
75
|
+
export enum AppendRetryPolicy {
|
|
76
|
+
All,
|
|
77
|
+
NoSideEffects,
|
|
78
|
+
}
|
|
79
|
+
|
|
71
80
|
const defaultS2ClientConfig: S2ClientConfig = {
|
|
72
81
|
requestTimeout: 3000,
|
|
73
82
|
endpoints: S2Endpoints.forCloud(S2Cloud.Aws),
|
|
83
|
+
appedRetryPolicy: AppendRetryPolicy.All,
|
|
74
84
|
};
|
|
75
85
|
|
|
86
|
+
|
|
76
87
|
export class S2Client {
|
|
77
88
|
private config: S2ClientConfig;
|
|
78
89
|
private _account?: S2Account;
|
|
@@ -116,15 +127,23 @@ class S2Account {
|
|
|
116
127
|
request?: ListBasinsRequest
|
|
117
128
|
): Promise<PageIterator<ListBasinsResponse, { cursor: string }>> {
|
|
118
129
|
const url = this.URL;
|
|
119
|
-
return
|
|
130
|
+
return retryWithExponentialBackoff(
|
|
131
|
+
() => this._account.listBasins(request ?? {}, url ? { serverURL: url } : {}),
|
|
132
|
+
this.config.maxRetries,
|
|
133
|
+
this.config.initialBackoffMs,
|
|
134
|
+
this.config.maxBackoffMs
|
|
135
|
+
);
|
|
120
136
|
}
|
|
121
137
|
|
|
122
138
|
async getBasinConfig(basin: string): Promise<BasinConfig | undefined> {
|
|
123
139
|
const _request: GetBasinConfigRequest = { basin };
|
|
124
140
|
const url = this.URL;
|
|
125
|
-
return (
|
|
126
|
-
, url ? { serverURL: url } : {}
|
|
127
|
-
|
|
141
|
+
return retryWithExponentialBackoff(
|
|
142
|
+
() => this._account.getBasinConfig(_request, url ? { serverURL: url } : {}),
|
|
143
|
+
this.config.maxRetries,
|
|
144
|
+
this.config.initialBackoffMs,
|
|
145
|
+
this.config.maxBackoffMs
|
|
146
|
+
);
|
|
128
147
|
}
|
|
129
148
|
|
|
130
149
|
async createBasin(basin: string, request?: CreateBasinRequest): Promise<BasinInfo | undefined> {
|
|
@@ -134,14 +153,22 @@ class S2Account {
|
|
|
134
153
|
createBasinRequest: request ?? {},
|
|
135
154
|
};
|
|
136
155
|
const url = this.URL;
|
|
137
|
-
return (
|
|
138
|
-
url ? { serverURL: url } : {}
|
|
139
|
-
|
|
156
|
+
return retryWithExponentialBackoff(
|
|
157
|
+
() => this._account.createBasin(_request, url ? { serverURL: url } : {}),
|
|
158
|
+
this.config.maxRetries,
|
|
159
|
+
this.config.initialBackoffMs,
|
|
160
|
+
this.config.maxBackoffMs
|
|
161
|
+
);
|
|
140
162
|
}
|
|
141
163
|
|
|
142
|
-
async deleteBasin(basin: string, if_exists?: boolean): Promise<void
|
|
164
|
+
async deleteBasin(basin: string, if_exists?: boolean): Promise<void> {
|
|
143
165
|
const url = this.URL;
|
|
144
|
-
const response = await
|
|
166
|
+
const response = await retryWithExponentialBackoff(
|
|
167
|
+
() => accountDeleteBasin(this._account, { basin }, url ? { serverURL: url } : {}),
|
|
168
|
+
this.config.maxRetries,
|
|
169
|
+
this.config.initialBackoffMs,
|
|
170
|
+
this.config.maxBackoffMs
|
|
171
|
+
);
|
|
145
172
|
if (if_exists && response.error instanceof NotFoundError) return;
|
|
146
173
|
if (response.error) throw new Error(response.error.message);
|
|
147
174
|
return;
|
|
@@ -150,9 +177,12 @@ class S2Account {
|
|
|
150
177
|
async reconfigureBasin(basin: string, config: BasinConfig): Promise<BasinConfig | undefined> {
|
|
151
178
|
const url = this.URL;
|
|
152
179
|
const _request: ReconfigureBasinRequest = { basin, basinConfig: config };
|
|
153
|
-
return (
|
|
154
|
-
, url ? { serverURL: url } : {}
|
|
155
|
-
|
|
180
|
+
return retryWithExponentialBackoff(
|
|
181
|
+
() => this._account.reconfigureBasin(_request, url ? { serverURL: url } : {}),
|
|
182
|
+
this.config.maxRetries,
|
|
183
|
+
this.config.initialBackoffMs,
|
|
184
|
+
this.config.maxBackoffMs
|
|
185
|
+
);
|
|
156
186
|
}
|
|
157
187
|
}
|
|
158
188
|
|
|
@@ -185,13 +215,21 @@ class S2Basin {
|
|
|
185
215
|
async listStreams(
|
|
186
216
|
request: ListStreamsRequest
|
|
187
217
|
): Promise<PageIterator<ListStreamsResponse, { cursor: string }>> {
|
|
188
|
-
return
|
|
218
|
+
return retryWithExponentialBackoff(
|
|
219
|
+
() => this._basin.listStreams(request, { serverURL: this.URL }),
|
|
220
|
+
this.config.maxRetries,
|
|
221
|
+
this.config.initialBackoffMs,
|
|
222
|
+
this.config.maxBackoffMs
|
|
223
|
+
);
|
|
189
224
|
}
|
|
190
225
|
|
|
191
226
|
async getStreamConfig(stream: string): Promise<StreamConfig | undefined> {
|
|
192
|
-
return (
|
|
193
|
-
|
|
194
|
-
|
|
227
|
+
return retryWithExponentialBackoff(
|
|
228
|
+
() => this._basin.getStreamConfig({ stream }, { serverURL: this.URL }),
|
|
229
|
+
this.config.maxRetries,
|
|
230
|
+
this.config.initialBackoffMs,
|
|
231
|
+
this.config.maxBackoffMs
|
|
232
|
+
);
|
|
195
233
|
}
|
|
196
234
|
|
|
197
235
|
async createStream(stream: string, request?: CreateStreamRequest): Promise<StreamInfo | undefined> {
|
|
@@ -200,27 +238,33 @@ class S2Basin {
|
|
|
200
238
|
s2RequestToken: genS2RequestToken(),
|
|
201
239
|
createStreamRequest: request ?? {},
|
|
202
240
|
};
|
|
203
|
-
return (
|
|
204
|
-
|
|
205
|
-
|
|
241
|
+
return retryWithExponentialBackoff(
|
|
242
|
+
() => this._basin.createStream(_request, { serverURL: this.URL }),
|
|
243
|
+
this.config.maxRetries,
|
|
244
|
+
this.config.initialBackoffMs,
|
|
245
|
+
this.config.maxBackoffMs
|
|
246
|
+
);
|
|
206
247
|
}
|
|
207
248
|
|
|
208
249
|
async deleteStream(stream: string, if_exists?: boolean): Promise<void | undefined> {
|
|
209
|
-
const response = await
|
|
210
|
-
serverURL: this.URL,
|
|
211
|
-
|
|
250
|
+
const response = await retryWithExponentialBackoff(
|
|
251
|
+
() => basinDeleteStream(this._basin, { stream }, { serverURL: this.URL }),
|
|
252
|
+
this.config.maxRetries,
|
|
253
|
+
this.config.initialBackoffMs,
|
|
254
|
+
this.config.maxBackoffMs
|
|
255
|
+
);
|
|
212
256
|
if (if_exists && response instanceof NotFoundError) return;
|
|
213
257
|
if (response.error) throw new Error(response.error.message);
|
|
214
258
|
return;
|
|
215
259
|
}
|
|
216
260
|
|
|
217
|
-
async reconfigureStream(stream: string, config: StreamConfig): Promise<StreamConfig
|
|
218
|
-
return (
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
)
|
|
261
|
+
async reconfigureStream(stream: string, config: StreamConfig): Promise<StreamConfig> {
|
|
262
|
+
return retryWithExponentialBackoff(
|
|
263
|
+
() => this._basin.reconfigureStream({ stream, streamConfig: config }, { serverURL: this.URL }),
|
|
264
|
+
this.config.maxRetries,
|
|
265
|
+
this.config.initialBackoffMs,
|
|
266
|
+
this.config.maxBackoffMs
|
|
267
|
+
);
|
|
224
268
|
}
|
|
225
269
|
}
|
|
226
270
|
|
|
@@ -245,29 +289,44 @@ class Stream {
|
|
|
245
289
|
});
|
|
246
290
|
}
|
|
247
291
|
|
|
248
|
-
async checkTail(): Promise<CheckTailResponse
|
|
292
|
+
async checkTail(): Promise<CheckTailResponse> {
|
|
249
293
|
return (
|
|
250
294
|
await this._stream.checkTail({ stream: this.streamName }, { serverURL: this.basinURL })
|
|
251
|
-
)
|
|
295
|
+
);
|
|
252
296
|
}
|
|
253
297
|
|
|
254
|
-
async append(request: AppendRequest): Promise<AppendOutput
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
298
|
+
async append(request: AppendRequest): Promise<AppendOutput> {
|
|
299
|
+
switch (this.config.appedRetryPolicy) {
|
|
300
|
+
case AppendRetryPolicy.All:
|
|
301
|
+
case undefined:
|
|
302
|
+
return retryWithExponentialBackoff(
|
|
303
|
+
() => this._stream.append({ ...request, stream: this.streamName }, { serverURL: this.basinURL }),
|
|
304
|
+
this.config.maxRetries,
|
|
305
|
+
this.config.initialBackoffMs,
|
|
306
|
+
this.config.maxBackoffMs
|
|
307
|
+
);
|
|
308
|
+
case AppendRetryPolicy.NoSideEffects:
|
|
309
|
+
return (
|
|
310
|
+
await this._stream.append({ ...request, stream: this.streamName }, {
|
|
311
|
+
serverURL: this.basinURL,
|
|
312
|
+
})
|
|
313
|
+
);
|
|
314
|
+
default:
|
|
315
|
+
throw new Error("Invalid AppendRetryPolicy");
|
|
316
|
+
}
|
|
258
317
|
}
|
|
259
318
|
|
|
260
|
-
async read(request: ReadRequest): Promise<Output
|
|
319
|
+
async read(request: ReadRequest): Promise<Output> {
|
|
261
320
|
return (
|
|
262
|
-
await this._stream.read({ ...request, stream: this.streamName }, { serverURL: this.basinURL })
|
|
263
|
-
)
|
|
321
|
+
await this._stream.read({ ...request, stream: this.streamName }, { serverURL: this.basinURL }) as Output
|
|
322
|
+
);
|
|
264
323
|
}
|
|
265
324
|
|
|
266
325
|
async *readStream(request: ReadRequest): AsyncGenerator<ReadResponse, void, undefined> {
|
|
267
326
|
let currentRequest: ReadRequest = { ...request };
|
|
268
|
-
let
|
|
327
|
+
let initialBackoffMs = this.config.initialBackoffMs ?? 100;
|
|
269
328
|
const maxBackoffMs = 5000;
|
|
270
|
-
const maxRetries = 5;
|
|
329
|
+
const maxRetries = this.config.maxRetries ?? 5;
|
|
271
330
|
let retryCount = 0;
|
|
272
331
|
|
|
273
332
|
while (true) {
|
|
@@ -281,7 +340,7 @@ class Stream {
|
|
|
281
340
|
acceptHeaderOverride: ReadAcceptEnum.textEventStream
|
|
282
341
|
}
|
|
283
342
|
);
|
|
284
|
-
stream = response
|
|
343
|
+
stream = response as EventStream<ReadResponse>;
|
|
285
344
|
if (!stream) return;
|
|
286
345
|
|
|
287
346
|
for await (const event of stream) {
|
|
@@ -310,13 +369,16 @@ class Stream {
|
|
|
310
369
|
}
|
|
311
370
|
return;
|
|
312
371
|
} catch (error) {
|
|
313
|
-
if (error instanceof
|
|
314
|
-
|
|
372
|
+
if (error instanceof RetryableError) {
|
|
373
|
+
if (retryCount >= maxRetries) {
|
|
374
|
+
throw error;
|
|
375
|
+
}
|
|
376
|
+
retryCount++;
|
|
377
|
+
await new Promise(resolve => setTimeout(resolve, initialBackoffMs));
|
|
378
|
+
initialBackoffMs = Math.min(initialBackoffMs * 2, maxBackoffMs);
|
|
379
|
+
} else {
|
|
315
380
|
throw error;
|
|
316
381
|
}
|
|
317
|
-
retryCount++;
|
|
318
|
-
await new Promise(resolve => setTimeout(resolve, backoffMs));
|
|
319
|
-
backoffMs = Math.min(backoffMs * 2, maxBackoffMs);
|
|
320
382
|
}
|
|
321
383
|
}
|
|
322
384
|
}
|
|
@@ -336,4 +398,33 @@ function meteredBatchSize(batch: SequencedRecordBatch): number {
|
|
|
336
398
|
|
|
337
399
|
export function genS2RequestToken(): string {
|
|
338
400
|
return uuidv4().replace(/-/g, "");
|
|
339
|
-
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
async function retryWithExponentialBackoff<T>(
|
|
404
|
+
operation: () => Promise<T>,
|
|
405
|
+
maxAttempts: number = 5,
|
|
406
|
+
initialBackoffMs: number = 100,
|
|
407
|
+
maxBackoffMs: number = 5000
|
|
408
|
+
): Promise<T> {
|
|
409
|
+
let attempt = 0;
|
|
410
|
+
|
|
411
|
+
while (attempt < maxAttempts) {
|
|
412
|
+
try {
|
|
413
|
+
return await operation();
|
|
414
|
+
} catch (error) {
|
|
415
|
+
if (error instanceof RetryableError) {
|
|
416
|
+
attempt++;
|
|
417
|
+
if (attempt >= maxAttempts) throw error;
|
|
418
|
+
|
|
419
|
+
const jitter = Math.random() * 0.3 + 0.85;
|
|
420
|
+
const delayMs = Math.min(initialBackoffMs * Math.pow(2, attempt) * jitter, maxBackoffMs);
|
|
421
|
+
|
|
422
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
423
|
+
} else {
|
|
424
|
+
throw error;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
throw new Error("Max retry attempts reached");
|
|
430
|
+
}
|
package/src/lib/config.ts
CHANGED
|
@@ -54,7 +54,8 @@ export function serverURLFromOptions(options: SDKOptions): URL | null {
|
|
|
54
54
|
export const SDK_METADATA = {
|
|
55
55
|
language: "typescript",
|
|
56
56
|
openapiDocVersion: "1.0.0",
|
|
57
|
-
sdkVersion: "0.3.
|
|
57
|
+
sdkVersion: "0.3.13",
|
|
58
58
|
genVersion: "2.506.0",
|
|
59
|
-
userAgent:
|
|
59
|
+
userAgent:
|
|
60
|
+
"speakeasy-sdk/typescript 0.3.13 2.506.0 1.0.0 @s2-dev/streamstore",
|
|
60
61
|
} as const;
|
package/src/lib/matchers.ts
CHANGED
|
@@ -160,7 +160,6 @@ export type MatchedError<Matchers> = Matchers extends Matcher<any, infer E>[]
|
|
|
160
160
|
: never;
|
|
161
161
|
export type MatchFunc<T, E> = (
|
|
162
162
|
response: Response,
|
|
163
|
-
request: Request,
|
|
164
163
|
options?: { resultKey?: string; extraFields?: Record<string, unknown> },
|
|
165
164
|
) => Promise<[result: Result<T, E>, raw: unknown]>;
|
|
166
165
|
|
|
@@ -169,7 +168,6 @@ export function match<T, E>(
|
|
|
169
168
|
): MatchFunc<T, E | APIError | SDKValidationError> {
|
|
170
169
|
return async function matchFunc(
|
|
171
170
|
response: Response,
|
|
172
|
-
request: Request,
|
|
173
171
|
options?: { resultKey?: string; extraFields?: Record<string, unknown> },
|
|
174
172
|
): Promise<
|
|
175
173
|
[result: Result<T, E | APIError | SDKValidationError>, raw: unknown]
|
|
@@ -191,14 +189,15 @@ export function match<T, E>(
|
|
|
191
189
|
}
|
|
192
190
|
|
|
193
191
|
if (!matcher) {
|
|
194
|
-
await
|
|
192
|
+
const responseBody = await response.text();
|
|
195
193
|
return [{
|
|
196
194
|
ok: false,
|
|
197
|
-
error: new APIError(
|
|
195
|
+
error: new APIError(
|
|
196
|
+
"Unexpected API response status or content-type",
|
|
198
197
|
response,
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
},
|
|
198
|
+
responseBody,
|
|
199
|
+
),
|
|
200
|
+
}, responseBody];
|
|
202
201
|
}
|
|
203
202
|
|
|
204
203
|
const encoding = matcher.enc;
|
|
@@ -224,7 +223,7 @@ export function match<T, E>(
|
|
|
224
223
|
raw = await discardResponseBody(response);
|
|
225
224
|
break;
|
|
226
225
|
case "fail":
|
|
227
|
-
raw = await
|
|
226
|
+
raw = await response.text();
|
|
228
227
|
break;
|
|
229
228
|
default:
|
|
230
229
|
encoding satisfies never;
|
|
@@ -234,7 +233,11 @@ export function match<T, E>(
|
|
|
234
233
|
if (matcher.enc === "fail") {
|
|
235
234
|
return [{
|
|
236
235
|
ok: false,
|
|
237
|
-
error: new APIError(
|
|
236
|
+
error: new APIError(
|
|
237
|
+
"API error occurred",
|
|
238
|
+
response,
|
|
239
|
+
typeof raw === "string" ? raw : "",
|
|
240
|
+
),
|
|
238
241
|
}, raw];
|
|
239
242
|
}
|
|
240
243
|
|
|
@@ -253,11 +256,14 @@ export function match<T, E>(
|
|
|
253
256
|
...(matcher.hdrs ? { Headers: unpackHeaders(response.headers) } : null),
|
|
254
257
|
[resultKey]: raw,
|
|
255
258
|
};
|
|
256
|
-
} else {
|
|
259
|
+
} else if (matcher.hdrs) {
|
|
257
260
|
data = {
|
|
258
261
|
...options?.extraFields,
|
|
259
262
|
...(matcher.hdrs ? { Headers: unpackHeaders(response.headers) } : null),
|
|
263
|
+
...(isPlainObject(raw) ? raw : null),
|
|
260
264
|
};
|
|
265
|
+
} else {
|
|
266
|
+
data = raw;
|
|
261
267
|
}
|
|
262
268
|
|
|
263
269
|
if ("err" in matcher) {
|
|
@@ -14,7 +14,6 @@ export * from "./createbasinrequest.js";
|
|
|
14
14
|
export * from "./createstreamrequest.js";
|
|
15
15
|
export * from "./formatoption.js";
|
|
16
16
|
export * from "./header.js";
|
|
17
|
-
export * from "./httpmetadata.js";
|
|
18
17
|
export * from "./listbasinsresponse.js";
|
|
19
18
|
export * from "./liststreamsresponse.js";
|
|
20
19
|
export * from "./output.js";
|
|
@@ -3,19 +3,25 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
export class APIError extends Error {
|
|
6
|
+
public readonly statusCode: number;
|
|
7
|
+
public readonly contentType: string;
|
|
8
|
+
|
|
6
9
|
constructor(
|
|
7
10
|
message: string,
|
|
8
|
-
public readonly
|
|
9
|
-
|
|
10
|
-
request: Request;
|
|
11
|
-
},
|
|
11
|
+
public readonly rawResponse: Response,
|
|
12
|
+
public readonly body: string = "",
|
|
12
13
|
) {
|
|
14
|
+
const statusCode = rawResponse.status;
|
|
15
|
+
const contentType = rawResponse.headers.get("content-type") || "";
|
|
16
|
+
const bodyString = body.length > 0 ? `\n${body}` : "";
|
|
17
|
+
|
|
13
18
|
super(
|
|
14
|
-
`${message}: Status ${
|
|
15
|
-
httpMeta.response.headers.get("content-type") || ""
|
|
16
|
-
}`,
|
|
19
|
+
`${message}: Status ${statusCode} Content-Type ${contentType} Body ${bodyString}`,
|
|
17
20
|
);
|
|
18
21
|
|
|
22
|
+
this.statusCode = statusCode;
|
|
23
|
+
this.contentType = contentType;
|
|
24
|
+
|
|
19
25
|
this.name = "APIError";
|
|
20
26
|
}
|
|
21
27
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as z from "zod";
|
|
6
|
+
|
|
7
|
+
export type RetryableErrorData = {
|
|
8
|
+
error: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export class RetryableError extends Error {
|
|
12
|
+
error: string;
|
|
13
|
+
|
|
14
|
+
/** The original data that was passed to this error instance. */
|
|
15
|
+
data$: RetryableErrorData;
|
|
16
|
+
|
|
17
|
+
constructor(err: RetryableErrorData) {
|
|
18
|
+
const message = "message" in err && typeof err.message === "string"
|
|
19
|
+
? err.message
|
|
20
|
+
: `API error occurred: ${JSON.stringify(err)}`;
|
|
21
|
+
super(message);
|
|
22
|
+
this.data$ = err;
|
|
23
|
+
|
|
24
|
+
this.error = err.error;
|
|
25
|
+
|
|
26
|
+
this.name = "RetryableError";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** @internal */
|
|
31
|
+
export const RetryableError$inboundSchema: z.ZodType<
|
|
32
|
+
RetryableError,
|
|
33
|
+
z.ZodTypeDef,
|
|
34
|
+
unknown
|
|
35
|
+
> = z.object({
|
|
36
|
+
error: z.string(),
|
|
37
|
+
})
|
|
38
|
+
.transform((v) => {
|
|
39
|
+
return new RetryableError(v);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
/** @internal */
|
|
43
|
+
export type RetryableError$Outbound = {
|
|
44
|
+
error: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/** @internal */
|
|
48
|
+
export const RetryableError$outboundSchema: z.ZodType<
|
|
49
|
+
RetryableError$Outbound,
|
|
50
|
+
z.ZodTypeDef,
|
|
51
|
+
RetryableError
|
|
52
|
+
> = z.instanceof(RetryableError)
|
|
53
|
+
.transform(v => v.data$)
|
|
54
|
+
.pipe(z.object({
|
|
55
|
+
error: z.string(),
|
|
56
|
+
}));
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @internal
|
|
60
|
+
* @deprecated This namespace will be removed in future versions. Use schemas and types that are exported directly from this module.
|
|
61
|
+
*/
|
|
62
|
+
export namespace RetryableError$ {
|
|
63
|
+
/** @deprecated use `RetryableError$inboundSchema` instead. */
|
|
64
|
+
export const inboundSchema = RetryableError$inboundSchema;
|
|
65
|
+
/** @deprecated use `RetryableError$outboundSchema` instead. */
|
|
66
|
+
export const outboundSchema = RetryableError$outboundSchema;
|
|
67
|
+
/** @deprecated use `RetryableError$Outbound` instead. */
|
|
68
|
+
export type Outbound = RetryableError$Outbound;
|
|
69
|
+
}
|