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

added rate limit with exponential backoff and retry #286

Merged
merged 21 commits into from
Feb 25, 2021
Merged

Conversation

jspaaks
Copy link
Member

@jspaaks jspaaks commented Feb 20, 2021

Describe the changes made in this pull request

  • Added rate limit with exponential backoff and retry. Refs GitHub API rate limiting #93

  • Removed sleep from livetests and clitests

  • Added -a and --apikeys-filename to cli. Refs add -a | --apikeys-filename option to have higher rate limit #263 Now reading from env vars

  • the functions with which to interact with github, gitlab, etc are in requesting and are organized as follows:

    .
    └── get_from_platform
        ├── get_from_github
        │   ├── get_from_github_no_auth
        │   │   ├── get_from_github_no_auth_api
        │   │   ├── get_from_github_no_auth_frontend
        │   │   └── get_from_github_no_auth_raw
        │   └── get_from_github_with_auth
        │       ├── get_from_github_with_auth_api
        │       ├── get_from_github_with_auth_frontend
        │       └── get_from_github_with_auth_raw
        └── get_from_gitlab
            ├── get_from_gitlab_no_auth
            │   ├── get_from_gitlab_no_auth_api
            │   ├── get_from_gitlab_no_auth_frontend
            │   └── get_from_gitlab_no_auth_raw
            └── get_from_gitlab_with_auth
                ├── get_from_gitlab_with_auth_api
                ├── get_from_gitlab_with_auth_frontend
                └── get_from_gitlab_with_auth_raw
    

    This gives the developer control over the level at which to use the rate limiting decorators, for example different rates apply for each platform, a given platform may have different rate limits for unauthenticated/authenticated, as well as different rates for different parts of their service.

Instructions to review the pull request

Try running the unit tests

pytest tests/

Now replace get_calls() in the decorator in requesting/get_from_github_no_auth.py with 60. Running the tests again will halt halfway through because of rate limits. It will continue very slowly due to exponential backoff and retry, but the retries happen too slow for the ratelimit of 60 per hour, therefore they all ultimately fail with a too-many-calls error.

cli now has a -a | --apikeys-filename option that can be used to point to a secrets file with api keys

Apikeys are read from env vars named APIKEY_GITHUB and APIKEY_GITLAB, e.g.:

$ cat secrets.txt
APIKEY_GITHUB=<user who made the key>:<longish key with random characters>
APIKEY_GITLAB=<user who made the key>:<longish key with random characters>
source secrets.txt
howfairis https://github.com/fair-software/howfairis

Open questions / problems

  1. How to bypass the ratelimit decorators when using mocks fixed it, but hides the next point about Repo
  2. Repo might need to be extended with apikeys arg as well, since it's making a request to raw. No longer needed now that we're reading from env vars
  3. What about instantiating Repo within Checker.__init__? Checker's constructor would then need additional arguments url, branch and path, and could drop repo.
  4. On GitHub and GitLab, raw seems to have its own limits, not covered by api key increased rate limit.
  5. On GitLab, unauthenticated api calls return a ratelimit of 2000, not 500 like the documentation says. authenticated requests also have ratelimit 2000, this is consistent with the documentation

@fdiblen fdiblen self-requested a review February 25, 2021 14:11
@fdiblen fdiblen removed the standup label Feb 25, 2021
.gitignore Outdated
@@ -9,3 +9,5 @@

docs/_build
docs/apidocs

secrets.yml
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
secrets.yml

Copy link
Member Author

Choose a reason for hiding this comment

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

done in upcoming commit

@eriktks eriktks self-requested a review February 25, 2021 15:39
Comment on lines 7 to 10
github_apikey_is_invalid = apikeys is not None and (apikeys.get("github-key") is None or
apikeys.get("github-user") is None)

if apikeys is None or github_apikey_is_invalid:
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
github_apikey_is_invalid = apikeys is not None and (apikeys.get("github-key") is None or
apikeys.get("github-user") is None)
if apikeys is None or github_apikey_is_invalid:
if apikeys is None or apikeys.get("github-key") is None or apikeys.get("github-user") is None:


def get_from_gitlab(url, url_type, apikeys=None):

if apikeys is None:
Copy link
Member

Choose a reason for hiding this comment

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

This code is much shorter than the equivalent code for github. Is it complete?

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed it same as github now

def get_from_gitlab_with_auth_api(url, apikeys):

headers = {
"Accept": "application/vnd.github.v3+json"
Copy link
Member

Choose a reason for hiding this comment

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

Probably github here should be changed

Copy link
Member Author

Choose a reason for hiding this comment

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

changed to only json, also added headers to equivalent noauth gitlab case.

setup.py Outdated
Comment on lines 50 to 51
"ruamel.yaml == 0.16.*",
"requests == 2.*",
Copy link
Member

@eriktks eriktks Feb 25, 2021

Choose a reason for hiding this comment

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

these two lines are not in alphabetical order

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed it

Copy link
Member

@eriktks eriktks left a comment

Choose a reason for hiding this comment

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

We went through the code and added some minor comments. Well done!

Copy link
Member

@fdiblen fdiblen left a comment

Choose a reason for hiding this comment

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

Awesome sos! 🍜
A few suggestions which we should create issues about:

  • We need to update the documentation to reflect this work.
  • It is a good idea to raise some exceptions, e.g. when the authentication fails.
  • If for some reason we cannot use authenticantion and use unathenticated method, we should warn the user.
  • Number of calls are hardcoded. We can consider making them configurable.

@sonarcloud
Copy link

sonarcloud bot commented Feb 25, 2021

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.

3 participants