diff --git a/lib/errors/index.test.ts b/lib/errors/index.test.ts
index 2538b7a887..c2dd36edeb 100644
--- a/lib/errors/index.test.ts
+++ b/lib/errors/index.test.ts
@@ -27,8 +27,12 @@ describe('httperror', () => {
});
describe('RequestInProgressError', () => {
- it(`RequestInProgressError`, async () => {
+ it(`RequestInProgressError with retry`, async () => {
const responses = await Promise.all([request.get('/test/slow'), request.get('/test/slow')]);
+ expect(new Set(responses.map((r) => r.status))).toEqual(new Set([200, 200]));
+ });
+ it(`RequestInProgressError`, async () => {
+ const responses = await Promise.all([request.get('/test/slow4'), request.get('/test/slow4')]);
expect(new Set(responses.map((r) => r.status))).toEqual(new Set([200, 503]));
expect(new Set(responses.map((r) => r.headers['cache-control']))).toEqual(new Set([`public, max-age=${config.cache.routeExpire}`, `public, max-age=${config.requestTimeout / 1000}`]));
expect(responses.filter((r) => r.text.includes('RequestInProgressError: This path is currently fetching, please come back later!'))).toHaveLength(1);
@@ -63,19 +67,19 @@ describe('route throws an error', () => {
const value = $(item).find('.debug-value').html()?.trim();
switch (key) {
case 'Request Amount:':
- expect(value).toBe('9');
+ expect(value).toBe('11');
break;
case 'Hot Routes:':
- expect(value).toBe('6 /test/:id/:params?
');
+ expect(value).toBe('8 /test/:id/:params?
');
break;
case 'Hot Paths:':
- expect(value).toBe('2 /test/error
2 /test/slow
1 /test/httperror
1 /test/config-not-found-error
1 /test/invalid-parameter-error
1 /thisDoesNotExist
1 /
');
+ expect(value).toBe('2 /test/error
2 /test/slow
2 /test/slow4
1 /test/httperror
1 /test/config-not-found-error
1 /test/invalid-parameter-error
1 /thisDoesNotExist
1 /
');
break;
case 'Hot Error Routes:':
expect(value).toBe('5 /test/:id/:params?
');
break;
case 'Hot Error Paths:':
- expect(value).toBe('2 /test/error
1 /test/httperror
1 /test/slow
1 /test/config-not-found-error
1 /test/invalid-parameter-error
1 /thisDoesNotExist
');
+ expect(value).toBe('2 /test/error
1 /test/httperror
1 /test/slow4
1 /test/config-not-found-error
1 /test/invalid-parameter-error
1 /thisDoesNotExist
');
break;
default:
}
diff --git a/lib/middleware/cache.ts b/lib/middleware/cache.ts
index 23924294fe..6c5596f5af 100644
--- a/lib/middleware/cache.ts
+++ b/lib/middleware/cache.ts
@@ -23,7 +23,21 @@ const middleware: MiddlewareHandler = async (ctx, next) => {
const isRequesting = await cacheModule.globalCache.get(controlKey);
if (isRequesting === '1') {
- throw new RequestInProgressError('This path is currently fetching, please come back later!');
+ let retryTimes = process.env.NODE_ENV === 'test' ? 1 : 10;
+ let bypass = false;
+ while (retryTimes > 0) {
+ // eslint-disable-next-line no-await-in-loop
+ await new Promise((resolve) => setTimeout(resolve, process.env.NODE_ENV === 'test' ? 3000 : 6000));
+ // eslint-disable-next-line no-await-in-loop
+ if ((await cacheModule.globalCache.get(controlKey)) !== '1') {
+ bypass = true;
+ break;
+ }
+ retryTimes--;
+ }
+ if (!bypass) {
+ throw new RequestInProgressError('This path is currently fetching, please come back later!');
+ }
}
const value = await cacheModule.globalCache.get(key);
diff --git a/lib/routes/test/index.ts b/lib/routes/test/index.ts
index d7481e9425..8cba7553c4 100644
--- a/lib/routes/test/index.ts
+++ b/lib/routes/test/index.ts
@@ -376,6 +376,10 @@ async function handler(ctx) {
await wait(1000);
}
+ if (ctx.req.param('id') === 'slow4') {
+ await wait(4000);
+ }
+
if (ctx.req.query('mode') === 'fulltext') {
item = [
{