Skip to content
This repository was archived by the owner on Feb 1, 2022. It is now read-only.

Commit ec9fc17

Browse files
feat: support sourcing from buckets with over 1000 objects (#20)
* adds ContinuationToken and extra error handling * updates list objects error handling Co-Authored-By: Robin Métral <[email protected]> * updates empty bucket error handling Co-Authored-By: Robin Métral <[email protected]> * adds types for getS3ListObjects params Co-Authored-By: Robin Métral <[email protected]> * adds types for listAllS3Items params Co-Authored-By: Robin Métral <[email protected]> * use optional chaining operator for contents check Co-Authored-By: Robin Métral <[email protected]> * uses ObjectType for allS3Items Co-Authored-By: Robin Métral <[email protected]> * feat: adds suggested changes from PR to use ContinuationToken * fix: runs prettier to correct indent * fix: adds type back to allBucketsObjects * corrects type on allBucketsObjects Co-Authored-By: Robin Métral <[email protected]> * Corrects check for data.Contents Co-Authored-By: Robin Métral <[email protected]> Co-authored-by: Robin Métral <[email protected]>
1 parent d0fda52 commit ec9fc17

File tree

1 file changed

+50
-22
lines changed

1 file changed

+50
-22
lines changed

src/gatsby-node.ts

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,62 @@ export async function sourceNodes(
2828
// get objects
2929
const s3 = new AWS.S3();
3030

31-
const listObjects = async bucket => {
32-
// todo improve this call
33-
// see https://stackoverflow.com/a/49888947
34-
const response = await s3
35-
.listObjectsV2({
36-
Bucket: bucket
37-
// todo handle continuation token
38-
// ContinuationToken: token,
39-
})
40-
.promise();
41-
42-
// add bucket key
43-
const objects = response.Contents?.reduce((acc: ObjectType[], cur) => {
44-
const object: ObjectType = { ...cur, Bucket: bucket };
45-
acc.push(object);
46-
return acc;
47-
}, []);
48-
49-
return objects;
31+
const getS3ListObjects = async (params: {
32+
Bucket: string;
33+
ContinuationToken?: string;
34+
}) => {
35+
return await s3
36+
.listObjectsV2(params)
37+
.promise()
38+
.catch(error => {
39+
reporter.error(
40+
`Error listing S3 objects on bucket "${params.Bucket}": ${error}`
41+
);
42+
});
43+
};
44+
45+
const listAllS3Objects = async (bucket: string) => {
46+
const allS3Objects: ObjectType[] = [];
47+
48+
const data = await getS3ListObjects({ Bucket: bucket });
49+
50+
if (data && data.Contents) {
51+
data.Contents.forEach(object => {
52+
allS3Objects.push({ ...object, Bucket: bucket });
53+
});
54+
} else {
55+
reporter.error(
56+
`Error processing objects from bucket "${bucket}". Is it empty?`
57+
);
58+
}
59+
60+
let nextToken = data && data.IsTruncated && data.NextContinuationToken;
61+
62+
while (nextToken) {
63+
const data = await getS3ListObjects({
64+
Bucket: bucket,
65+
ContinuationToken: nextToken
66+
});
67+
68+
if (data && data.Contents) {
69+
data.Contents.forEach(object => {
70+
allS3Objects.push({ ...object, Bucket: bucket });
71+
});
72+
}
73+
nextToken = data && data.IsTruncated && data.NextContinuationToken;
74+
}
75+
76+
return allS3Objects;
5077
};
5178

5279
try {
53-
let objects: Array<any> = await Promise.all(
54-
buckets.map(bucket => listObjects(bucket))
80+
const allBucketsObjects: ObjectType[][] = await Promise.all(
81+
buckets.map(bucket => listAllS3Objects(bucket))
5582
);
83+
5684
// flatten objects
5785
// flat() is not supported in node 10
58-
objects = [].concat(...objects);
86+
const objects = allBucketsObjects.reduce((acc, val) => acc.concat(val), []);
5987

6088
// create file nodes
6189
// todo touch nodes if they exist already

0 commit comments

Comments
 (0)