{"action":"created","comment":{"url":"https://api.github.com/repos/fyler/fyler/pulls/comments/31126063","id":31126063,"diff_hunk":"@@ -0,0 +1,694 @@\n+-module(fyler_category_manager).\n+-behaviour(gen_fsm).\n+\n+-include(\"../include/log.hrl\").\n+-include(\"fyler.hrl\").\n+\n+-define(REGEX, \"\\\"PrivateIpAddress\\\": \\\"(?<ip>[^\\\"]*)\\\"\").\n+-define(NODE(Category, Ip), list_to_atom(lists:flatten(io_lib:format(\"fyler_~p_pool@~s\", [Category, Ip])))).\n+-define(TIMEOUT, 60000).\n+\n+%% ------------------------------------------------------------------\n+%% API Function Exports\n+%% ------------------------------------------------------------------\n+\n+-export([\n+  start_link/1,\n+  run_task/2,\n+  cancel_task/2,\n+  task_accepted/3,\n+  task_rejected/3,\n+  pool_connected/2,\n+  pool_down/2,\n+  pool_enabled/2,\n+  pool_disabled/2\n+]).\n+\n+%% ------------------------------------------------------------------\n+%% gen_fsm Function Exports\n+%% ------------------------------------------------------------------\n+\n+-export([init/1, handle_event/3,\n+         handle_sync_event/4, handle_info/3,\n+         terminate/3, code_change/4]).\n+\n+-export([start/2, zero/2, tasks/2, pools/2]).\n+\n+-record(state, {\n+  category :: atom(),\n+  retasks = fyler_queue:new() :: fyler_queue:fyler_queue(task()),\n+  tasks = fyler_queue:new() :: fyler_queue:fyler_queue(task()),\n+  task_filter = [] :: [task()],\n+  pools = [] :: [{atom(), enabled | disabled | {pending, reference(), non_neg_integer()}}],\n+  passive_pools = [] :: [atom()],\n+  index = 0 :: non_neg_integer(),\n+  priorities = #{} :: #{atom() => pos_integer()},\n+  node_to_id = #{} :: #{atom() => iolist()},\n+  check_ref :: reference()\n+}).\n+\n+%% ------------------------------------------------------------------\n+%% API Function Definitions\n+%% ------------------------------------------------------------------\n+\n+start_link(Category) ->\n+  gen_fsm:start_link(?MODULE, [Category], []).\n+\n+run_task(Manager, #task{} = Task) ->\n+  gen_fsm:send_event(Manager, {run, Task}).\n+\n+cancel_task(Manager, Id) ->\n+  gen_fsm:send_event(Manager, {cancel, Id}).\n+\n+task_accepted(Manager, Ref, Node) ->\n+  gen_fsm:send_event(Manager, {task_accepted, Ref, Node}).\n+\n+task_rejected(Manager, Ref, Node) ->\n+  gen_fsm:send_event(Manager, {task_rejected, Ref, Node}).\n+\n+pool_connected(Manager, Node) ->\n+  gen_fsm:send_event(Manager, {pool_connected, Node}).\n+\n+pool_down(Manager, Node) ->\n+  gen_fsm:send_event(Manager, {pool_down, Node}).\n+\n+pool_enabled(Manager, Node) ->\n+  gen_fsm:send_event(Manager, {pool_enabled, Node}).\n+\n+pool_disabled(Manager, Node) ->\n+  gen_fsm:send_event(Manager, {pool_disabled, Node}).\n+\n+%% ------------------------------------------------------------------\n+%% gen_fsm Function Definitions\n+%% ------------------------------------------------------------------\n+\n+init([Category]) ->\n+  self() ! start,\n+  {ok, start, #state{category = Category}}.\n+\n+start(Event, #state{} = State) ->\n+  {next_state, NextState, NewState} = start_(Event, State),\n+  apply_state(NextState, start, NewState#state{check_ref = undefined}).\n+\n+zero({check, Ref}, #state{check_ref = Ref} = State) ->\n+  zero(check, State);\n+\n+zero({check, _}, State) ->\n+  {next_state, zero, State};\n+\n+zero(Event, #state{} = State) ->\n+  {next_state, NextState, NewState} = zero_(Event, State),\n+  case NextState of\n+    zero ->\n+      {next_state, NextState, NewState};\n+    NextState ->\n+      apply_state(NextState, start, NewState#state{check_ref = undefined})\n+  end.\n+\n+pools({check, Ref}, #state{check_ref = Ref} = State) ->\n+  pools(check, State);\n+\n+pools({check, _}, State) ->\n+  {next_state, pools, State};\n+\n+pools(Event, #state{} = State) ->\n+  {next_state, NextState, NewState} = pools_(Event, State),\n+  case NextState of\n+    pools ->\n+      {next_state, NextState, NewState};\n+    NextState ->\n+      apply_state(NextState, start, NewState#state{check_ref = undefined})\n+  end.\n+\n+tasks({check, Ref}, #state{check_ref = Ref} = State) ->\n+  tasks(check, State);\n+\n+tasks({check, _}, State) ->\n+  {next_state, tasks, State};\n+\n+tasks(Event, #state{} = State) ->\n+  {next_state, NextState, NewState} = tasks_(Event, State),\n+  case NextState of\n+    tasks ->\n+      {next_state, NextState, NewState};\n+    NextState ->\n+      apply_state(NextState, start, NewState#state{check_ref = undefined})\n+  end.\n+\n+start_(start, #state{category = Category} = State) ->\n+  Priorities = maps:get(priorities, ?Config(Category, #{}), #{}),\n+  FreeNodes =\n+    fun\n+      (#pool{node = Node, enabled = true, category = C}, List) when C == Category -> [{Node, enabled} | List];\n+      (#pool{node = Node, enabled = false, category = C}, List) when C == Category -> [{Node, disabled} | List];\n+      (_, List) -> List\n+    end,\n+  Pools = ets:foldl(FreeNodes, [], ?T_POOLS),\n+  case ets:info(Category) of\n+    undefined ->\n+      ets:new(Category, [public, named_table, {keypos, #current_task.id}, {heir, whereis(fyler_server), ok}]);\n+    _ ->\n+      ok\n+  end,\n+  NextState =\n+    case is_enabled(Pools) of\n+      true -> pools;\n+      false -> zero\n+    end,\n+\n+  InstanceList = maps:get(instances, ?Config(Category, #{}), []),\n+  {ok, Re} = re:compile(?REGEX),\n+  IdToNode =\n+    fun\n+      (Id, {Map, Nodes}) ->\n+        case re:run(aws_cli:instance(Id), Re, [{capture, [ip], list}]) of\n+          {match, [Ip]} ->\n+            Node = ?NODE(Category, Ip),\n+            {maps:put(Node, Id, Map), [Node | Nodes]};\n+          nomatch ->\n+            {Map, Nodes}\n+        end\n+    end,\n+  {NodeToId, AllNodes} = lists:foldl(IdToNode, {#{}, []}, InstanceList),\n+  PassiveNodes = lists:subtract(AllNodes, Pools),\n+  NewState = State#state{pools = Pools, passive_pools = PassiveNodes, priorities = Priorities, node_to_id = NodeToId},\n+  {next_state, NextState, NewState}.\n+\n+zero_(start, State) ->\n+  {next_state, zero, State};\n+\n+zero_({run, #task{priority = Priority} = Task}, #state{tasks = Tasks, priorities = Priorities} = State) ->\n+  NumPriority = maps:get(Priority, Priorities, 1),\n+  update_ets(Task),\n+  {next_state, tasks, State#state{tasks = fyler_queue:in(Task, NumPriority, Tasks)}};\n+\n+zero_({task_rejected, Ref, Node}, #state{category = Category, retasks = ReTasks, pools = Pools} = State) ->\n+  case status(Node, Pools) of\n+    {pending, Ref, Id} ->\n+      NewPools = enable(Node, Pools),\n+      case task(Category, Id) of\n+        undefined ->\n+          {next_state, zero, State#state{pools = NewPools}};\n+        Task ->\n+          {NextState, NewState} = choose_pool(State#state{retasks = fyler_queue:in(Task, ReTasks), pools = NewPools}),\n+          {next_state, NextState, NewState}\n+      end;\n+    _ ->\n+      {next_state, zero, State}\n+  end;\n+\n+zero_({pool_connected, Node}, #state{pools = Pools, passive_pools = PassivePools} = State) ->\n+  {next_state, pools, State#state{pools = connect(Node, Pools), passive_pools = lists:delete(Node, PassivePools)}};\n+\n+zero_({pool_enabled, Node}, #state{pools = Pools} = State) ->\n+  NewPools = enable(Node, Pools),\n+  {next_state, pools, State#state{pools = NewPools}};\n+\n+zero_({task_accepted, Ref, Node}, #state{pools = Pools} = State) ->\n+  case status(Node, Pools) of\n+    {pending, Ref, _Id} ->\n+      NewPools = enable(Node, Pools),\n+      {next_state, pools, State#state{pools = NewPools}};\n+    _ ->\n+      {next_state, zero, State}\n+  end;\n+\n+zero_({pool_disabled, Node}, #state{category = Category, retasks = ReTasks, pools = Pools} = State) ->\n+  NewPools = disable(Node, Pools),\n+  case status(Node, Pools) of\n+    {pending, _Ref, Id} ->\n+      case task(Category, Id) of\n+        undefined ->\n+          {next_state, zero, State#state{pools = NewPools}};\n+        Task ->\n+          rpc:cast(Node, fyler_pool, cancel_task, [Id]),\n+          {next_state, tasks, State#state{retasks = fyler_queue:in(Task, ReTasks), pools = NewPools}}\n+      end;\n+    _ ->\n+      {next_state, zero, State#state{pools = NewPools}}\n+  end;\n+\n+zero_({pool_down, Node}, #state{category = Category, retasks = ReTasks, pools = Pools,\n+  passive_pools = PassivePools} = State) ->\n+\n+  NewReTasks = restart_tasks(Category, ReTasks, Node),\n+  NewState = State#state{pools = delete(Node, Pools), passive_pools = [Node|PassivePools]},\n+  case fyler_queue:is_empty(NewReTasks) of\n+    true ->\n+      {next_state, zero, NewState};\n+    false ->\n+      {next_state, tasks, NewState#state{retasks = NewReTasks}}\n+  end;\n+\n+zero_({cancel_task, Id}, #state{category = Category} = State) ->\n+  case ets:lookup(Category, Id) of\n+    [#current_task{pool = Node, status = progress}] ->\n+      ets:delete(Category, Id),\n+      rpc:cast(Node, fyler_pool, cancel_task, [Id]);\n+    _ ->\n+      ok\n+  end,\n+  {next_state, zero, State}.\n+\n+pools_(start, #state{pools = [_]} = State) ->\n+  {next_state, pools, State};\n+\n+pools_(start, #state{} = State) ->\n+  {next_state, pools, send_check(State)};\n+\n+pools_(check, #state{pools = [_]} = State) ->\n+  {next_state, pools, State};\n+\n+pools_(check, #state{pools = [{Pool, _}|_], node_to_id = NodeToId} = State) ->\n+  stop_pool(Pool, NodeToId),\n+  {next_state, pools, send_check(State)};\n+\n+pools_({pool_connected, Node}, #state{pools = [Pool], passive_pools = PassivePools} = State) ->\n+  NewState = State#state{pools = connect(Node, [Pool]), passive_pools = lists:delete(Node, PassivePools)},\n+  {next_state, pools, send_check(NewState)};\n+\n+pools_({pool_connected, Node}, #state{pools = Pools, passive_pools = PassivePools} = State) ->\n+  {next_state, pools, State#state{pools = connect(Node, Pools), passive_pools = lists:delete(Node, PassivePools)}};\n+\n+pools_({pool_enabled, Node}, #state{pools = Pools} = State) ->\n+  {next_state, pools, State#state{pools = enable(Node, Pools)}};\n+\n+pools_({task_accepted, Ref, Node}, #state{pools = Pools} = State) ->\n+  NewPools =\n+    case status(Node, Pools) of\n+      {pending, Ref, _Id} ->\n+        enable(Node, Pools);\n+      _ ->\n+        Pools\n+    end,\n+  {next_state, pools, State#state{pools = NewPools}};\n+\n+pools_({pool_disabled, Node}, #state{category = Category, retasks = ReTasks, pools = Pools} = State) ->\n+  NewPools = disable(Node, Pools),\n+  NextState1 =\n+    case is_enabled(NewPools) of\n+      true -> pools;\n+      false -> zero\n+    end,\n+  NewState1 = State#state{pools = NewPools},\n+  {NextState, NewState} =\n+  case status(Node, Pools) of\n+    {pending, _Ref, Id} ->\n+      case task(Category, Id) of\n+        undefined ->\n+          {NextState1, NewState1};\n+        Task ->\n+          rpc:cast(Node, fyler_pool, cancel_task, [Id]),\n+          choose_pool(NewState1#state{retasks = fyler_queue:in(Task, ReTasks)})\n+      end;\n+    enabled ->\n+      {NextState1, NewState1}\n+  end,\n+  {next_state, NextState, NewState};\n+\n+pools_({pool_down, Node}, #state{category = Category, retasks = ReTasks, pools = Pools,\n+  passive_pools = PassivePools} = State) ->\n+\n+  NewReTasks = restart_tasks(Category, ReTasks, Node),\n+  State1 = State#state{retasks = NewReTasks, pools = delete(Node, Pools), passive_pools = [Node|PassivePools]},\n+  {NextState, NewState} = choose_pool(State1),\n+  {next_state, NextState, NewState};\n+\n+pools_({task_rejected, Ref, Node}, #state{category = Category, retasks = ReTasks, pools = Pools} = State) ->\n+  case status(Node, Pools) of\n+    {pending, Ref, Id} ->\n+      NewPools = enable(Node, Pools),\n+      case task(Category, Id) of\n+        undefined ->\n+          {next_state, pools, State#state{pools = NewPools}};\n+        Task ->\n+          {NextState, NewState} = choose_pool(State#state{retasks = fyler_queue:in(Task, ReTasks), pools = NewPools}),\n+          {next_state, NextState, NewState}\n+      end;\n+    _ ->\n+      {next_state, pools, State}\n+  end;\n+\n+pools_({run, #task{priority = Priority} = Task}, #state{tasks = Tasks, priorities = Priorities} = State) ->\n+  update_ets(Task),\n+  NumPriority = maps:get(Priority, Priorities, 1),\n+  NewTasks = fyler_queue:in(Task, NumPriority, Tasks),\n+  {NextState, NewState} = choose_pool(State#state{tasks = NewTasks}),\n+  {next_state, NextState, NewState};\n+\n+pools_({cancel_task, Id}, #state{category = Category} = State) ->\n+  case ets:lookup(Category, Id) of\n+    [#current_task{pool = Node, status = progress}] ->\n+      ets:delete(Category, Id),\n+      rpc:cast(Node, fyler_pool, cancel_task, [Id]);\n+    [#current_task{status = queued}] ->\n+      ets:delete(Category, Id);\n+    _ ->\n+      ok\n+  end,\n+  {next_state, pools, State}.\n+\n+tasks_(start, State) ->\n+  {next_state, tasks, send_check(State)};\n+\n+tasks_(check, #state{passive_pools = []} = State) ->\n+  {next_state, tasks, send_check(State)};\n+\n+tasks_(check, #state{passive_pools = Pools, node_to_id = NodeToId} = State) ->\n+  start_pool(lists:last(Pools), NodeToId),\n+  {next_state, tasks, send_check(State)};\n+\n+tasks_({pool_connected, Node}, #state{pools = Pools, passive_pools = PassivePools} = State) ->\n+  State1 = State#state{pools = connect(Node, Pools), passive_pools = lists:delete(Node, PassivePools)},\n+  {NextState, NewState} = choose_pool(State1),\n+  {next_state, NextState, NewState};\n+\n+tasks_({pool_enabled, Node}, #state{pools = Pools} = State) ->\n+  {NextState, NewState} = choose_pool(State#state{pools = enable(Node, Pools)}),\n+  {next_state, NextState, NewState};\n+\n+tasks_({pool_down, Node}, #state{category = Category, retasks = ReTasks, pools = Pools, passive_pools = []} = State) ->\n+  NewReTasks = restart_tasks(Category, ReTasks, Node),\n+  {next_state, tasks, State#state{retasks = NewReTasks, pools = delete(Node, Pools), passive_pools = [Node]}};\n+\n+tasks_({pool_down, Node}, #state{category = Category, retasks = ReTasks, pools = Pools,\n+  passive_pools = PassivePools} = State) ->\n+\n+  NewReTasks = restart_tasks(Category, ReTasks, Node),\n+  NewState = State#state{retasks = NewReTasks, pools = delete(Node, Pools), passive_pools = [Node|PassivePools]},\n+  {next_state, tasks, NewState};\n+\n+tasks_({pool_disabled, Node}, #state{category = Category, retasks = ReTasks, pools = Pools} = State) ->\n+  NewPools = disable(Node, Pools),\n+  case status(Node, Pools) of\n+    {pending, _Ref, Id} ->\n+      case task(Category, Id) of\n+        undefined ->\n+          {next_state, tasks, State#state{pools = NewPools}};\n+        Task ->\n+          rpc:cast(Node, fyler_pool, cancel_task, [Id]),\n+          {next_state, tasks, State#state{retasks = fyler_queue:in(Task, ReTasks), pools = NewPools}}\n+      end;\n+    _ ->\n+      {next_state, tasks, State#state{pools = NewPools}}\n+  end;\n+\n+tasks_({task_accepted, Ref, Node}, #state{pools = Pools} = State) ->\n+  case status(Node, Pools) of\n+    {pending, Ref, _Id} ->\n+      {NextState, NewState} = choose_pool(State#state{pools = enable(Node, Pools)}),\n+      {next_state, NextState, NewState};\n+    _ ->\n+      {next_state, tasks, State}\n+  end;\n+\n+tasks_({task_rejected, Ref, Node}, #state{category = Category, retasks = ReTasks, pools = Pools} = State) ->\n+  case status(Node, Pools) of\n+    {pending, Ref, Id} ->\n+      NewPools = enable(Node, Pools),\n+      case task(Category, Id) of\n+        undefined ->\n+          {next_state, tasks, State#state{pools = NewPools}};\n+        Task ->\n+          {NextState, NewState} = choose_pool(State#state{retasks = fyler_queue:in(Task, ReTasks), pools = NewPools}),\n+          {next_state, NextState, NewState}\n+      end;\n+    _ ->\n+      {next_state, tasks, State#state{pools = Pools}}\n+  end;\n+\n+tasks_({run, #task{priority = Priority} = Task}, #state{tasks = Tasks, priorities = Priorities} = State) ->","path":"apps/fyler/src/fyler_category_manager.erl","position":420,"original_position":420,"commit_id":"722fb3e10f3f0c3642ce2137196fb5a4afe743dd","original_commit_id":"722fb3e10f3f0c3642ce2137196fb5a4afe743dd","user":{"login":"elvisci","id":8136322,"avatar_url":"https://avatars.githubusercontent.com/u/8136322?v=3","gravatar_id":"","url":"https://api.github.com/users/elvisci","html_url":"https://github.com/elvisci","followers_url":"https://api.github.com/users/elvisci/followers","following_url":"https://api.github.com/users/elvisci/following{/other_user}","gists_url":"https://api.github.com/users/elvisci/gists{/gist_id}","starred_url":"https://api.github.com/users/elvisci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elvisci/subscriptions","organizations_url":"https://api.github.com/users/elvisci/orgs","repos_url":"https://api.github.com/users/elvisci/repos","events_url":"https://api.github.com/users/elvisci/events{/privacy}","received_events_url":"https://api.github.com/users/elvisci/received_events","type":"User","site_admin":false},"body":"Line 420 is too long: tasks_({run, #task{priority = Priority} = Task}, #state{tasks = Tasks, priorities = Priorities} = State) ->.","created_at":"2015-05-27T12:04:12Z","updated_at":"2015-05-27T12:04:12Z","html_url":"https://github.com/fyler/fyler/pull/3#discussion_r31126063","pull_request_url":"https://api.github.com/repos/fyler/fyler/pulls/3","_links":{"self":{"href":"https://api.github.com/repos/fyler/fyler/pulls/comments/31126063"},"html":{"href":"https://github.com/fyler/fyler/pull/3#discussion_r31126063"},"pull_request":{"href":"https://api.github.com/repos/fyler/fyler/pulls/3"}}},"pull_request":{"url":"https://api.github.com/repos/fyler/fyler/pulls/3","id":35844700,"html_url":"https://github.com/fyler/fyler/pull/3","diff_url":"https://github.com/fyler/fyler/pull/3.diff","patch_url":"https://github.com/fyler/fyler/pull/3.patch","issue_url":"https://api.github.com/repos/fyler/fyler/issues/3","number":3,"state":"closed","locked":false,"title":"Dev ilia","user":{"login":"silkbottle","id":4836648,"avatar_url":"https://avatars.githubusercontent.com/u/4836648?v=3","gravatar_id":"","url":"https://api.github.com/users/silkbottle","html_url":"https://github.com/silkbottle","followers_url":"https://api.github.com/users/silkbottle/followers","following_url":"https://api.github.com/users/silkbottle/following{/other_user}","gists_url":"https://api.github.com/users/silkbottle/gists{/gist_id}","starred_url":"https://api.github.com/users/silkbottle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/silkbottle/subscriptions","organizations_url":"https://api.github.com/users/silkbottle/orgs","repos_url":"https://api.github.com/users/silkbottle/repos","events_url":"https://api.github.com/users/silkbottle/events{/privacy}","received_events_url":"https://api.github.com/users/silkbottle/received_events","type":"User","site_admin":false},"body":"add managers for each category and migrate from ibrowse to hackney","created_at":"2015-05-20T15:33:29Z","updated_at":"2015-05-27T12:04:12Z","closed_at":"2015-05-27T12:04:07Z","merged_at":null,"merge_commit_sha":"301b2cadcdfc090df1c58b223435522efc186ce8","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/fyler/fyler/pulls/3/commits","review_comments_url":"https://api.github.com/repos/fyler/fyler/pulls/3/comments","review_comment_url":"https://api.github.com/repos/fyler/fyler/pulls/comments{/number}","comments_url":"https://api.github.com/repos/fyler/fyler/issues/3/comments","statuses_url":"https://api.github.com/repos/fyler/fyler/statuses/722fb3e10f3f0c3642ce2137196fb5a4afe743dd","head":{"label":"fyler:dev_ilia","ref":"dev_ilia","sha":"722fb3e10f3f0c3642ce2137196fb5a4afe743dd","user":{"login":"fyler","id":8720842,"avatar_url":"https://avatars.githubusercontent.com/u/8720842?v=3","gravatar_id":"","url":"https://api.github.com/users/fyler","html_url":"https://github.com/fyler","followers_url":"https://api.github.com/users/fyler/followers","following_url":"https://api.github.com/users/fyler/following{/other_user}","gists_url":"https://api.github.com/users/fyler/gists{/gist_id}","starred_url":"https://api.github.com/users/fyler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fyler/subscriptions","organizations_url":"https://api.github.com/users/fyler/orgs","repos_url":"https://api.github.com/users/fyler/repos","events_url":"https://api.github.com/users/fyler/events{/privacy}","received_events_url":"https://api.github.com/users/fyler/received_events","type":"Organization","site_admin":false},"repo":{"id":12726738,"name":"fyler","full_name":"fyler/fyler","owner":{"login":"fyler","id":8720842,"avatar_url":"https://avatars.githubusercontent.com/u/8720842?v=3","gravatar_id":"","url":"https://api.github.com/users/fyler","html_url":"https://github.com/fyler","followers_url":"https://api.github.com/users/fyler/followers","following_url":"https://api.github.com/users/fyler/following{/other_user}","gists_url":"https://api.github.com/users/fyler/gists{/gist_id}","starred_url":"https://api.github.com/users/fyler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fyler/subscriptions","organizations_url":"https://api.github.com/users/fyler/orgs","repos_url":"https://api.github.com/users/fyler/repos","events_url":"https://api.github.com/users/fyler/events{/privacy}","received_events_url":"https://api.github.com/users/fyler/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/fyler/fyler","description":"Erlang application for handling file processing tasks","fork":false,"url":"https://api.github.com/repos/fyler/fyler","forks_url":"https://api.github.com/repos/fyler/fyler/forks","keys_url":"https://api.github.com/repos/fyler/fyler/keys{/key_id}","collaborators_url":"https://api.github.com/repos/fyler/fyler/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/fyler/fyler/teams","hooks_url":"https://api.github.com/repos/fyler/fyler/hooks","issue_events_url":"https://api.github.com/repos/fyler/fyler/issues/events{/number}","events_url":"https://api.github.com/repos/fyler/fyler/events","assignees_url":"https://api.github.com/repos/fyler/fyler/assignees{/user}","branches_url":"https://api.github.com/repos/fyler/fyler/branches{/branch}","tags_url":"https://api.github.com/repos/fyler/fyler/tags","blobs_url":"https://api.github.com/repos/fyler/fyler/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/fyler/fyler/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/fyler/fyler/git/refs{/sha}","trees_url":"https://api.github.com/repos/fyler/fyler/git/trees{/sha}","statuses_url":"https://api.github.com/repos/fyler/fyler/statuses/{sha}","languages_url":"https://api.github.com/repos/fyler/fyler/languages","stargazers_url":"https://api.github.com/repos/fyler/fyler/stargazers","contributors_url":"https://api.github.com/repos/fyler/fyler/contributors","subscribers_url":"https://api.github.com/repos/fyler/fyler/subscribers","subscription_url":"https://api.github.com/repos/fyler/fyler/subscription","commits_url":"https://api.github.com/repos/fyler/fyler/commits{/sha}","git_commits_url":"https://api.github.com/repos/fyler/fyler/git/commits{/sha}","comments_url":"https://api.github.com/repos/fyler/fyler/comments{/number}","issue_comment_url":"https://api.github.com/repos/fyler/fyler/issues/comments{/number}","contents_url":"https://api.github.com/repos/fyler/fyler/contents/{+path}","compare_url":"https://api.github.com/repos/fyler/fyler/compare/{base}...{head}","merges_url":"https://api.github.com/repos/fyler/fyler/merges","archive_url":"https://api.github.com/repos/fyler/fyler/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/fyler/fyler/downloads","issues_url":"https://api.github.com/repos/fyler/fyler/issues{/number}","pulls_url":"https://api.github.com/repos/fyler/fyler/pulls{/number}","milestones_url":"https://api.github.com/repos/fyler/fyler/milestones{/number}","notifications_url":"https://api.github.com/repos/fyler/fyler/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/fyler/fyler/labels{/name}","releases_url":"https://api.github.com/repos/fyler/fyler/releases{/id}","created_at":"2013-09-10T10:26:57Z","updated_at":"2015-02-10T13:08:22Z","pushed_at":"2015-05-27T12:04:07Z","git_url":"git://github.com/fyler/fyler.git","ssh_url":"git@github.com:fyler/fyler.git","clone_url":"https://github.com/fyler/fyler.git","svn_url":"https://github.com/fyler/fyler","homepage":"","size":127477,"stargazers_count":0,"watchers_count":0,"language":"Erlang","has_issues":true,"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"}},"base":{"label":"fyler:master","ref":"master","sha":"39e6f7759347534b3ed0a0d877a5c2b55220cf82","user":{"login":"fyler","id":8720842,"avatar_url":"https://avatars.githubusercontent.com/u/8720842?v=3","gravatar_id":"","url":"https://api.github.com/users/fyler","html_url":"https://github.com/fyler","followers_url":"https://api.github.com/users/fyler/followers","following_url":"https://api.github.com/users/fyler/following{/other_user}","gists_url":"https://api.github.com/users/fyler/gists{/gist_id}","starred_url":"https://api.github.com/users/fyler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fyler/subscriptions","organizations_url":"https://api.github.com/users/fyler/orgs","repos_url":"https://api.github.com/users/fyler/repos","events_url":"https://api.github.com/users/fyler/events{/privacy}","received_events_url":"https://api.github.com/users/fyler/received_events","type":"Organization","site_admin":false},"repo":{"id":12726738,"name":"fyler","full_name":"fyler/fyler","owner":{"login":"fyler","id":8720842,"avatar_url":"https://avatars.githubusercontent.com/u/8720842?v=3","gravatar_id":"","url":"https://api.github.com/users/fyler","html_url":"https://github.com/fyler","followers_url":"https://api.github.com/users/fyler/followers","following_url":"https://api.github.com/users/fyler/following{/other_user}","gists_url":"https://api.github.com/users/fyler/gists{/gist_id}","starred_url":"https://api.github.com/users/fyler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fyler/subscriptions","organizations_url":"https://api.github.com/users/fyler/orgs","repos_url":"https://api.github.com/users/fyler/repos","events_url":"https://api.github.com/users/fyler/events{/privacy}","received_events_url":"https://api.github.com/users/fyler/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/fyler/fyler","description":"Erlang application for handling file processing tasks","fork":false,"url":"https://api.github.com/repos/fyler/fyler","forks_url":"https://api.github.com/repos/fyler/fyler/forks","keys_url":"https://api.github.com/repos/fyler/fyler/keys{/key_id}","collaborators_url":"https://api.github.com/repos/fyler/fyler/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/fyler/fyler/teams","hooks_url":"https://api.github.com/repos/fyler/fyler/hooks","issue_events_url":"https://api.github.com/repos/fyler/fyler/issues/events{/number}","events_url":"https://api.github.com/repos/fyler/fyler/events","assignees_url":"https://api.github.com/repos/fyler/fyler/assignees{/user}","branches_url":"https://api.github.com/repos/fyler/fyler/branches{/branch}","tags_url":"https://api.github.com/repos/fyler/fyler/tags","blobs_url":"https://api.github.com/repos/fyler/fyler/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/fyler/fyler/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/fyler/fyler/git/refs{/sha}","trees_url":"https://api.github.com/repos/fyler/fyler/git/trees{/sha}","statuses_url":"https://api.github.com/repos/fyler/fyler/statuses/{sha}","languages_url":"https://api.github.com/repos/fyler/fyler/languages","stargazers_url":"https://api.github.com/repos/fyler/fyler/stargazers","contributors_url":"https://api.github.com/repos/fyler/fyler/contributors","subscribers_url":"https://api.github.com/repos/fyler/fyler/subscribers","subscription_url":"https://api.github.com/repos/fyler/fyler/subscription","commits_url":"https://api.github.com/repos/fyler/fyler/commits{/sha}","git_commits_url":"https://api.github.com/repos/fyler/fyler/git/commits{/sha}","comments_url":"https://api.github.com/repos/fyler/fyler/comments{/number}","issue_comment_url":"https://api.github.com/repos/fyler/fyler/issues/comments{/number}","contents_url":"https://api.github.com/repos/fyler/fyler/contents/{+path}","compare_url":"https://api.github.com/repos/fyler/fyler/compare/{base}...{head}","merges_url":"https://api.github.com/repos/fyler/fyler/merges","archive_url":"https://api.github.com/repos/fyler/fyler/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/fyler/fyler/downloads","issues_url":"https://api.github.com/repos/fyler/fyler/issues{/number}","pulls_url":"https://api.github.com/repos/fyler/fyler/pulls{/number}","milestones_url":"https://api.github.com/repos/fyler/fyler/milestones{/number}","notifications_url":"https://api.github.com/repos/fyler/fyler/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/fyler/fyler/labels{/name}","releases_url":"https://api.github.com/repos/fyler/fyler/releases{/id}","created_at":"2013-09-10T10:26:57Z","updated_at":"2015-02-10T13:08:22Z","pushed_at":"2015-05-27T12:04:07Z","git_url":"git://github.com/fyler/fyler.git","ssh_url":"git@github.com:fyler/fyler.git","clone_url":"https://github.com/fyler/fyler.git","svn_url":"https://github.com/fyler/fyler","homepage":"","size":127477,"stargazers_count":0,"watchers_count":0,"language":"Erlang","has_issues":true,"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/fyler/fyler/pulls/3"},"html":{"href":"https://github.com/fyler/fyler/pull/3"},"issue":{"href":"https://api.github.com/repos/fyler/fyler/issues/3"},"comments":{"href":"https://api.github.com/repos/fyler/fyler/issues/3/comments"},"review_comments":{"href":"https://api.github.com/repos/fyler/fyler/pulls/3/comments"},"review_comment":{"href":"https://api.github.com/repos/fyler/fyler/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/fyler/fyler/pulls/3/commits"},"statuses":{"href":"https://api.github.com/repos/fyler/fyler/statuses/722fb3e10f3f0c3642ce2137196fb5a4afe743dd"}}}}