Class: GithubApi

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/org_lang_stats/github_api.rb

Overview

This class is a basic GitHub API client library. The only function that is exposed publically, get_all_pages, will auto-paginate when needed and if not needeed will just return the hash payload. Most failures that could happen while calling an API are also handled here.

Instance Method Summary collapse

Methods included from Logging

#enable, #logger, logger

Constructor Details

#initialize(token = nil) ⇒ GithubApi

Returns a new instance of GithubApi.



17
18
19
# File 'lib/org_lang_stats/github_api.rb', line 17

def initialize(token = nil)
    @token = token
end

Instance Method Details

#abort_max_retriesObject



80
81
82
# File 'lib/org_lang_stats/github_api.rb', line 80

def abort_max_retries
    abort 'Max retries limit reached! Run in --debug mode for more info'
end

#auth_stringObject



21
22
23
# File 'lib/org_lang_stats/github_api.rb', line 21

def auth_string
    "Basic #{Base64.strict_encode64(':' + @token)}" if @token
end

#get_all_pages(url:, params: {}, all_pages: []) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/org_lang_stats/github_api.rb', line 25

def get_all_pages(url:, params: {}, all_pages: [])

    response = get_page(url, params)
    logger.debug "Url:#{url} returned succesfully!"

    resp_body = JSON.parse(response)

    return resp_body if resp_body.is_a?(Hash)
    all_pages += resp_body

    begin
        next_url = get_next_url(response)
        return get_all_pages(url: next_url, params: params, all_pages: all_pages)
    rescue NoMethodError
        # Ends the recursion
        return all_pages
    end
end

#get_next_url(response) ⇒ Object



61
62
63
64
65
# File 'lib/org_lang_stats/github_api.rb', line 61

def get_next_url(response)
    response.headers[:link].split(',')
                           .select { |link| link.include? 'rel="next"' }.first
                           .split(';').first[/<(.+)>/, 1]
end

#get_page(url, params = {}) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/org_lang_stats/github_api.rb', line 44

def get_page(url, params = {})
    begin
        tries ||= MAX_RETRIES
        RestClient.get(url, params: DEFAULT_PARAMS.merge(params), Authorization: auth_string)
    # Soft error codes
    rescue RestClient::Forbidden, RestClient::Exceptions::OpenTimeout, Errno::ECONNRESET, SocketError => ex

        rate_lim_reached(ex) if ex.class.name == 'RestClient::Forbidden'
        sleep_with_msg(ex)
        retry unless (tries -= 1).zero?
        abort_max_retries
    # Hard error codes
    rescue RestClient::NotFound
        abort "Url #{url} not found!"
    end
end

#rate_lim_reached(ex) ⇒ Object



73
74
75
76
77
78
# File 'lib/org_lang_stats/github_api.rb', line 73

def rate_lim_reached(ex)
    reset_in = ex.response.headers[:x_ratelimit_reset].to_i - Time.now.to_i
    logger.debug "Rate limit reached! Limits will be reset in #{reset_in / 60} minutes"
    logger.debug "Sleeping until then...Refresh your IP and rerun if you don't want to wait!"
    sleep reset_in
end

#sleep_with_msg(ex) ⇒ Object



67
68
69
70
71
# File 'lib/org_lang_stats/github_api.rb', line 67

def sleep_with_msg(ex)
    logger.debug "An error of type #{ex.class} happened, message is #{ex.message}"
    logger.debug "Request will be retried in #{DEFAULT_SLEEP} seconds\n"
    sleep DEFAULT_SLEEP
end