class ConnectedDevelopers

Attributes

developers[R]

Public Class Methods

new(developers:, twitter_client:, github_client: @twitter_client = twitter_client) click to toggle source
# File lib/developer_cliques/connected_developers.rb, line 11
def initialize developers:, twitter_client:, github_client:
  @twitter_client = twitter_client
  @github_client = github_client
  @developers = developers
  @organizations = {}
end

Public Instance Methods

followers(user_name) click to toggle source
# File lib/developer_cliques/connected_developers.rb, line 28
def followers user_name
  follow_list = twitter_retry { @twitter_client.followers(user_name).entries.map{ |u| u.screen_name } }
  AppLogger.debug "FRIENDS: #{follow_list}"
  follow_list
end
friends(user_name) click to toggle source
# File lib/developer_cliques/connected_developers.rb, line 22
def friends user_name
  friends_list = twitter_retry { @twitter_client.friends(user_name).entries.map{ |u| u.screen_name } }
  AppLogger.debug "FRIENDS: #{friends_list}"
  friends_list
end
graph() click to toggle source
# File lib/developer_cliques/connected_developers.rb, line 18
def graph
  @graph ||= generate_graph
end
organizations(user_name) click to toggle source
# File lib/developer_cliques/connected_developers.rb, line 34
def organizations user_name
  @organizations[user_name] ||= @github_client.organizations(user_name).map{ |u| u.login }
end

Private Instance Methods

generate_graph() click to toggle source
# File lib/developer_cliques/connected_developers.rb, line 40
def generate_graph
  developers_graph = {}
  excluded = []

  promises = developers.map do |developer|
    excluded << developer
    developers_graph[developer] ||= []

    graph_by_developer developers_graph: developers_graph, developer: developer, excluded: excluded.clone
  end

  Concurrent::Promise.all?(*promises).execute.wait!
  developers_graph
end
graph_by_developer(developers_graph:, developer:, excluded: AppLogger.debug "GITHUB USER: click to toggle source
# File lib/developer_cliques/connected_developers.rb, line 55
def graph_by_developer developers_graph:, developer:, excluded:
  AppLogger.debug "GITHUB USER: #{developer}"
  AppLogger.debug "ORGANIZATIONS: #{organizations(developer)}"

  Concurrent::Promise.new {
    graph_by_organization developers_graph: developers_graph,
                          remaining_devs: developers-excluded,
                          current_developer: developer
  }.then{ |relationships|
    developers_graph[developer] = twitter_friendships developer: developer, relationships: relationships
  }
end
graph_by_organization(developers_graph:, remaining_devs:, current_developer: AppLogger.debug "REMAINING DEVS: click to toggle source
# File lib/developer_cliques/connected_developers.rb, line 68
def graph_by_organization developers_graph:, remaining_devs:, current_developer:
  #Bidireccional relationship. It excludes iterated developers and itself. We look only in one way
  AppLogger.debug "REMAINING DEVS: #{remaining_devs}"
  remaining_devs.each do |related_developer|
    # Intersection between organizations if there are some organization in common goes in
    unless (organizations(current_developer) & organizations(related_developer)).empty?
      #It creates relationship in one direction
      developers_graph[current_developer] << related_developer
      # And reverse direction
      developers_graph[related_developer] ||= []
      developers_graph[related_developer] << current_developer
    end
  end
  developers_graph[current_developer]
end
twitter_friendships(developer:, relationships: relationships &= friends(developer) & followers(developer) unless relationships.empty?) click to toggle source
# File lib/developer_cliques/connected_developers.rb, line 84
def twitter_friendships developer:, relationships:
  #Intersection between friends, followers and current relationships by organizations in common
  relationships &= friends(developer) & followers(developer) unless relationships.empty?
  relationships
end
twitter_retry() { || ... } click to toggle source
# File lib/developer_cliques/connected_developers.rb, line 90
def twitter_retry &block
  begin
    yield
  rescue Twitter::Error::TooManyRequests => error
    # NOTE: Your process could go to sleep for up to 15 minutes but if you
    # retry any sooner, it will almost certainly fail with the same exception.
    AppLogger.debug "TOO MANY REQUEST: #{error}. Must wait #{error.rate_limit.reset_in/60} min"
    sleep error.rate_limit.reset_in + 1
    retry
  end
end