Skip to content

Commit

Permalink
Merge pull request #50 from lalalilo/add_invalidation_retry
Browse files Browse the repository at this point in the history
Add invalidation retry
  • Loading branch information
NaitoKenzo committed Feb 2, 2023
2 parents 51e5ab5 + c73d532 commit 17801a2
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 12 deletions.
50 changes: 48 additions & 2 deletions src/cloudfront.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { cloudfront } from "./aws-services";
import { awsResolve } from "./test-helper";
import { awsReject, awsResolve } from "./test-helper";
import {
findDeployedCloudfrontDistribution,
invalidateCloudfrontCache,
identifyingTag,
createCloudFrontDistribution,
setSimpleAuthBehavior,
getCacheInvalidations
getCacheInvalidations,
invalidateCloudfrontCacheWithRetry
} from "./cloudfront";
import { lambdaPrefix } from "./lambda";

Expand Down Expand Up @@ -154,6 +155,51 @@ describe("cloudfront", () => {
});
});

describe("invalidateCloudfrontCacheWithRetry", () => {
const createInvalidationMock = jest.spyOn(cloudfront, "createInvalidation");
const waitForMock = jest.spyOn(cloudfront, "waitFor");

afterEach(() => {
createInvalidationMock.mockReset();
waitForMock.mockReset();
});
it("should retry once", async () => {
createInvalidationMock
.mockReturnValueOnce(awsReject(1))
.mockReturnValueOnce(awsResolve({ Invalidation: {} }));

await invalidateCloudfrontCacheWithRetry(
"some-distribution-id",
"index.html, static/*"
);

expect(createInvalidationMock).toHaveBeenCalledTimes(2);
});

it("should retry 5 times at most", async () => {
createInvalidationMock
.mockReturnValueOnce(awsReject(1))
.mockReturnValueOnce(awsReject(1))
.mockReturnValueOnce(awsReject(1))
.mockReturnValueOnce(awsReject(1))
.mockReturnValueOnce(awsReject(1))
.mockReturnValueOnce(awsReject(1))
.mockReturnValueOnce(awsReject(1))
.mockReturnValueOnce(awsResolve({ Invalidation: {} }));

try {
await invalidateCloudfrontCacheWithRetry(
"some-distribution-id",
"index.html, static/*"
);
} catch (error) {
expect(error).toBeDefined();
}

expect(createInvalidationMock).toHaveBeenCalledTimes(5);
});
});

describe("createCloudFrontDistribution", () => {
const createDistributionMock = jest.spyOn(cloudfront, "createDistribution");
const waitForMock = jest.spyOn(cloudfront, "waitFor");
Expand Down
32 changes: 29 additions & 3 deletions src/cloudfront.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { cloudfront, bucketRegion, websiteEndpoint } from "./aws-services";
import { getAll } from "./aws-helper";
import { logger } from "./logger";
import {
import CloudFront, {
DistributionSummary,
DistributionConfig,
Tag,
LambdaFunctionAssociationList
} from "aws-sdk/clients/cloudfront";
import { lambdaPrefix } from "./lambda";
import { PromiseResult } from "aws-sdk/lib/request";
import { AWSError } from "aws-sdk";

export interface DistributionIdentificationDetail {
Id: string;
Expand Down Expand Up @@ -277,6 +279,30 @@ export const invalidateCloudfrontCache = async (
}
};

export const invalidateCloudfrontCacheWithRetry = async (
distributionId: string,
paths: string,
wait: boolean = false,
count: number = 0
): Promise<PromiseResult<
CloudFront.GetInvalidationResult,
AWSError
> | void> => {
try {
return await invalidateCloudfrontCache(distributionId, paths, wait);
} catch (error) {
if (count < 4) {
return await invalidateCloudfrontCacheWithRetry(
distributionId,
paths,
wait,
count + 1
);
}
throw error;
}
};

export const identifyingTag: Tag = {
Key: "managed-by-aws-spa",
Value: "v1"
Expand All @@ -290,8 +316,8 @@ export const setSimpleAuthBehavior = async (
.getDistributionConfig({ Id: distributionId })
.promise();

const lambdaConfigs = DistributionConfig!.DefaultCacheBehavior
.LambdaFunctionAssociations!.Items!;
const lambdaConfigs =
DistributionConfig!.DefaultCacheBehavior.LambdaFunctionAssociations!.Items!;

if (lambdaFunctionARN === null) {
logger.info(
Expand Down
15 changes: 8 additions & 7 deletions src/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { getCertificateARN, createCertificate } from "./acm";
import {
findDeployedCloudfrontDistribution,
createCloudFrontDistribution,
invalidateCloudfrontCache,
invalidateCloudfrontCacheWithRetry,
DistributionIdentificationDetail,
setSimpleAuthBehavior,
getCacheInvalidations
Expand Down Expand Up @@ -41,8 +41,9 @@ export const deploy = async (
const [domainName, s3Folder] = url.split("/");

logger.info(
`✨ Deploying "${folder}" on "${domainName}" with path "${s3Folder ||
"/"}"...`
`✨ Deploying "${folder}" on "${domainName}" with path "${
s3Folder || "/"
}"...`
);

if (!existsSync(folder)) {
Expand Down Expand Up @@ -75,9 +76,8 @@ export const deploy = async (
certificateArn = await createCertificate(domainName, hostedZone.Id);
}

let distribution: DistributionIdentificationDetail | null = await findDeployedCloudfrontDistribution(
domainName
);
let distribution: DistributionIdentificationDetail | null =
await findDeployedCloudfrontDistribution(domainName);
if (!distribution) {
distribution = await createCloudFrontDistribution(
domainName,
Expand All @@ -102,7 +102,8 @@ export const deploy = async (
}

await syncToS3(folder, domainName, cacheBustedPrefix, s3Folder);
await invalidateCloudfrontCache(

await invalidateCloudfrontCacheWithRetry(
distribution.Id,
getCacheInvalidations(cacheInvalidations, s3Folder),
wait
Expand Down

0 comments on commit 17801a2

Please sign in to comment.