Skip to content

Commit 0768097

Browse files
authored
bugfix: fix XAmzContentSHA256Mismatch (#249)
This appears to be a bug in the AWS s3 SDK. The root of the issue seems to be calling upload on lib-storage rather than an issue with the implementation. Switching from promise.all to a serial implentation fixes the issue, while also increasing the queue size off the default 3. For future improvements, I would also thing about exposing more of the uploadOptions inside the next deployment construct. Perhaps we should also give consumers the options of uploading serial vs parallel. Next steps I will also raise this with AWS team.
1 parent d5c116b commit 0768097

File tree

5 files changed

+970
-943
lines changed

5 files changed

+970
-943
lines changed

API.md

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/NextjsBucketDeployment.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ export interface NextjsBucketDeploymentProps {
7070
* @default false
7171
*/
7272
readonly zip?: boolean | undefined;
73+
/**
74+
* The number of files to upload in parallel.
75+
*/
76+
readonly queueSize?: number | undefined;
7377
}
7478

7579
/**
@@ -80,6 +84,7 @@ export interface CustomResourceProperties {
8084
destinationKeyPrefix?: string;
8185
prune?: boolean | undefined;
8286
putConfig?: NextjsBucketDeploymentProps['putConfig'];
87+
queueSize?: number | undefined;
8388
substitutionConfig?: NextjsBucketDeploymentProps['substitutionConfig'];
8489
sourceBucketName: string;
8590
sourceKeyPrefix?: string | undefined;
@@ -149,6 +154,7 @@ export class NextjsBucketDeployment extends Construct {
149154
prune: this.props.prune ?? false,
150155
substitutionConfig: this.props.substitutionConfig,
151156
zip: this.props.zip,
157+
queueSize: this.props.queueSize,
152158
};
153159
return new CustomResource(this, 'CustomResource', {
154160
properties,

src/generated-structs/OptionalNextjsBucketDeploymentProps.ts

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lambdas/nextjs-bucket-deployment.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
type PutObjectCommandInput,
2626
S3Client,
2727
} from '@aws-sdk/client-s3';
28-
import { Upload } from '@aws-sdk/lib-storage';
28+
import { Options, Upload } from '@aws-sdk/lib-storage';
2929
import type { CloudFormationCustomResourceHandler } from 'aws-lambda';
3030
import type * as JSZipType from 'jszip';
3131
// @ts-ignore jsii doesn't support esModuleInterop
@@ -73,6 +73,7 @@ export const handler: CloudFormationCustomResourceHandler = async (event, contex
7373
filePaths,
7474
baseLocalDir: sourceDirPath,
7575
putConfig: props.putConfig,
76+
queueSize: props.queueSize,
7677
});
7778
if (props.prune) {
7879
debug('Emptying/pruning bucket: ' + props.destinationBucketName);
@@ -272,12 +273,14 @@ async function uploadObjects({
272273
filePaths,
273274
baseLocalDir,
274275
putConfig = {},
276+
queueSize,
275277
}: {
276278
bucket: CustomResourceProperties['destinationBucketName'];
277279
keyPrefix?: CustomResourceProperties['destinationKeyPrefix'];
278280
filePaths: string[];
279281
baseLocalDir: string;
280282
putConfig: CustomResourceProperties['putConfig'];
283+
queueSize: CustomResourceProperties['queueSize'];
281284
}) {
282285
for await (const filePathChunk of chunkArray(filePaths, 100)) {
283286
const putObjectInputs: PutObjectCommandInput[] = filePathChunk.map((path) => {
@@ -293,7 +296,21 @@ async function uploadObjects({
293296
};
294297
});
295298

296-
await Promise.all(putObjectInputs.map((params) => new Upload({ client: s3, params }).done()));
299+
// Call put objects serially, prevents XAmzContentSHA256Mismatch errors
300+
// This seems to be a bug within the lib storage package, I have opened an issue here: https://github.com/aws/aws-sdk-js-v3/issues/6940
301+
await putObjectInputs.reduce(async (acc, params) => {
302+
await acc;
303+
const opts: Options = {
304+
client: s3,
305+
params,
306+
};
307+
if (queueSize) {
308+
opts.queueSize = queueSize;
309+
}
310+
const upload = new Upload(opts);
311+
console.log('uploading', params);
312+
return upload.done();
313+
}, Promise.resolve<any>(null));
297314
}
298315
}
299316

0 commit comments

Comments
 (0)