Skip to content

Commit 628f9a2

Browse files
authored
fix(mutex): support per-call-site acquire timeouts (renovatebot#41259)
fix(mutex): Support per-call-site acquire timeouts Closes renovatebot#41210
1 parent ad6c40e commit 628f9a2

File tree

4 files changed

+18
-7
lines changed

4 files changed

+18
-7
lines changed

lib/modules/datasource/crate/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,14 @@ export class CrateDatasource extends Datasource {
338338
const cacheKey = `crate-datasource/registry-clone-path/${registryFetchUrl}`;
339339
const lockKey = registryFetchUrl;
340340

341-
const releaseLock = await acquireLock(lockKey, 'crate-registry');
341+
const executionTimeout =
342+
GlobalConfig.get('executionTimeout', 15) * 60 * 1000;
343+
const gitTimeout = GlobalConfig.get('gitTimeout', executionTimeout);
344+
const releaseLock = await acquireLock(
345+
lockKey,
346+
'crate-registry',
347+
gitTimeout,
348+
);
342349
try {
343350
const cached = memCache.get<CloneResult>(cacheKey);
344351

lib/util/http/http.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ export abstract class HttpBase<
159159
throw new Error(HOST_DISABLED);
160160
}
161161
options = applyAuthorization(options);
162-
options.timeout ??= 60000;
162+
const timeout = options.timeout ?? 60000;
163+
options.timeout = timeout;
163164

164165
let cacheProvider: HttpCacheProvider | undefined;
165166
if (isReadMethod && options.cacheProvider) {
@@ -205,6 +206,7 @@ export abstract class HttpBase<
205206
releaseLock = await acquireLock(
206207
`${options.method} ${url}`,
207208
'http-mutex',
209+
timeout * 2,
208210
);
209211
}
210212
try {

lib/util/http/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export type GotStreamOptions = Options & GotExtraOptions;
2525
export interface GotExtraOptions {
2626
abortOnError?: boolean;
2727
abortIgnoreStatusCodes?: number[];
28+
timeout?: number;
2829
token?: string;
2930
hostType?: string;
3031
enabled?: boolean;

lib/util/mutex.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { Mutex, type MutexInterface, withTimeout } from 'async-mutex';
22

33
const DEFAULT_NAMESPACE = 'default';
4-
let mutexes: Record<string, Record<string, MutexInterface>> = {};
4+
const DEFAULT_TIMEOUT_MS = 2 * 60 * 1000;
5+
let mutexes: Record<string, Record<string, Mutex>> = {};
56

67
export function initMutexes(): void {
78
mutexes = {};
@@ -10,16 +11,16 @@ export function initMutexes(): void {
1011
export function getMutex(
1112
key: string,
1213
namespace: string = DEFAULT_NAMESPACE,
13-
): MutexInterface {
14+
): Mutex {
1415
mutexes[namespace] ??= {};
15-
// create a new mutex if it doesn't exist with a timeout of 2 minutes
16-
mutexes[namespace][key] ??= withTimeout(new Mutex(), 1000 * 60 * 2);
16+
mutexes[namespace][key] ??= new Mutex();
1717
return mutexes[namespace][key];
1818
}
1919

2020
export function acquireLock(
2121
key: string,
2222
namespace: string = DEFAULT_NAMESPACE,
23+
timeoutMs: number = DEFAULT_TIMEOUT_MS,
2324
): Promise<MutexInterface.Releaser> {
24-
return getMutex(key, namespace).acquire();
25+
return withTimeout(getMutex(key, namespace), timeoutMs).acquire();
2526
}

0 commit comments

Comments
 (0)