Skip to content

Conversation

@DarkIsDude
Copy link
Contributor

@DarkIsDude DarkIsDude commented Jan 15, 2026

Issue: CLDSRV-823

Description

Motivation and context

Opening a first PR to migrate from callback to async/await syntax. A TAD is opened.

https://scality.atlassian.net/wiki/spaces/OS/pages/3523346468/2025-10-30+-+Async+Await+migration

This is a first PR to start the migration. As mention in the TAD, the idea is to migrate to async/await when working on a specific part of our component. Maybe a common goal of one PR per squad per sprint is a good idea.

All idea or remarks are welcome 🙏

@DarkIsDude DarkIsDude self-assigned this Jan 15, 2026
@bert-e
Copy link
Contributor

bert-e commented Jan 15, 2026

Hello darkisdude,

My role is to assist you with the merge of this
pull request. Please type @bert-e help to get information
on this process, or consult the user documentation.

Available options
name description privileged authored
/after_pull_request Wait for the given pull request id to be merged before continuing with the current one.
/bypass_author_approval Bypass the pull request author's approval
/bypass_build_status Bypass the build and test status
/bypass_commit_size Bypass the check on the size of the changeset TBA
/bypass_incompatible_branch Bypass the check on the source branch prefix
/bypass_jira_check Bypass the Jira issue check
/bypass_peer_approval Bypass the pull request peers' approval
/bypass_leader_approval Bypass the pull request leaders' approval
/approve Instruct Bert-E that the author has approved the pull request. ✍️
/create_pull_requests Allow the creation of integration pull requests.
/create_integration_branches Allow the creation of integration branches.
/no_octopus Prevent Wall-E from doing any octopus merge and use multiple consecutive merge instead
/unanimity Change review acceptance criteria from one reviewer at least to all reviewers
/wait Instruct Bert-E not to run until further notice.
Available commands
name description privileged
/help Print Bert-E's manual in the pull request.
/status Print Bert-E's current status in the pull request TBA
/clear Remove all comments from Bert-E from the history TBA
/retry Re-start a fresh build TBA
/build Re-start a fresh build TBA
/force_reset Delete integration branches & pull requests, and restart merge process from the beginning.
/reset Try to remove integration branches unless there are commits on them which do not appear on the source branch.

Status report is not available.

@bert-e
Copy link
Contributor

bert-e commented Jan 15, 2026

Incorrect fix version

The Fix Version/s in issue CLDSRV-823 contains:

  • None

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 9.2.15

  • 9.3.0

Please check the Fix Version/s of CLDSRV-823, or the target
branch of this pull request.

@DarkIsDude DarkIsDude changed the title 🎨 Async/Await migration 🎨 Async/Await migration on bucketGet Jan 15, 2026
@codecov
Copy link

codecov bot commented Jan 15, 2026

Codecov Report

❌ Patch coverage is 92.55319% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.50%. Comparing base (a8f32a3) to head (7a14efc).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
lib/api/bucketGet.js 90.90% 5 Missing ⚠️
lib/api/objectGetLegalHold.js 94.87% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

Files with missing lines Coverage Δ
lib/api/objectGetLegalHold.js 96.07% <94.87%> (+0.33%) ⬆️
lib/api/bucketGet.js 95.74% <90.90%> (-0.41%) ⬇️
@@                 Coverage Diff                 @@
##           development/9.2    #6045      +/-   ##
===================================================
+ Coverage            84.49%   84.50%   +0.01%     
===================================================
  Files                  206      206              
  Lines                13142    13157      +15     
===================================================
+ Hits                 11104    11118      +14     
- Misses                2038     2039       +1     
Flag Coverage Δ
file-ft-tests 67.70% <89.36%> (+0.02%) ⬆️
kmip-ft-tests 28.23% <5.31%> (-0.03%) ⬇️
mongo-v0-ft-tests 68.91% <89.36%> (-0.01%) ⬇️
mongo-v1-ft-tests 68.93% <89.36%> (+0.02%) ⬆️
multiple-backend 35.24% <30.85%> (+0.01%) ⬆️
sur-tests 35.79% <30.85%> (-0.02%) ⬇️
sur-tests-inflights 37.64% <30.85%> (-0.03%) ⬇️
unit 69.66% <74.46%> (+0.02%) ⬆️
utapi-v2-tests 34.50% <30.85%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@DarkIsDude DarkIsDude force-pushed the feature/CLDSRV-823/async-await-start branch from 16402cf to 4e7d644 Compare January 15, 2026 12:17
@DarkIsDude DarkIsDude requested review from a team, anurag4DSB, delthas and maeldonn and removed request for a team January 16, 2026 09:03
@DarkIsDude DarkIsDude marked this pull request as ready for review January 16, 2026 09:03
@DarkIsDude DarkIsDude requested review from a team and removed request for anurag4DSB January 16, 2026 09:03
@DarkIsDude DarkIsDude changed the title 🎨 Async/Await migration on bucketGet 🎨 Async/Await migration on bucketGet and objectGetLegalHold Jan 16, 2026
@bert-e
Copy link
Contributor

bert-e commented Jan 16, 2026

Request integration branches

Waiting for integration branch creation to be requested by the user.

To request integration branches, please comment on this pull request with the following command:

/create_integration_branches

Alternatively, the /approve and /create_pull_requests commands will automatically
create the integration branches.

@bert-e
Copy link
Contributor

bert-e commented Jan 19, 2026

Incorrect fix version

The Fix Version/s in issue CLDSRV-823 contains:

  • 9.2.15

  • 9.3.0

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 9.2.16

  • 9.3.0

Please check the Fix Version/s of CLDSRV-823, or the target
branch of this pull request.

@bert-e
Copy link
Contributor

bert-e commented Jan 20, 2026

Request integration branches

Waiting for integration branch creation to be requested by the user.

To request integration branches, please comment on this pull request with the following command:

/create_integration_branches

Alternatively, the /approve and /create_pull_requests commands will automatically
create the integration branches.

@francoisferrand francoisferrand self-requested a review January 20, 2026 20:34
const val = p.tag !== 'NextVersionIdMarker' || p.value === 'null' ?
p.value : versionIdUtils.encode(p.value);
p.value :
versionIdUtils.encode(p.value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not seem related to async/await: kind of dilutes the message here (ie show casing the migration)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(significant part of this change seems to be in that case...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, I re-read the whole file and try to simplify at the same time 🙏

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we split the PR, to keep the focus?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make really sense ? +160 −171 the PR is pretty small already ?

@bert-e
Copy link
Contributor

bert-e commented Jan 22, 2026

Incorrect fix version

The Fix Version/s in issue CLDSRV-823 contains:

  • 9.2.18

  • 9.3.0

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 9.2.19

  • 9.3.0

Please check the Fix Version/s of CLDSRV-823, or the target
branch of this pull request.

@bert-e
Copy link
Contributor

bert-e commented Jan 23, 2026

Request integration branches

Waiting for integration branch creation to be requested by the user.

To request integration branches, please comment on this pull request with the following command:

/create_integration_branches

Alternatively, the /approve and /create_pull_requests commands will automatically
create the integration branches.

@DarkIsDude DarkIsDude force-pushed the feature/CLDSRV-823/async-await-start branch 2 times, most recently from bafa722 to 08d8dc0 Compare January 23, 2026 17:17
@bert-e
Copy link
Contributor

bert-e commented Jan 23, 2026

Incorrect fix version

The Fix Version/s in issue CLDSRV-823 contains:

  • 9.2.20

  • 9.3.0

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 9.2.21

  • 9.3.0

Please check the Fix Version/s of CLDSRV-823, or the target
branch of this pull request.

@DarkIsDude DarkIsDude force-pushed the feature/CLDSRV-823/async-await-start branch from 08d8dc0 to 2196def Compare January 23, 2026 17:37
@bert-e
Copy link
Contributor

bert-e commented Jan 23, 2026

Incorrect fix version

The Fix Version/s in issue CLDSRV-823 contains:

  • 9.2.20

  • 9.3.0

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 9.2.22

  • 9.3.0

Please check the Fix Version/s of CLDSRV-823, or the target
branch of this pull request.

return res;
}

const validateBucket = (params, denials, log) => new Promise(resolve => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • we should use promisify instead of manually recoding it?
  • is it worth introducing a wrapper? Esp. in such case where it is called just once, I feel it just kind of "hides" the call to standardMetadataValidateBucket without much value; and I fear such helper would end up being harder to remove eventually (once migration is complete), because it would require changes the code in multiple places when not needed anymore [vs just searching for standardMetadataValidateBucket and updating all uses]
Suggested change
const validateBucket = (params, denials, log) => new Promise(resolve => {
const validateBucket = promisify(standardMetadataValidateBucket);

I.e. overall, since this is a temporary state, I would rather not try to make the migrated function look "perfect", but rather embrace the fact this is a transition, and temporarily keep promisify calls in the middle of these...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My goal was also to try to lighten the function as it's already a 100 lines function but I agree with you that it's maybe not the best choices 🙏.

if (error) {
log.debug('error processing request', { error });
monitoring.promMetrics('GET', bucketName, error.code, 'listBucket');
error.additionalResHeaders = corsHeaders;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was not done before: as we kind of "abused" the continuation callback semantics with an 3rd parameter on error...
→ so I wonder if this is a good exemple? or it is on purpose, to show how to handle such tricks as well?
→ to minimize risk, should we first do a refactor to stop doing this (without migrating to async/await); then proceed with a more streamlined migration to async/await?

I don't see how this is handled in "caller" code though (i.e. code "receiving" these CORS/additional headers on error), did I miss it do we already support such use of the additionalResHeaders field ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦 thanks for the spot. I forgot to add that in the callback 🙏.

I'm not sure we should do a first refactor, it'll add delay and it's the goal of a refactor IMO ? But I guess I can add that in our docs on Confluence ? So yes the goal is to make a "good" example.

processVersions,
processMasterVersions,
bucketGet,
bucketGet: (...args) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we go that road?

  • "rewiring" functions in imports/exports makes the code difficult to read IMHO, as the function is not called the same way it is "defined"
  • may not be an issue for this specific function, but this approach does not allow progressively migrating calls: even if the body of the function was updated already, it is still exported only as async or as continuation callback...
  • the slicing is dangerous, as it is based on the actual arguments of the call, not the parameters of the function. So if some code calls without callbacK (esp. likely while migrating...) we end up dropping the last (non-callback) parameter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point. So what is your suggestion ? Should I create a new wrapper bucketGet and rename the function bucketGetAsync ? Or integrate that directly in the function with a if (callback) { bucketGet(...).then().catch() } ? I'm not a big fan of this if as we introduce callback in an async/await code (but can be acceptable during migration I guess?). Or any other idea?

The idea of the slice was to avoid repeating the same arguments in the async and in the callback function but indeed the tradeoff is what you mention. Anyway if some code calls without callback, we'll have an issue in any case.

@bert-e
Copy link
Contributor

bert-e commented Jan 29, 2026

Branches have diverged

This pull request's source branch feature/CLDSRV-823/async-await-start has diverged from
development/9.2 by more than 50 commits.

To avoid any integration risks, please re-synchronize them using one of the
following solutions:

  • Merge origin/development/9.2 into feature/CLDSRV-823/async-await-start
  • Rebase feature/CLDSRV-823/async-await-start onto origin/development/9.2

Note: If you choose to rebase, you may have to ask me to rebuild
integration branches using the reset command.

@DarkIsDude DarkIsDude force-pushed the feature/CLDSRV-823/async-await-start branch from 2196def to 250de6f Compare January 29, 2026 11:03
@bert-e
Copy link
Contributor

bert-e commented Jan 29, 2026

Request integration branches

Waiting for integration branch creation to be requested by the user.

To request integration branches, please comment on this pull request with the following command:

/create_integration_branches

Alternatively, the /approve and /create_pull_requests commands will automatically
create the integration branches.

@DarkIsDude DarkIsDude force-pushed the feature/CLDSRV-823/async-await-start branch from 0ef0fb3 to 474bad8 Compare January 29, 2026 12:14
@DarkIsDude DarkIsDude force-pushed the feature/CLDSRV-823/async-await-start branch from 474bad8 to 7a14efc Compare January 29, 2026 12:14

objectGetLegalHold(...argsWithoutCallback)
.then(result => callback(null, ...result))
.catch(err => callback(err, null, err.additionalResHeaders));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.catch(err => callback(err, null, err.additionalResHeaders));
.catch(err => callback(err, null, err.additionalResHeaders ?? {}));

It's just defensive, maybe useless...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same thing can be found in the other file if you need to modify it. 🤷‍♂️


const { convertToXml } = s3middleware.objectLegalHold;

const standardMetadataValidateBucketAndObjPromised = (metadataValParams, actionImplicitDenies, log) =>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing one custom promisify for each file that is migrated, we can do the same thing in another way:

https://nodejs.org/docs/latest-v22.x/api/util.html#custom-promisified-functions

Doing it at function level will facilitate its migration and reduce impacts.

* @param {object} log - Werelogs logger
* @param {function} callback - callback to server
* @return {undefined}
* @return {Promise<object>} - object containing xml and additionalResHeaders

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding @throws documentation for better visibility on error handling.

let bucket;

try {
const standardMetadataValidateBucketPromised = promisify(standardMetadataValidateBucket);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a migration context, I think it's easier to keep all promisified functions at the top of the file.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And for performance of course

const standardMetadataValidateBucketPromised = promisify(standardMetadataValidateBucket);
bucket = await standardMetadataValidateBucketPromised(metadataValParams, request.actionImplicitDenies, log);
} catch (err) {
error = err;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal of this variable is to get cors headesr before throwing the error but it adds complexity. You could call collectCorsHeaders in the catch to avoid this.

@@ -278,28 +261,25 @@ function handleResult(listParams, requestMaxKeys, encoding, authInfo,
* @param {function} log - Werelogs request logger
* @param {function} callback - callback to respond to http request

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param {function} callback - callback to respond to http request

});
xmlParams.push({ tag: 'StartAfter', value: listParams.startAfter || '' });
xmlParams.push({ tag: 'FetchOwner', value: `${listParams.fetchOwner}` });
xmlParams.push({ tag: 'ContinuationToken', value: generateToken(listParams.continuationToken) || '', });

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trailing comma 👀

throw errors.NoSuchObjectLockConfiguration;
}

const additionalResHeaders = collectCorsHeaders(request.headers.origin, request.method, bucket);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep the initial behavior, this function should be call earlier to do the err.additionalResHeader trick.

}

let list;
try {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big fan of multiple try/catch in a single function, could it be simplified ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants