Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify promise queue implementation #102

Merged
merged 8 commits into from
Oct 16, 2024
Merged

Conversation

ahuth
Copy link
Contributor

@ahuth ahuth commented Oct 11, 2024

This PR

  • Simplifies the promise queue implementation (used to prevent concurrent axe.run calls, which doesn't work), so it's easier to understand.
  • Moves some "axe" logic out of Result and into TestBrowser/AxePage, where it makes more sense (to me) for it to belong.

@ahuth ahuth marked this pull request as ready for review October 11, 2024 23:12
@ahuth
Copy link
Contributor Author

ahuth commented Oct 11, 2024

@booc0mtaco @timzchang @jeremiah-clothier looks like a maintainer needs to approve the CI workflow. Also, please review when you get a chance 🙏

Just to make sure promise rejections are handled.
@jeremiah-clothier
Copy link
Contributor

looks like a maintainer needs to approve the CI workflow. Also, please review when you get a chance 🙏

I can't see the settings on this repo, I'm not sure how this is currently configured

And into the AxePage code, with the rest of the axe-core logic.
Keep all Axe and playwright stuff in the "Browser" code.
'landmark-one-main',
'page-has-heading-one',
'region',
];
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved the default disabled rules into the AxePage file, so that Axe stuff is more centralized there.

story.config,
);
return new Result(axeResults.violations);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved this function into TestBrowser, so that Playwright code is centralized there.

return new Promise<T>((resolve, reject) => {
queue = queue.then(createPromise).then(resolve).catch(reject);
});
};
Copy link
Contributor Author

@ahuth ahuth Oct 12, 2024

Choose a reason for hiding this comment

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

A change with this new implementation is the it'll stop processing subsequent promises if one is rejected (unless we add rejection handing somewhere, which I might do at some point).

Regardless, I think this is fine, because:

  • The axe.run promise will not normally be rejected (even if there are axe violations). So something has gone very wrong with the axe run if it is.
  • This whole queue mechanism is a fallback that might not even be necessary. It shouldn't be possible to end up with multiple axe.run's at a time. This queue is probably overly paranoid.

story.runOptions,
story.context,
story.config,
);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

As noted elsewhere, I moved this code here. That way the Result object doesn't need to contain any Playwright stuff.

@booc0mtaco
Copy link
Contributor

@ahuth thanks for the refactor and contribution! will have a look this evening

Comment on lines +121 to +122
return new Promise<T>((resolve, reject) => {
queue = queue.then(createPromise).then(resolve).catch(reject);
Copy link
Contributor

Choose a reason for hiding this comment

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

Am I understanding correctly that the first .then invokes the promise at the end of the queue, and then createPromise is invoked, adding on to the queue?

Does the second .then then resolve the one just created by createPromise?

Sorry a lot of promises going around 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sort of!

.then creates a new promise off of the current queue (which of course is then set as the current queue). It's resolved with the value the created promise is resolved with...

Might be more clear if I wrote it out as

queue = queue.then(() => {
  return createPromise();
})

of if we made it less generic and inlined the promise creation (for illustration purposes), it would look something like

// For each story
queue = queue.then(() => {
  return axe.run(...);
})

Going even deeper, if we unrolled the loop it would be like

Promise.resolve()
  .then(() => axe.run(...)) // Story 1
  .then(() => axe.run(...)) // Story 2
  .then(() => axe.run(...)) // Story 3
  // etc.

Hope that helps!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess the other way to say it is that .then creates a promise, and createPromise creates a different promise, but they are linked

Copy link
Contributor

@timzchang timzchang left a comment

Choose a reason for hiding this comment

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

thanks for the explanation!

Copy link
Contributor

@booc0mtaco booc0mtaco left a comment

Choose a reason for hiding this comment

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

Less is more ++
Fail-early-and-often ++

Will look into cutting a new patch release at the end of the week.

@booc0mtaco booc0mtaco merged commit 52163be into chanzuckerberg:main Oct 16, 2024
2 checks passed
@ahuth ahuth deleted the ah-queue branch October 16, 2024 16:09
@ahuth
Copy link
Contributor Author

ahuth commented Oct 16, 2024

Ok, thanks! If you run into any issues doing that, lemme know. There's a wiki article in this repo about publishing.

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.

4 participants