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

Remove the bluebird dependency from everywhere 🔥 #14882

Closed
ErisDS opened this issue May 23, 2022 · 20 comments · Fixed by #21790
Closed

Remove the bluebird dependency from everywhere 🔥 #14882

ErisDS opened this issue May 23, 2022 · 20 comments · Fixed by #21790
Labels
Hacktoberfest Issues suitable for hacktoberfest participants help wanted [triage] Ideal issues for contributors to help with pinned [triage] Ignored by stalebot

Comments

@ErisDS
Copy link
Member

ErisDS commented May 23, 2022

Now that there are native promises in Node.js and with async/await, bluebird really is a blast from the past. However, it's embedded pretty hard across our dependencies and some of our code uses catch predicates, which means we have to be careful about the order in which we rip bluebird out, otherwise we could break our error handling in weird and unexpected ways.

Here's some notes on what we need to do, most importantly starting with finding everywhere we depend on catch predicates:

Native:

  • Promise.all
  • Promise.then
  • Promise.reject
  • Promise.resolve

Bluebird

  • catch predicates -> replace with normal if statements
  • Promise.promisify -> require('util').promisify
  • Promise.props -> Promise.all example
  • Promise.join -> Promise.all
  • Promise.each -> Promise.all + array.map
  • Promise.map -> Promise.all + array.map
  • Promise.filter -> for and async/await
  • Promise.mapSeries -> use our sequence util (which needs an implementation of reduce, but is our only usage of it)
  • Promise.delay -> promisify getTimeout? Or get rid?

Refactor Approach

This refactor needs to be done in two phases:

  1. ✅ Remove all the catch predicates

💡 The best way to find catch predicates is with this regex: /\.catch\([^)]+,/.

  1. Remove bluebird from everywhere else:
  • Ghost monorepo - bluebird is required 117 times 😱
  • framework - bluebird required 5 times, but these are some of the most critical usages
  • SDK - just one usage, easy win!
  • gscan - 3 usages
  • knex-migrator - 3 usages

Why did we have to do catch predicates first?

Catch predicates result in error handling that assume the Promise they are handling is a Bluebird promise. If that isn't the case, Ghost will error, and quite possibly crash.

Our code coverage isn't quite good enough to be certain that all the unhappy paths are tested and we'll find these, and it's too much cognitive load for anyone to figure out if removing Bluebird is safe whilst there are still catch predicates in the codebase.


How to work on this issue

The slow and steady approach to refactoring is the only thing that really works. Branches should be very short lived (<1 day if possible). Therefore, please do not attempt to do this entire refactor in a single PR. It is not possible for us to review!

Instead, please find a single file with many references, or a small subfolder of the codebase with a handful of usages, make the changes, and submit a PR. Then repeat.

Please follow our contribution guidelines as closely as you can, particularly being sure to reference this issue in your commit. Refactor commits should not use emojis as they are not user-facing changes.

Note: This refactor has almost no user facing impact and (hopefully) no tests should break or change.

A reference refactor commit can be found here: 10aad8d

Thank you 🙏 ❤️ 🙏

@ErisDS ErisDS added the help wanted [triage] Ideal issues for contributors to help with label May 23, 2022
@Emmanuel-Melon
Copy link
Contributor

I can work with this, I had a similar task at my previous workplace 😁

Navarjun pushed a commit to Navarjun/Ghost that referenced this issue May 28, 2022
Issue TryGhost#14882
- Bluebird promise was being used for getting cached image sizes using .props method. It has been removed to be replaced by native promise using Promise.all
@ErisDS
Copy link
Member Author

ErisDS commented Jun 3, 2022

I've updated the OP here to be clearer that we need to remove catch predicates first, and why as there have been a couple of PRs that missed that detail.

@Emmanuel-Melon
Copy link
Contributor

I've updated the OP here to be clearer that we need to remove catch predicates first, and why as there have been a couple of PRs that missed that detail.

Apologies for the delay, I've been away for a bit. Resuming working on this task today.

ErisDS pushed a commit that referenced this issue Aug 1, 2022
refs: #14882

* refactored security.password to use native bcrypt promises
* refactored security.string to use more modern es features
ErisDS pushed a commit to Dave3of5/Ghost that referenced this issue Aug 5, 2022
ErisDS pushed a commit that referenced this issue Aug 5, 2022
refs #14882

- catch predicates make removing Bluebird from other parts of the code risky.
@ErisDS ErisDS added the Hacktoberfest Issues suitable for hacktoberfest participants label Aug 10, 2022
ErisDS added a commit to ErisDS/Ghost that referenced this issue Aug 24, 2022
refs: TryGhost#14882

- I found a common pattern where catch predicates were being used to catch non-existent models in destroy methods, and sometimes elsewhere in the API endpoints
- The use of predicates is deprecated, and we're working to remove them from everywhere, so that we can remove bluebird
- In order to still handle these errors correctly, we needed a small change to mw-error-handler so that it can detect EmptyResponse errors from bookshelf, as well as 404s
Note: there is a small change as a result of this - the context on these errors now says "Resource not found" instead of "{ModelName} not found".
- I think this is acceptable for now, as we will be reviewing these errors in more depth later. It's quite easy to make changes, we just have to decide what with proper design input
ErisDS added a commit to ErisDS/Ghost that referenced this issue Aug 24, 2022
refs: TryGhost#14882

- The use of predicates is deprecated, and we're working to remove them from everywhere, so that we can remove bluebird
- This should be the final piece of the puzzle in terms of predicates, from here we can start removing bluebird without concern that a predicate somewhere will explode
- Note: some of this code is poorly tested, but the refactors are very straightforward and minimal
ErisDS added a commit that referenced this issue Aug 24, 2022
refs: #14882

- I found a common pattern where catch predicates were being used to catch non-existent models in destroy methods, and sometimes elsewhere in the API endpoints
- The use of predicates is deprecated, and we're working to remove them from everywhere, so that we can remove bluebird
- In order to still handle these errors correctly, we needed a small change to mw-error-handler so that it can detect EmptyResponse errors from bookshelf, as well as 404s
Note: there is a small change as a result of this - the context on these errors now says "Resource not found" instead of "{ModelName} not found".
- I think this is acceptable for now, as we will be reviewing these errors in more depth later. It's quite easy to make changes, we just have to decide what with proper design input
ErisDS added a commit that referenced this issue Aug 24, 2022
refs: #14882

- The use of predicates is deprecated, and we're working to remove them from everywhere, so that we can remove bluebird
- This should be the final piece of the puzzle in terms of predicates, from here we can start removing bluebird without concern that a predicate somewhere will explode
- Note: some of this code is poorly tested, but the refactors are very straightforward and minimal
@ErisDS
Copy link
Member Author

ErisDS commented Aug 24, 2022

Hey all 👋 this issue was blocked on needing to remove the catch predicates first, so I've just merged a PR that removes all of them.

I've also updated the issue with the current state of things.

I'll go through the couple of blocked open PRs that remove some bits of bluebird asap. In the meantime, it'd be great to get some momentum on this and get rid of bluebird finally!

chairulakmal added a commit to chairulakmal/Ghost that referenced this issue Aug 29, 2023
daniellockyer pushed a commit that referenced this issue Aug 29, 2023
refs #14882

- this removes the last usage of Bluebird within Ghost and removes the dependency as it's no longer required within the codebase
daniellockyer pushed a commit to TryGhost/gscan that referenced this issue Aug 31, 2023
daniellockyer pushed a commit to TryGhost/gscan that referenced this issue Aug 31, 2023
daniellockyer added a commit to TryGhost/gscan that referenced this issue Aug 31, 2023
refs TryGhost/Ghost#14882

- this dependency is no longer needed because we're removed all
  functions that were supplied from it
markstos added a commit to markstos/express-hbs that referenced this issue Sep 3, 2023
Also, update eslintrc to support arrow notation.

Ref: TryGhost/Ghost#14882
markstos added a commit to markstos/express-hbs that referenced this issue Sep 3, 2023
Also, update eslintrc to support arrow notation.

Ref: TryGhost/Ghost#14882
@markstos
Copy link
Contributor

markstos commented Sep 3, 2023

I've submitted a PR to the nodemailer-mailgun-transport project to resolve this issue in that part of the dependency stack: orliesaurus/nodemailer-mailgun-transport#126

@markstos
Copy link
Contributor

markstos commented Sep 3, 2023

I've reviewed the status of this, and after the open PRs linked above are merged, it appears that perhaps than can be closed after lerna is used for final new package releases that contain the fix and and dependencies on those packages are updated one more time.

  • 🚧 Ghost monorepo - a yarn.lock mention remains which should get resolved per above.
  • ✅ framework
  • ✅ SDK
  • ✅ gscan
  • ✅ knex-migrator

daniellockyer pushed a commit to TryGhost/express-hbs that referenced this issue Sep 5, 2023
refs TryGhost/Ghost#14882

- this switches out the Bluebird specific code for a native variant so we can remove the dependency
@peterzimon peterzimon unpinned this issue Sep 26, 2023
@07tAnYa
Copy link

07tAnYa commented Oct 12, 2023

kindly assign this to me , I can work on this

@markstos
Copy link
Contributor

@07tAnYa Per my comment above, there is really nothing left to do. What change are you planning to make?

daniellockyer added a commit to TryGhost/knex-migrator that referenced this issue Dec 4, 2023
@nikkivaddepelli
Copy link

I would like to work on this issue. Can you please assign this to me?

@RahulJOD
Copy link

RahulJOD commented Oct 1, 2024

Hi, Please assign this issue to me. I want to contribute.

@kalvakeerthi
Copy link

I would like to work on this issue. Can you please assign this to me?

1 similar comment
@MINEGHOST007
Copy link

I would like to work on this issue. Can you please assign this to me?

@markstos
Copy link
Contributor

markstos commented Oct 6, 2024

@07tAnYa @nikkivaddepelli @RahulJOD @kalvakeerthi @MINEGHOST007 There is no need to wait for an issue to be assigned to you to contribute. See above what @chairulakmal did. They went ahead and submitted a pull request to help the project along and that pull request was merged. If there are places you can see where Bluebird can be removed following the recommended refactors above, go ahead and submit a PR. I don't speak as an official project rep, but as someone very experienced in maintaining and contributing to open source project.

Also, I'd love it if someone could explain why so many people are showing up here and requesting to be assigned this particular task. I'm involved with a lot of open source projects and don't see this elsewhere. This reminds of the project's prior problems with tea.xyz spam PRs.

@markstos
Copy link
Contributor

markstos commented Oct 6, 2024

With a second look, @ErisDS It appears this issue can be closed, I don't find any references to bluebird in any package.json dependencies any more:

# From top of Ghost repo
find . -name 'package.json' | xargs grep bluebird

From this test, it appears that all bluebird deps have been completely removed. From reviewing the git history, it seems the last use of Bluebird may have been removed over a year ago via 687cf5a

@bharateshwq
Copy link

Hey @markstos ,
i suppose the unprecedented traffic is because of the hacktoberfest event

ErisDS added a commit to ErisDS/Ghost that referenced this issue Dec 3, 2024
closes TryGhost#14882
ref TryGhost#14882 (comment)

- As per the comment on the issue, the last reference to bluebird in Ghost itself
  was removed over a year ago.
- We added this code blocking bluebird debug over 6 years ago.
- We do still use bluebird through dependencies so we could still have memory
  issues BUT
- This change only affects development, and really should not be a problem
  anymore.
- Leaning towards deleting the weird old edge-case code as it should not be
  an issue, and finding out the hard way if I'm wrong :D
@ErisDS
Copy link
Member Author

ErisDS commented Dec 3, 2024

Whoops, I missed that this was still open! I've just submitted a PR removing the very last reference to bluebird in the codebase. That will close this issue when it gets merged :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Hacktoberfest Issues suitable for hacktoberfest participants help wanted [triage] Ideal issues for contributors to help with pinned [triage] Ignored by stalebot
Projects
None yet
Development

Successfully merging a pull request may close this issue.