Skip to content

Commit 7ca7c78

Browse files
committed
Make S3ClientSend async-safe
1 parent 4030344 commit 7ca7c78

File tree

1 file changed

+24
-27
lines changed

1 file changed

+24
-27
lines changed

src/server/storage/s3-storage-provider.ts

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55

66
import { CacheOverride } from 'fastly:cache-override';
77
import { SecretStore } from 'fastly:secret-store';
8+
import { Command } from '@smithy/types';
89
import { FetchHttpHandler } from '@smithy/fetch-http-handler';
910
import {
1011
GetObjectCommand,
1112
GetObjectCommandInput,
1213
GetObjectCommandOutput,
1314
S3Client,
14-
S3ServiceException
15+
S3ClientResolvedConfig,
16+
S3ServiceException,
17+
ServiceInputTypes,
18+
ServiceOutputTypes,
1519
} from '@aws-sdk/client-s3';
1620

1721
import {
@@ -107,6 +111,9 @@ export type S3StorageProviderParams = {
107111
s3FastlyBackendName?: string,
108112
};
109113

114+
type S3ClientCommand<InputType extends ServiceInputTypes, OutputType extends ServiceOutputTypes> =
115+
Command<ServiceInputTypes, InputType, ServiceOutputTypes, OutputType, S3ClientResolvedConfig>;
116+
110117
export class S3StorageProvider implements StorageProvider {
111118
constructor(
112119
s3Region: string,
@@ -124,54 +131,44 @@ export class S3StorageProvider implements StorageProvider {
124131
private readonly s3Endpoint?: string;
125132
private readonly s3FastlyBackendName?: string;
126133

127-
private surrogateKeys?: string[];
128-
129-
private s3Client?: S3Client;
130-
async getS3Client() {
131-
if (this.s3Client != null) {
132-
return this.s3Client;
133-
}
134+
async sendS3Command<InputType extends ServiceInputTypes, OutputType extends ServiceOutputTypes>(
135+
command: S3ClientCommand<InputType, OutputType>,
136+
requestInit?: RequestInit,
137+
): Promise<OutputType> {
134138
const awsCredentials = await _awsCredentialsBuilder();
135-
this.s3Client = new S3Client({
139+
const s3Client = new S3Client({
136140
region: this.s3Region,
137141
endpoint: this.s3Endpoint,
138142
forcePathStyle: this.s3Endpoint != null,
139143
credentials: {
140144
accessKeyId: awsCredentials.accessKeyId,
141145
secretAccessKey: awsCredentials.secretAccessKey,
142146
},
143-
maxAttempts: 1,
147+
maxAttempts: 5,
144148
requestHandler: new FetchHttpHandler({
145-
requestInit: () => {
146-
return {
147-
backend: this.s3FastlyBackendName ?? "aws",
148-
cacheOverride: new CacheOverride({
149-
ttl: 3600,
150-
surrogateKey: (this.surrogateKeys ?? []).join(' ') || undefined,
151-
}),
152-
};
149+
requestInit() {
150+
return requestInit ?? {};
153151
},
154152
}),
155153
});
156-
return this.s3Client;
154+
return s3Client.send(command);
157155
}
158156

159157
async getEntry(key: string, tags?: string[]): Promise<StorageEntry | null> {
160-
161158
const input = {
162159
Bucket: this.s3Bucket, // required
163160
Key: key, // required
164161
} satisfies GetObjectCommandInput;
165162
const command = new GetObjectCommand(input);
166163
let response: GetObjectCommandOutput;
167164
try {
168-
const s3Client = await this.getS3Client();
169-
this.surrogateKeys = tags;
170-
try {
171-
response = await s3Client.send(command);
172-
} finally {
173-
this.surrogateKeys = undefined;
174-
}
165+
response = await this.sendS3Command(command, {
166+
backend: this.s3FastlyBackendName ?? "aws",
167+
cacheOverride: new CacheOverride({
168+
ttl: 3600,
169+
surrogateKey: (tags ?? []).join(' ') || undefined,
170+
}),
171+
});
175172
} catch(err) {
176173
if (err instanceof S3ServiceException && (err.name === "NotFound" || err.name === "NoSuchKey")) {
177174
console.log("Object does not exist");

0 commit comments

Comments
 (0)