Skip to content

Commit baa60fb

Browse files
committed
feat: auto retry certain errors
1 parent 38ef992 commit baa60fb

File tree

313 files changed

+797
-21079
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

313 files changed

+797
-21079
lines changed

scripts/generate-clients.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Effect } from "effect";
44
import { commonAwsErrorNames, isCommonAwsErrorName } from "../src/error.ts";
55
import type { Manifest, Shape } from "./manifest.ts";
66
import { loadAllLocalManifests } from "./manifest.ts";
7+
import { retryableErrorTags } from "../src/client.ts";
78

89
// Configuration flags
910
const INCLUDE_DOCUMENTATION = false; // Set to false to disable JSDoc comments
@@ -580,6 +581,10 @@ const generateErrorInterface = (
580581
const shapeName = extractShapeName(shapeId);
581582
let code = "";
582583

584+
if (retryableErrorTags.includes(shapeName)) {
585+
return code;
586+
}
587+
583588
if (doc) {
584589
code += `${doc}\n`;
585590
}
@@ -1201,11 +1206,16 @@ const generateServiceTypes = (serviceName: string, manifest: Manifest) =>
12011206
code += `import type { Buffer } from "node:buffer";\n`;
12021207
}
12031208
const { inherited, overrides } = getServiceErrorOverrides(manifest);
1209+
const filteredInherited = inherited.filter(
1210+
(type) => !retryableErrorTags.includes(type),
1211+
);
12041212
if (overrides.length === 0) {
12051213
code += `import type { CommonAwsError } from "../../error.ts";\n`;
12061214
} else {
1207-
code += `import type { ${inherited.join(", ")} } from "../../error.ts";\n`;
1208-
code += `type CommonAwsError = ${inherited.concat(overrides).join(" | ")};\n`;
1215+
code += `import type { ${filteredInherited.join(", ")} } from "../../error.ts";\n`;
1216+
code += `type CommonAwsError = ${filteredInherited
1217+
.concat(overrides)
1218+
.join(" | ")};\n`;
12091219
}
12101220

12111221
code += `import { AWSServiceClient } from "../../client.ts";\n\n`;
@@ -1325,7 +1335,11 @@ const generateServiceTypes = (serviceName: string, manifest: Manifest) =>
13251335
errorTypes.push("CommonAwsError");
13261336

13271337
const errorUnion =
1328-
errorTypes.length > 1 ? errorTypes.join(" | ") : errorTypes[0];
1338+
errorTypes.length > 1
1339+
? errorTypes
1340+
.filter((type) => !retryableErrorTags.includes(type))
1341+
.join(" | ")
1342+
: errorTypes[0];
13291343
const effectOutputType =
13301344
!operation.shape.output ||
13311345
operation.shape.output.target === "smithy.api#Unit"
@@ -1500,7 +1514,10 @@ const generateServiceTypes = (serviceName: string, manifest: Manifest) =>
15001514
);
15011515
errorTypes.push("CommonAwsError");
15021516

1503-
const errorUnion = errorTypes.map((type) => ` | ${type}`).join("\n");
1517+
const errorUnion = errorTypes
1518+
.filter((type) => !retryableErrorTags.includes(type))
1519+
.map((type) => ` | ${type}`)
1520+
.join("\n");
15041521
const effectOutputType =
15051522
!operation.shape.output ||
15061523
operation.shape.output.target === "smithy.api#Unit"
@@ -1585,7 +1602,9 @@ const generateServiceTypes = (serviceName: string, manifest: Manifest) =>
15851602
.filter(([_, shape]) => shape.traits?.["smithy.api#error"])
15861603
.map(([shapeId, _]) => extractShapeName(shapeId));
15871604
allServiceErrors.push("CommonAwsError");
1588-
code += `export type ${consistentInterfaceName}Errors = ${allServiceErrors.join(" | ")};\n\n`;
1605+
code += `export type ${consistentInterfaceName}Errors = ${allServiceErrors
1606+
.filter((type) => !retryableErrorTags.includes(type))
1607+
.join(" | ")};\n\n`;
15891608

15901609
// Store metadata for the service
15911610
// FIXME: shouldn't this be typed to ServiceMetdata?

scripts/manifest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { FileSystem } from "@effect/platform";
22
import { Effect, Schema } from "effect";
3-
import { join } from "node:path";
3+
import { join } from "pathe";
44

55
// Base trait schema for common Smithy traits
66
const TraitValue = Schema.Union(

src/client.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ import { Credentials, fromStaticCredentials } from "./credentials.ts";
66
import type { AwsErrorMeta } from "./error.ts";
77
import { DefaultFetch, Fetch } from "./fetch.service.ts";
88
import type { ProtocolHandler } from "./protocols/interface.ts";
9+
import * as Schedule from "effect/Schedule";
10+
11+
export const retryableErrorTags = [
12+
"InternalFailure",
13+
"RequestExpired",
14+
"ServiceException",
15+
"ServiceUnavailable",
16+
"ThrottlingException",
17+
"TooManyRequestsException",
18+
];
919

1020
const errorTags: {
1121
[serviceName: string]: {
@@ -247,7 +257,13 @@ export function createServiceProxy<T>(
247257
);
248258
}
249259
});
250-
return program;
260+
261+
return program.pipe(
262+
Effect.retry({
263+
schedule: Schedule.exponential(100),
264+
while: (e) => retryableErrorTags.includes(e._tag),
265+
}),
266+
);
251267
};
252268
},
253269
},

src/error.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,20 @@ export class ValidationException extends Data.TaggedError(
5959
)<AwsErrorMeta> {}
6060

6161
export type CommonAwsError =
62+
//* handled in src/client.ts
63+
// | InternalFailure
64+
// | RequestExpired
65+
// | ServiceUnavailable
66+
// | ThrottlingException
6267
| AccessDeniedException
6368
| ExpiredTokenException
6469
| IncompleteSignature
65-
| InternalFailure
6670
| MalformedHttpRequestException
6771
| NotAuthorized
6872
| OptInRequired
6973
| RequestAbortedException
7074
| RequestEntityTooLargeException
71-
| RequestExpired
7275
| RequestTimeoutException
73-
| ServiceUnavailable
74-
| ThrottlingException
7576
| UnrecognizedClientException
7677
| UnknownOperationException
7778
| ValidationError

0 commit comments

Comments
 (0)