{"action":"created","comment":{"url":"https://api.github.com/repos/inaka/elysium/pulls/comments/33387101","id":33387101,"diff_hunk":"@@ -0,0 +1,465 @@\n+%%------------------------------------------------------------------------------\n+%%% @copyright (c) 2014-2015, DuoMark International, Inc.\n+%%% @author Jay Nelson <jay@duomark.com> [http://duomark.com/]\n+%%% @reference 2014-2015 Development sponsored by TigerText, Inc. [http://tigertext.com/]\n+%%% @reference The license is based on the template for Modified BSD from\n+%%%   <a href=\"http://opensource.org/licenses/BSD-3-Clause\">OSI</a>\n+%%% @doc\n+%%%   Buffering strategy is a behaviour for different approaches to buffering\n+%%%   requests in excess of the number of Cassandra Connections.\n+\n+%%%   The current release provides the following buffering strategy\n+%%%   implementations:\n+%%%\n+%%%     elysium_bs_serial:\n+%%%        A connection queue and a pending request queue, each\n+%%%        implemented as a single gen_server with an erlang queue\n+%%%        as the internal state. Loss of a gen_server loses all\n+%%%        queue entries.\n+%%%\n+%%%     elysium_bs_parallel:\n+%%%        A connection queue and a pending request queue, each\n+%%%        implemented as a FIFO ets_buffer. The ets_buffers\n+%%%        survive all failures up to the elysium_sup itself.\n+%%%\n+%%%        As of Nov 13, 2014 this approach has concurrency\n+%%%        issues related to ets_missing_data errors.\n+%%%\n+%%% @since 0.1.7\n+%%% @end\n+%%%------------------------------------------------------------------------------\n+-module(elysium_buffering_strategy).\n+-author('jay@duomark.com').\n+\n+-include(\"elysium_types.hrl\").\n+-include(\"elysium_audit_types.hrl\").\n+\n+%% External API supplied for behaviour implementations to share.\n+-export([\n+         status/1,\n+         queue_status/2,\n+         queue_status_reset/2,\n+\n+         create_connection/3,\n+         checkin_connection/4,\n+         checkout_connection/1,\n+         pend_request/2,\n+\n+         decay_causes_death/2,\n+         decay_connection/3,\n+         report_available_resources/3,\n+         handle_pending_request/7\n+        ]).\n+\n+\n+%%%-----------------------------------------------------------------------\n+%%% Callbacks that behaviour implementers must provide\n+%%%-----------------------------------------------------------------------\n+\n+-callback idle_connection_count(connection_queue_name()) -> max_connections().\n+-callback checkin_connection(connection_queue_name(), cassandra_connection()) -> max_connections().\n+-callback checkout_connection(connection_queue_name())\n+                      -> connection_baton() | none_available | Error when Error::any().\n+-callback checkout_connection_error(config_type(), buffering_strategy_module(), connection_queue_name(), Error)\n+                      -> retry | Error when Error::any().\n+\n+-callback pending_request_count(requests_queue_name()) -> pending_count().\n+-callback checkin_pending_request(requests_queue_name(), reference(), erlang:timestamp())\n+                      -> pending_count().\n+-callback checkout_pending_request(requests_queue_name())\n+                      -> pending_request_baton() | none_available | Error when Error::any().\n+-callback checkout_pending_error(config_type(), buffering_strategy_module(), requests_queue_name(), Error)\n+                      -> retry | Error when Error::any().\n+\n+-callback queue_status       (connection_queue_name() | requests_queue_name()) -> {status, proplists:proplist()}.\n+-callback queue_status_reset (connection_queue_name() | requests_queue_name()) -> {status, proplists:proplist()}.\n+\n+\n+%%%-----------------------------------------------------------------------\n+%%% Buffering strategy provided functions\n+%%%-----------------------------------------------------------------------\n+\n+-spec create_connection(config_type(), cassandra_node(), connection_id())\n+                        -> pending_checkin().\n+\n+-spec checkin_connection(config_type(), cassandra_node(), connection_id(), Is_New_Connection::boolean())\n+                        -> pending_checkin().\n+\n+-spec checkout_connection(config_type()) -> cassandra_connection() | none_available.\n+\n+-spec pend_request(config_type(), query_request()) -> query_result().\n+\n+-spec decay_causes_death (config_type(), connection_id()) -> boolean().\n+-spec decay_connection   (config_type(), buffering_strategy_module(), connection_id()) -> true.\n+\n+-spec status             (config_type()) -> status_reply().\n+-spec queue_status       (config_type(), connection_queue_name() | requests_queue_name())\n+                         -> {status, proplists:proplist()}.\n+-spec queue_status_reset (config_type(), connection_queue_name() | requests_queue_name())\n+                         -> {status, proplists:proplist()}.\n+\n+-spec report_available_resources(Queue, Connections, Max_Or_Timeout) -> {Queue, Connections, Max_Or_Timeout}\n+                                       when Queue          :: queue_name(),\n+                                            Connections    :: max_connections() | pending_count(),\n+                                            Max_Or_Timeout :: max_connections() | timeout_in_ms().\n+\n+%% @doc Do any initialization before checkin of a newly created connection.\n+create_connection(Config, {_Ip, _Port} = Node, Connection_Id)\n+  when is_pid(Connection_Id) ->\n+    {_Buffering_Strategy, BS_Module} = elysium_connection:get_buffer_strategy_module(Config),\n+    elysium_buffering_audit:audit_data_init(Config, BS_Module, Connection_Id),\n+    checkin_connection(Config, Node, Connection_Id, true).\n+\n+%% @doc\n+%%   Checkin a Cassandra Connection, IF there are no Pending Requests.\n+%%   A checkin will continue looping on the pending queue with\n+%%   the chance for decay on each attempt. If it decays, any\n+%%   newly spawned replacement is expected to check the pending\n+%%   queue for outstanding requests. Brand new connections are\n+%%   not checked for decay before first use.\n+%% @end\n+checkin_connection(Config, {_Ip, _Port} = Node, Connection_Id, Is_New_Connection)\n+  when is_pid(Connection_Id) ->\n+    Pending_Queue    = elysium_config:requests_queue_name            (Config),\n+    {_BS, BS_Module} = elysium_connection:get_buffer_strategy_module (Config),\n+    case is_process_alive(Connection_Id) andalso BS_Module:pending_request_count(Pending_Queue) =:= 0 of\n+        true  -> checkin_immediate (Config, BS_Module, Node, Connection_Id, Pending_Queue, Is_New_Connection);\n+        false -> checkin_pending   (Config, BS_Module, Node, Connection_Id, Pending_Queue, Is_New_Connection)\n+    end.\n+\n+%% @doc\n+%%   Allocate a Cassandra Connection to the caller by popping an entry\n+%%   from the front of the connection queue. This function either\n+%%   returns a live pid(), or none_available to indicate that all\n+%%   connections to Cassandra are currently checked out.\n+%%\n+%%   The configuration parameter is not validated because this\n+%%   function should be a hotspot and we don't want it to slow\n+%%   down or become a concurrency bottleneck.\n+%% @end\n+checkout_connection(Config) ->\n+    Connection_Queue = elysium_config:session_queue_name             (Config),\n+    Max_Retries      = elysium_config:checkout_max_retry             (Config),\n+    {_BS, BS_Module} = elysium_connection:get_buffer_strategy_module (Config),\n+    fetch_pid_from_connection_queue(Config, BS_Module, Connection_Queue, Max_Retries, -1).\n+\n+%% @doc\n+%%   Block the caller until Cassandra Connection is available\n+%%   to run this Pending Request. The blocking recieve loop\n+%%   will unblock and a spawned process will execute the request,\n+%%   so that the caller can still timeout if the request takes too long.\n+%% @end\n+pend_request(Config, Query_Request) ->\n+    Sid_Reply_Ref    = make_ref(),\n+    Start_Time       = os:timestamp(),\n+    Pending_Queue    = elysium_config:requests_queue_name            (Config),\n+    Reply_Timeout    = elysium_config:request_reply_timeout          (Config),\n+    {_BS, BS_Module} = elysium_connection:get_buffer_strategy_module (Config),\n+    wait_for_connection(Config, BS_Module, Pending_Queue, Sid_Reply_Ref,\n+                        Start_Time, Query_Request, Reply_Timeout).\n+\n+%% @doc Get the next Cassandra Connection entry from the set of available Connections.\n+fetch_pid_from_connection_queue(_Config, _BS_Module, _Connection_Queue, Max_Retries, Times_Tried)\n+  when Times_Tried >= Max_Retries ->\n+    none_available;\n+fetch_pid_from_connection_queue( Config,  BS_Module,  Connection_Queue, Max_Retries, Times_Tried) ->\n+    case BS_Module:checkout_connection(Connection_Queue) of\n+        none_available -> none_available;\n+\n+        %% Return only a live pid, otherwise get the next one.\n+        {_Node, Connection_Id} = Connection_Data when is_pid(Connection_Id) ->\n+            case is_process_alive(Connection_Id) of\n+                %% NOTE: we toss only MAX_CHECKOUT_RETRY dead pids\n+                false -> _ = elysium_buffering_audit:audit_count(Config, BS_Module, session_dead),\n+                         fetch_pid_from_connection_queue(Config, BS_Module, Connection_Queue,\n+                                                         Max_Retries, Times_Tried+1);\n+                true  -> _ = elysium_buffering_audit:audit_data_checkout(Config, BS_Module, Connection_Id),\n+                         Connection_Data\n+            end;\n+\n+        Error ->\n+            case BS_Module:checkout_connection_error(Config, BS_Module, Connection_Queue, Error) of\n+                retry -> fetch_pid_from_connection_queue(Config, BS_Module, Connection_Queue,\n+                                                         Max_Retries, Times_Tried+1);\n+                Error -> Error\n+            end\n+    end.\n+\n+wait_for_connection(Config, BS_Module, Pending_Queue, Sid_Reply_Ref, Start_Time, Query_Request, Reply_Timeout) ->\n+    Connection_Queue = elysium_config:session_queue_name(Config),\n+    case fetch_pid_from_connection_queue(Config, BS_Module, Connection_Queue, 1, 0) of\n+\n+        %% A free cassandra connection showed up since we first checked...\n+        {Node, Connection_Id} when is_pid(Connection_Id) ->\n+            case is_process_alive(Connection_Id) of\n+                true  -> handle_pending_request(Config, BS_Module, 0, Reply_Timeout, Node,\n+                                                Connection_Id, Query_Request);\n+                false -> _ = elysium_buffering_audit:audit_count(Config, BS_Module, session_dead),\n+                         wait_for_connection(Config, BS_Module, Pending_Queue, Sid_Reply_Ref,\n+                                             Start_Time, Query_Request, Reply_Timeout)\n+            end;\n+\n+        %% None are still available, queue the request and wait for one to free up.\n+        _None_Available ->\n+            _Pending_Count = BS_Module:checkin_pending_request(Pending_Queue, Sid_Reply_Ref, Start_Time),\n+            wait_for_connection_loop(Config, BS_Module, Pending_Queue, Sid_Reply_Ref,\n+                                     Start_Time, Query_Request, Reply_Timeout)\n+    end.\n+\n+wait_for_connection_loop(Config, BS_Module, Pending_Queue, Sid_Reply_Ref,\n+                         Start_Time, Query_Request, Reply_Timeout) ->\n+    receive\n+        %% A live Cassandra Connection is now available to make the request...\n+        {sid, Sid_Reply_Ref, Node, Connection_Id, Pending_Queue, Is_New_Connection} ->\n+            Elapsed_Time = timer:now_diff(os:timestamp(), Start_Time),\n+            case {Elapsed_Time >= Reply_Timeout * 1000, is_process_alive(Connection_Id)} of\n+\n+                %% Alas, we timed out waiting...\n+                {true,  true}  -> _ = elysium_buffering_audit:audit_count(Config, BS_Module, session_timeouts),","path":"src/elysium_buffering_strategy.erl","position":218,"original_position":218,"commit_id":"f0a43ec183669292223af5f45f91ee57bd54296e","original_commit_id":"f0a43ec183669292223af5f45f91ee57bd54296e","user":{"login":"gadgetci","id":10134338,"avatar_url":"https://avatars.githubusercontent.com/u/10134338?v=3","gravatar_id":"","url":"https://api.github.com/users/gadgetci","html_url":"https://github.com/gadgetci","followers_url":"https://api.github.com/users/gadgetci/followers","following_url":"https://api.github.com/users/gadgetci/following{/other_user}","gists_url":"https://api.github.com/users/gadgetci/gists{/gist_id}","starred_url":"https://api.github.com/users/gadgetci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gadgetci/subscriptions","organizations_url":"https://api.github.com/users/gadgetci/orgs","repos_url":"https://api.github.com/users/gadgetci/repos","events_url":"https://api.github.com/users/gadgetci/events{/privacy}","received_events_url":"https://api.github.com/users/gadgetci/received_events","type":"User","site_admin":false},"body":"According to **Elvis**:\n> Line 218 is too long:                 {true,  true}  -> _ = elysium_buffering_audit:audit_count(Config, BS_Module, session_timeouts),.","created_at":"2015-06-26T19:21:27Z","updated_at":"2015-06-26T19:21:27Z","html_url":"https://github.com/inaka/elysium/pull/2#discussion_r33387101","pull_request_url":"https://api.github.com/repos/inaka/elysium/pulls/2","_links":{"self":{"href":"https://api.github.com/repos/inaka/elysium/pulls/comments/33387101"},"html":{"href":"https://github.com/inaka/elysium/pull/2#discussion_r33387101"},"pull_request":{"href":"https://api.github.com/repos/inaka/elysium/pulls/2"}}},"pull_request":{"url":"https://api.github.com/repos/inaka/elysium/pulls/2","id":38680903,"html_url":"https://github.com/inaka/elysium/pull/2","diff_url":"https://github.com/inaka/elysium/pull/2.diff","patch_url":"https://github.com/inaka/elysium/pull/2.patch","issue_url":"https://api.github.com/repos/inaka/elysium/issues/2","number":2,"state":"closed","locked":false,"title":"Up to date","user":{"login":"HernanRivasAcosta","id":5691671,"avatar_url":"https://avatars.githubusercontent.com/u/5691671?v=3","gravatar_id":"","url":"https://api.github.com/users/HernanRivasAcosta","html_url":"https://github.com/HernanRivasAcosta","followers_url":"https://api.github.com/users/HernanRivasAcosta/followers","following_url":"https://api.github.com/users/HernanRivasAcosta/following{/other_user}","gists_url":"https://api.github.com/users/HernanRivasAcosta/gists{/gist_id}","starred_url":"https://api.github.com/users/HernanRivasAcosta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HernanRivasAcosta/subscriptions","organizations_url":"https://api.github.com/users/HernanRivasAcosta/orgs","repos_url":"https://api.github.com/users/HernanRivasAcosta/repos","events_url":"https://api.github.com/users/HernanRivasAcosta/events{/privacy}","received_events_url":"https://api.github.com/users/HernanRivasAcosta/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-06-26T19:19:57Z","updated_at":"2015-06-26T19:21:27Z","closed_at":"2015-06-26T19:20:08Z","merged_at":"2015-06-26T19:20:08Z","merge_commit_sha":"4e385cca733cd97f7d23686af84d628fc133d3b6","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/inaka/elysium/pulls/2/commits","review_comments_url":"https://api.github.com/repos/inaka/elysium/pulls/2/comments","review_comment_url":"https://api.github.com/repos/inaka/elysium/pulls/comments{/number}","comments_url":"https://api.github.com/repos/inaka/elysium/issues/2/comments","statuses_url":"https://api.github.com/repos/inaka/elysium/statuses/f0a43ec183669292223af5f45f91ee57bd54296e","head":{"label":"tigertext:master","ref":"master","sha":"f0a43ec183669292223af5f45f91ee57bd54296e","user":{"login":"tigertext","id":173280,"avatar_url":"https://avatars.githubusercontent.com/u/173280?v=3","gravatar_id":"","url":"https://api.github.com/users/tigertext","html_url":"https://github.com/tigertext","followers_url":"https://api.github.com/users/tigertext/followers","following_url":"https://api.github.com/users/tigertext/following{/other_user}","gists_url":"https://api.github.com/users/tigertext/gists{/gist_id}","starred_url":"https://api.github.com/users/tigertext/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tigertext/subscriptions","organizations_url":"https://api.github.com/users/tigertext/orgs","repos_url":"https://api.github.com/users/tigertext/repos","events_url":"https://api.github.com/users/tigertext/events{/privacy}","received_events_url":"https://api.github.com/users/tigertext/received_events","type":"Organization","site_admin":false},"repo":{"id":24917017,"name":"elysium","full_name":"tigertext/elysium","owner":{"login":"tigertext","id":173280,"avatar_url":"https://avatars.githubusercontent.com/u/173280?v=3","gravatar_id":"","url":"https://api.github.com/users/tigertext","html_url":"https://github.com/tigertext","followers_url":"https://api.github.com/users/tigertext/followers","following_url":"https://api.github.com/users/tigertext/following{/other_user}","gists_url":"https://api.github.com/users/tigertext/gists{/gist_id}","starred_url":"https://api.github.com/users/tigertext/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tigertext/subscriptions","organizations_url":"https://api.github.com/users/tigertext/orgs","repos_url":"https://api.github.com/users/tigertext/repos","events_url":"https://api.github.com/users/tigertext/events{/privacy}","received_events_url":"https://api.github.com/users/tigertext/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/tigertext/elysium","description":"The blessed and happy erlang afterlife for Cassandra","fork":true,"url":"https://api.github.com/repos/tigertext/elysium","forks_url":"https://api.github.com/repos/tigertext/elysium/forks","keys_url":"https://api.github.com/repos/tigertext/elysium/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tigertext/elysium/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tigertext/elysium/teams","hooks_url":"https://api.github.com/repos/tigertext/elysium/hooks","issue_events_url":"https://api.github.com/repos/tigertext/elysium/issues/events{/number}","events_url":"https://api.github.com/repos/tigertext/elysium/events","assignees_url":"https://api.github.com/repos/tigertext/elysium/assignees{/user}","branches_url":"https://api.github.com/repos/tigertext/elysium/branches{/branch}","tags_url":"https://api.github.com/repos/tigertext/elysium/tags","blobs_url":"https://api.github.com/repos/tigertext/elysium/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tigertext/elysium/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tigertext/elysium/git/refs{/sha}","trees_url":"https://api.github.com/repos/tigertext/elysium/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tigertext/elysium/statuses/{sha}","languages_url":"https://api.github.com/repos/tigertext/elysium/languages","stargazers_url":"https://api.github.com/repos/tigertext/elysium/stargazers","contributors_url":"https://api.github.com/repos/tigertext/elysium/contributors","subscribers_url":"https://api.github.com/repos/tigertext/elysium/subscribers","subscription_url":"https://api.github.com/repos/tigertext/elysium/subscription","commits_url":"https://api.github.com/repos/tigertext/elysium/commits{/sha}","git_commits_url":"https://api.github.com/repos/tigertext/elysium/git/commits{/sha}","comments_url":"https://api.github.com/repos/tigertext/elysium/comments{/number}","issue_comment_url":"https://api.github.com/repos/tigertext/elysium/issues/comments{/number}","contents_url":"https://api.github.com/repos/tigertext/elysium/contents/{+path}","compare_url":"https://api.github.com/repos/tigertext/elysium/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tigertext/elysium/merges","archive_url":"https://api.github.com/repos/tigertext/elysium/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tigertext/elysium/downloads","issues_url":"https://api.github.com/repos/tigertext/elysium/issues{/number}","pulls_url":"https://api.github.com/repos/tigertext/elysium/pulls{/number}","milestones_url":"https://api.github.com/repos/tigertext/elysium/milestones{/number}","notifications_url":"https://api.github.com/repos/tigertext/elysium/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tigertext/elysium/labels{/name}","releases_url":"https://api.github.com/repos/tigertext/elysium/releases{/id}","created_at":"2014-10-08T00:02:02Z","updated_at":"2015-06-19T03:23:57Z","pushed_at":"2015-04-24T18:00:44Z","git_url":"git://github.com/tigertext/elysium.git","ssh_url":"git@github.com:tigertext/elysium.git","clone_url":"https://github.com/tigertext/elysium.git","svn_url":"https://github.com/tigertext/elysium","homepage":null,"size":1606,"stargazers_count":1,"watchers_count":1,"language":"Erlang","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":1,"forks":2,"open_issues":1,"watchers":1,"default_branch":"master"}},"base":{"label":"inaka:master","ref":"master","sha":"37cca477d0beb04f75c5062b03155b11ac33fbdd","user":{"login":"inaka","id":867053,"avatar_url":"https://avatars.githubusercontent.com/u/867053?v=3","gravatar_id":"","url":"https://api.github.com/users/inaka","html_url":"https://github.com/inaka","followers_url":"https://api.github.com/users/inaka/followers","following_url":"https://api.github.com/users/inaka/following{/other_user}","gists_url":"https://api.github.com/users/inaka/gists{/gist_id}","starred_url":"https://api.github.com/users/inaka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/inaka/subscriptions","organizations_url":"https://api.github.com/users/inaka/orgs","repos_url":"https://api.github.com/users/inaka/repos","events_url":"https://api.github.com/users/inaka/events{/privacy}","received_events_url":"https://api.github.com/users/inaka/received_events","type":"Organization","site_admin":false},"repo":{"id":25830237,"name":"elysium","full_name":"inaka/elysium","owner":{"login":"inaka","id":867053,"avatar_url":"https://avatars.githubusercontent.com/u/867053?v=3","gravatar_id":"","url":"https://api.github.com/users/inaka","html_url":"https://github.com/inaka","followers_url":"https://api.github.com/users/inaka/followers","following_url":"https://api.github.com/users/inaka/following{/other_user}","gists_url":"https://api.github.com/users/inaka/gists{/gist_id}","starred_url":"https://api.github.com/users/inaka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/inaka/subscriptions","organizations_url":"https://api.github.com/users/inaka/orgs","repos_url":"https://api.github.com/users/inaka/repos","events_url":"https://api.github.com/users/inaka/events{/privacy}","received_events_url":"https://api.github.com/users/inaka/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/inaka/elysium","description":"The blessed and happy erlang afterlife for Cassandra","fork":true,"url":"https://api.github.com/repos/inaka/elysium","forks_url":"https://api.github.com/repos/inaka/elysium/forks","keys_url":"https://api.github.com/repos/inaka/elysium/keys{/key_id}","collaborators_url":"https://api.github.com/repos/inaka/elysium/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/inaka/elysium/teams","hooks_url":"https://api.github.com/repos/inaka/elysium/hooks","issue_events_url":"https://api.github.com/repos/inaka/elysium/issues/events{/number}","events_url":"https://api.github.com/repos/inaka/elysium/events","assignees_url":"https://api.github.com/repos/inaka/elysium/assignees{/user}","branches_url":"https://api.github.com/repos/inaka/elysium/branches{/branch}","tags_url":"https://api.github.com/repos/inaka/elysium/tags","blobs_url":"https://api.github.com/repos/inaka/elysium/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/inaka/elysium/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/inaka/elysium/git/refs{/sha}","trees_url":"https://api.github.com/repos/inaka/elysium/git/trees{/sha}","statuses_url":"https://api.github.com/repos/inaka/elysium/statuses/{sha}","languages_url":"https://api.github.com/repos/inaka/elysium/languages","stargazers_url":"https://api.github.com/repos/inaka/elysium/stargazers","contributors_url":"https://api.github.com/repos/inaka/elysium/contributors","subscribers_url":"https://api.github.com/repos/inaka/elysium/subscribers","subscription_url":"https://api.github.com/repos/inaka/elysium/subscription","commits_url":"https://api.github.com/repos/inaka/elysium/commits{/sha}","git_commits_url":"https://api.github.com/repos/inaka/elysium/git/commits{/sha}","comments_url":"https://api.github.com/repos/inaka/elysium/comments{/number}","issue_comment_url":"https://api.github.com/repos/inaka/elysium/issues/comments{/number}","contents_url":"https://api.github.com/repos/inaka/elysium/contents/{+path}","compare_url":"https://api.github.com/repos/inaka/elysium/compare/{base}...{head}","merges_url":"https://api.github.com/repos/inaka/elysium/merges","archive_url":"https://api.github.com/repos/inaka/elysium/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/inaka/elysium/downloads","issues_url":"https://api.github.com/repos/inaka/elysium/issues{/number}","pulls_url":"https://api.github.com/repos/inaka/elysium/pulls{/number}","milestones_url":"https://api.github.com/repos/inaka/elysium/milestones{/number}","notifications_url":"https://api.github.com/repos/inaka/elysium/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/inaka/elysium/labels{/name}","releases_url":"https://api.github.com/repos/inaka/elysium/releases{/id}","created_at":"2014-10-27T17:16:14Z","updated_at":"2014-11-13T18:28:31Z","pushed_at":"2015-06-26T19:20:08Z","git_url":"git://github.com/inaka/elysium.git","ssh_url":"git@github.com:inaka/elysium.git","clone_url":"https://github.com/inaka/elysium.git","svn_url":"https://github.com/inaka/elysium","homepage":null,"size":293,"stargazers_count":0,"watchers_count":0,"language":"Erlang","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/inaka/elysium/pulls/2"},"html":{"href":"https://github.com/inaka/elysium/pull/2"},"issue":{"href":"https://api.github.com/repos/inaka/elysium/issues/2"},"comments":{"href":"https://api.github.com/repos/inaka/elysium/issues/2/comments"},"review_comments":{"href":"https://api.github.com/repos/inaka/elysium/pulls/2/comments"},"review_comment":{"href":"https://api.github.com/repos/inaka/elysium/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/inaka/elysium/pulls/2/commits"},"statuses":{"href":"https://api.github.com/repos/inaka/elysium/statuses/f0a43ec183669292223af5f45f91ee57bd54296e"}}}}