From f930943d02bf1b07dfc26efbb540282a04d5206b Mon Sep 17 00:00:00 2001 From: williamlardier Date: Thu, 28 Nov 2024 12:16:19 +0100 Subject: [PATCH] Add quota support in Backbeat - Backbeat may send internal API requests that will evaluate quotas. This change fixes these scenarios, as they were trying to push finalizer hooks to an empty object. Issue: CLDSRV-586 --- lib/routes/routeBackbeat.js | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/routes/routeBackbeat.js b/lib/routes/routeBackbeat.js index 34a75cb5ff..15e53b10c9 100644 --- a/lib/routes/routeBackbeat.js +++ b/lib/routes/routeBackbeat.js @@ -1372,6 +1372,10 @@ function routeBackbeat(clientIP, request, response, log) { _normalizeBackbeatRequest(request); const requestContexts = prepareRequestContexts('objectReplicate', request); + // Ensure backbeat operations like expiration can properly use quotas + // eslint-disable-next-line no-param-reassign + request.finalizerHooks = []; + // proxy api requests to Backbeat API server if (request.resourceType === 'api') { if (!config.backbeat) { @@ -1518,16 +1522,24 @@ function routeBackbeat(clientIP, request, response, log) { return backbeatRoutes[request.method][request.resourceType] [request.query.operation](request, response, log, next); }], - err => { - if (err) { - return responseJSONBody(err, null, response, log); - } - log.debug('backbeat route response sent successfully', - { method: request.method, - bucketName: request.bucketName, - objectKey: request.objectKey }); - return undefined; - }); + err => async.forEachLimit( + // Finalizer hooks are used in a quota context and ensure consistent + // metrics in case of API errors. No operation required if the API + // completed successfully. + request.finalizerHooks, + 5, + (hook, done) => hook(err, done), + () => { + if (err) { + return responseJSONBody(err, null, response, log); + } + log.debug('backbeat route response sent successfully', + { method: request.method, + bucketName: request.bucketName, + objectKey: request.objectKey }); + return undefined; + }, + )); }