Skip to content

Commit

Permalink
fix: retry R2 binding requests
Browse files Browse the repository at this point in the history
Fixes #78
  • Loading branch information
flakey5 committed Nov 18, 2023
1 parent 0e9ec8b commit cca46c3
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/constants/limits.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Max amount of retries for S3 requests
*/
export const S3_RETRY_LIMIT = 3;
export const R2_RETRY_LIMIT = 3;

/**
* Max amount of keys to be returned in a S3 request
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/strategies/directoryListing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { getFile } from './serveFile';

// Imports the Precompiled Handlebars Template
import htmlTemplate from '../../templates/directoryListing.out.js';
import { S3_MAX_KEYS, S3_RETRY_LIMIT } from '../../constants/limits';
import { S3_MAX_KEYS, R2_RETRY_LIMIT } from '../../constants/limits';

// Applies the Template into a Handlebars Template Function
const handleBarsTemplate = Handlebars.template(htmlTemplate);
Expand Down Expand Up @@ -152,7 +152,7 @@ async function fetchR2Result(
cursor: string | undefined,
env: Env
): Promise<ListObjectsV2CommandOutput> {
let retriesRemaining = S3_RETRY_LIMIT;
let retriesRemaining = R2_RETRY_LIMIT;
while (retriesRemaining > 0) {
try {
// Send request to R2
Expand Down
56 changes: 54 additions & 2 deletions src/handlers/strategies/serveFile.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Env } from '../../env';
import { objectHasBody } from '../../util';
import responses from '../../commonResponses';
import { R2_RETRY_LIMIT } from '../../constants/limits';

/**
* Decides on what status code to return to
Expand Down Expand Up @@ -42,6 +43,57 @@ function getStatusCode(request: Request, objectHasBody: boolean): number {
return 304;
}

/**
* Fetch an object from a R2 bucket with retries
* The bindings _might_ have retries, if so this just adds
* a little bit more resiliency
* @param bucket The {@link R2Bucket} to read from
* @param key Object key
* @param options Conditional headers, etc.
*/
async function r2GetWithRetries(
bucket: R2Bucket,
key: string,
options?: R2GetOptions
): Promise<R2Object | null> {
for (let i = 0; i < R2_RETRY_LIMIT; i++) {
try {
return await bucket.get(key, options);
} catch (err) {
// Log error & retry
console.error(`R2 GetObject error: ${err}`);
}
}

// R2 isn't having a good day, return a 500 & log to sentry
throw new Error(`R2 GetObject failed after ${R2_RETRY_LIMIT} retries: `);
}

/**
* Fetch an object from a R2 bucket with retries
* The bindings _might_ have retries, if so this just adds
* a little bit more resiliency
* @param bucket The {@link R2Bucket} to read from
* @param key Object key
*/
async function r2HeadWithRetries(
bucket: R2Bucket,
key: string
): Promise<R2Object | null> {
for (let i = 0; i < R2_RETRY_LIMIT; i++) {
try {
const file = await bucket.head(key);
return file;
} catch (err) {
// Log error & retry
console.error(`R2 HeadObject error: ${err}`);
}
}

// R2 isn't having a good day, return a 500 & log to sentry
throw new Error(`R2 HeadObject failed after ${R2_RETRY_LIMIT} retries: `);
}

/**
* File handler
* @param url Parsed url of the request
Expand All @@ -60,7 +112,7 @@ export async function getFile(
switch (request.method) {
case 'GET':
try {
file = await env.R2_BUCKET.get(bucketPath, {
file = await r2GetWithRetries(env.R2_BUCKET, bucketPath, {
onlyIf: request.headers,
range: request.headers,
});
Expand All @@ -71,7 +123,7 @@ export async function getFile(
return responses.BAD_REQUEST;
}
case 'HEAD':
file = await env.R2_BUCKET.head(bucketPath);
file = await r2HeadWithRetries(env.R2_BUCKET, bucketPath);
break;
default:
return responses.METHOD_NOT_ALLOWED;
Expand Down

0 comments on commit cca46c3

Please sign in to comment.