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

bitbucket server api rate limiting #24860

Open
wants to merge 35 commits into
base: master
Choose a base branch
from

Conversation

kjjuno
Copy link

@kjjuno kjjuno commented May 21, 2024

Hey, I just made a Pull Request!

Adds the ability to rate limit calls to the bitbucket server api. If no rateLimit is provided in the configuration no rate limiting will be applied.

✔️ Checklist

  • A changeset describing the change and affected packages. (more info)
  • Added or updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)
  • All your commits have a Signed-off-by line in the message. (more info)

@kjjuno kjjuno requested review from a team and backstage-service as code owners May 21, 2024 20:56
@kjjuno kjjuno requested review from Rugvip and vinzscam May 21, 2024 20:56
@github-actions github-actions bot added the area:catalog Related to the Catalog Project Area label May 21, 2024
@kjjuno kjjuno force-pushed the feature/bitbucket-server-rate-limiting branch from 384b54c to 9c2ffd8 Compare May 21, 2024 21:13
@backstage-goalie
Copy link
Contributor

backstage-goalie bot commented May 21, 2024

Unexpected Changesets

The following changeset(s) reference packages that have not been changed in this PR:

  • /home/runner/work/backstage/backstage/.changeset/tidy-ducks-scream.md: @backstage/plugin-catalog-backend

Note that only changes that affect the published package require changesets, for example changes to tests and storybook stories do not require changesets.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@backstage/backend-defaults packages/backend-defaults patch v0.5.0-next.0
@backstage/integration packages/integration minor v1.14.0
@backstage/plugin-bitbucket-cloud-common plugins/bitbucket-cloud-common patch v0.2.22
@backstage/plugin-catalog-backend-module-bitbucket-server plugins/catalog-backend-module-bitbucket-server patch v0.2.2-next.0

@kjjuno
Copy link
Author

kjjuno commented May 21, 2024

Missing Changesets

The following package(s) are changed by this PR but do not have a changeset:

  • @backstage/integration

See CONTRIBUTING.md for more information about how to add changesets.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@backstage/integration packages/integration none v1.11.0
@backstage/plugin-catalog-backend-module-bitbucket-server plugins/catalog-backend-module-bitbucket-server minor v0.1.33-next.0

I'm not sure how the @backstage/integration package is showing as changed. I didn't think I had changed it. Is this a mistake because of the merge conflicts I dealt with, or am I legitimately missing something here?

@kjjuno kjjuno changed the title Adds bitbucket server rate limiting bitbucket server api rate limiting May 21, 2024
Copy link
Member

@vinzscam vinzscam left a comment

Choose a reason for hiding this comment

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

hey, question: are you getting the rate limiting when using the BitbucketServerEntityProvider? 🤔

Looking at the code it doesn't seem you should get any rate limiting

@vinzscam
Copy link
Member

Missing Changesets

The following package(s) are changed by this PR but do not have a changeset:

  • @backstage/integration

See CONTRIBUTING.md for more information about how to add changesets.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@backstage/integration packages/integration none v1.11.0
@backstage/plugin-catalog-backend-module-bitbucket-server plugins/catalog-backend-module-bitbucket-server minor v0.1.33-next.0

I'm not sure how the @backstage/integration package is showing as changed. I didn't think I had changed it. Is this a mistake because of the merge conflicts I dealt with, or am I legitimately missing something here?

you have changed packages/integration/src/bitbucketServer/config.ts, that's why 😄

@backstage-goalie
Copy link
Contributor

Thanks for the contribution!
All commits need to be DCO signed before they are reviewed. Please refer to the the DCO section in CONTRIBUTING.md or the DCO status for more info.

@kjjuno
Copy link
Author

kjjuno commented May 22, 2024

hey, question: are you getting the rate limiting when using the BitbucketServerEntityProvider? 🤔

Looking at the code it doesn't seem you should get any rate limiting

We added this plugin to scrape our bitbucket server instance, and almost immediately we started getting performance issues on our server. The team that owns that has asked us to make sure we only hit the api around 1 time per second.

This PR adds the ability rate limit those calls by making use of the Bottleneck library.

The rate limiting is implemented in the BitbucketServerClient itself.

Does this address your concern, or do you still have questions or concerns?

@kjjuno kjjuno force-pushed the feature/bitbucket-server-rate-limiting branch 2 times, most recently from f9bc959 to 7112134 Compare May 22, 2024 16:39
@vinzscam
Copy link
Member

BitbucketServerClient

my question was more about: are you using the BitbucketServerEntityProvider or are you using the BitbucketServerClient directly?

@kjjuno
Copy link
Author

kjjuno commented May 22, 2024

we are using the BitbucketServerEntityProvider

@kjjuno kjjuno requested a review from vinzscam May 23, 2024 00:39
Copy link
Member

@Rugvip Rugvip left a comment

Choose a reason for hiding this comment

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

Thank you! 👍

@kjjuno kjjuno force-pushed the feature/bitbucket-server-rate-limiting branch from 7112134 to b569090 Compare June 4, 2024 14:54
@github-actions github-actions bot added the documentation Improvements or additions to documentation label Jun 4, 2024
@kjjuno kjjuno requested a review from Rugvip June 4, 2024 21:34
@kjjuno kjjuno requested a review from freben June 5, 2024 18:18
Copy link
Contributor

This PR has been automatically marked as stale because it has not had recent activity from the author. It will be closed if no further activity occurs. If the PR was closed and you want it re-opened, let us know and we'll re-open the PR so that you can continue the contribution!

@github-actions github-actions bot added the stale label Jun 19, 2024
@freben freben removed the stale label Jun 19, 2024
@kjjuno
Copy link
Author

kjjuno commented Jun 21, 2024

@freben how would you feel about going back to the approach of putting the throttling into the client? We could make it so that you need to opt into that behavior. If there is no throttling configured no throttling would be applied.

The client itself seems to be the only place I can guarantee that throttling is properly applied

@github-actions github-actions bot added the stale label Jul 30, 2024
@kjjuno
Copy link
Author

kjjuno commented Jul 30, 2024

Still waiting for the backstage team to get back from vacation. This should not be marked stale.

@brunooliveiramac
Copy link

thumbs up for this

@freben freben removed the stale label Aug 6, 2024
@kjjuno
Copy link
Author

kjjuno commented Aug 12, 2024

Any chance I could get a new review? This is a critical enhancement for us. If there are still any outstanding concerns please let me know.

@kjjuno kjjuno requested a review from cal5barton August 13, 2024 15:01
Copy link
Member

@benjdlambert benjdlambert left a comment

Choose a reason for hiding this comment

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

Hey 👋

Apologies for the long turnaround on reviews for this, we've been pretty slammed after the holiday season, so we're just getting back to full capacity again!

I'm thinking that whilst we might get to having some form of FetchService in the backend, similar to the fetchApiRef in the frontend, we're not really there yet and we don't know what that's going to look like either. I don't want to be even more of a blocker for this work, so what I would suggest is that we narrow down the changes for what's required for this PR just to the @backstage/plugin-bitbucket* packages instead, and leave out the other changes for now.

It might need some restructuring of course, to maybe have this in some other config variable or to be set in some other way in the interim and out of the integrations.config for now, but I think that it's probably easier to go down that path, and then eventually deprecate that way once we have some more thoughts about what we're going to do with a global FetchService.

Does this make sense for now?

@kjjuno
Copy link
Author

kjjuno commented Aug 19, 2024

Hey 👋

Apologies for the long turnaround on reviews for this, we've been pretty slammed after the holiday season, so we're just getting back to full capacity again!

I'm thinking that whilst we might get to having some form of FetchService in the backend, similar to the fetchApiRef in the frontend, we're not really there yet and we don't know what that's going to look like either. I don't want to be even more of a blocker for this work, so what I would suggest is that we narrow down the changes for what's required for this PR just to the @backstage/plugin-bitbucket* packages instead, and leave out the other changes for now.

It might need some restructuring of course, to maybe have this in some other config variable or to be set in some other way in the interim and out of the integrations.config for now, but I think that it's probably easier to go down that path, and then eventually deprecate that way once we have some more thoughts about what we're going to do with a global FetchService.

Does this make sense for now?

Totally makes sense. I'll restructure things to make that service only for the bitbucket plugins. I can also change the config as @joshjung suggested. I should have something up hopefully as early as tomorrow

@joshjung
Copy link
Contributor

Totally makes sense. I'll restructure things to make that service only for the bitbucket plugins. I can also change the config as @joshjung suggested. I should have something up hopefully as early as tomorrow

Great! Once you have this done, what I can do is restructure the PR I have for the Gitlab plugin to match the same config format you use.

Kevin Johnson added 5 commits August 20, 2024 13:05
Signed-off-by: Kevin Johnson <kljohnson@verisk.com>
Signed-off-by: Kevin Johnson <kljohnson@verisk.com>
Signed-off-by: Kevin Johnson <kljohnson@verisk.com>
Signed-off-by: Kevin Johnson <kljohnson@verisk.com>
@github-actions github-actions bot added the BEP Backstage Enhancement Proposals label Aug 20, 2024
Signed-off-by: Kevin Johnson <kljohnson@verisk.com>
@kjjuno kjjuno force-pushed the feature/bitbucket-server-rate-limiting branch from 746a96c to dc28db7 Compare August 20, 2024 22:52
@kjjuno
Copy link
Author

kjjuno commented Aug 21, 2024

This is ready for another look now I think

Copy link
Member

@freben freben left a comment

Choose a reason for hiding this comment

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

Sorry for the delay and the large amount of comments. This turns out to be a very tricky thing, in part because of previous decisions that are none of your fault, but also because of just the tricky nature of the integrations package and polymorphism. That package is being revamped in some nearish future, making things a lot simpler. But here we are.

Let me summarize the comments:

  • The -common packages cannot use node-fetch at all
  • The integrations package needs to be kept almost perfectly pristine and must not contain any implementation code

The effect of this is:

  • Need to make a node typed package, preferably @backstage/integration-bitbucket-node and have all implementation there
  • Dial back the integrations package even more to exclusively the throttler type change
  • Change things to accept a typeof fetch making it entirely transparent to their implementations what the fetcher actually is doing.

@@ -20,6 +20,11 @@ integrations:
bitbucketCloud:
- username: ${BITBUCKET_CLOUD_USERNAME}
appPassword: ${BITBUCKET_CLOUD_PASSWORD}
fetch: # optional
Copy link
Member

Choose a reason for hiding this comment

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

Might as well remove this nesting level (in the docs below it's not here)

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 something I specifically requested because we were introducing a new object that was going to be shared across multiple configurations for customizing fetch. Since I have to add it in another spot, would it not make sense to have the nesting so that there is a consistent indicator across configuration locations, since most likely this throttling will end up in a lot of spots in the future? What if we also want to add more configurations for fetching?

@@ -32,6 +37,11 @@ integrations:
apiBaseUrl: https://bitbucket.mycompany.com/rest/api/1.0
username: ${BITBUCKET_SERVER_USERNAME}
password: ${BITBUCKET_SERVER_PASSWORD}
fetch: # optional
Copy link
Member

Choose a reason for hiding this comment

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

remove nesting

Comment on lines +29 to +30
BitbucketFetchFunction,
BitbucketFetchService,
Copy link
Member

Choose a reason for hiding this comment

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

I really would want to get rid of these types. The core of it is, the integrations package should be left as pristine as is humanly possible. See comments below.

getBitbucketCloudDefaultBranch,
getBitbucketCloudDownloadUrl,
getBitbucketCloudFileFetchUrl,
getBitbucketCloudRequestOptions,
ScmIntegrations,
} from '@backstage/integration';
import fetch, { Response } from 'node-fetch';
Copy link
Member

Choose a reason for hiding this comment

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

keep this import

@@ -58,6 +60,8 @@ export class BitbucketCloudUrlReader implements UrlReaderService {
});
};

private readonly fetch: BitbucketFetchFunction;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
private readonly fetch: BitbucketFetchFunction;
private readonly fetch: typeof fetch;

Comment on lines +51 to +52
"node-fetch": "^2.6.7",
"p-throttle": "^4.1.1"
Copy link
Member

Choose a reason for hiding this comment

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

remove

* This service can be configured to throttle the number of requests that can be made.
* @internal
*/
export class BitbucketFetchService {
Copy link
Member

Choose a reason for hiding this comment

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

If you make a @backstage/integration-bitbucket-node package, it could have a

function createThrottledFetch(options: {
  inner: typeof fetch,
  throttleByHost: {
    [host in string]: ThrottleConfig;
  }
}): typeof fetch

or something like that, and make it like a "middleware-like" thing around the inner fetch, like we do when we create the fetchApi for the frontend.

No need for caching fetch implementations in a map. Its internal state will be a Map<string, typeof pThrottle> instead.

@@ -42,11 +42,13 @@
},
"dependencies": {
"@backstage/integration": "workspace:^",
"cross-fetch": "^4.0.0"
"cross-fetch": "^4.0.0",
"node-fetch": "^2.6.7"
Copy link
Member

Choose a reason for hiding this comment

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

remove

},
"devDependencies": {
"@backstage/cli": "workspace:^",
"@openapitools/openapi-generator-cli": "^2.4.26",
"@types/node-fetch": "^2.5.12",
Copy link
Member

Choose a reason for hiding this comment

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

remove

@@ -32,9 +36,13 @@ export class BitbucketCloudClient {
return new BitbucketCloudClient(config);
}

private readonly fetch: BitbucketFetchFunction;
Copy link
Member

Choose a reason for hiding this comment

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

This one should also accept a fetch?: typeof fetch in its constructor. But we'll see if typescript gets cranky with the node-fetch vs cross-fetch types.

Copy link
Contributor

This PR has been automatically marked as stale because it has not had recent activity from the author. It will be closed if no further activity occurs. If the PR was closed and you want it re-opened, let us know and we'll re-open the PR so that you can continue the contribution!

@github-actions github-actions bot added the stale label Sep 20, 2024
@kjjuno
Copy link
Author

kjjuno commented Sep 20, 2024

I am still working through this. I have been distracted by other priorities at work, but this is still very much on my mind and I intend to have an update posted next week sometime.

@github-actions github-actions bot removed the stale label Sep 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:catalog Related to the Catalog Project Area BEP Backstage Enhancement Proposals documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants