{"action":"created","comment":{"url":"https://api.github.com/repos/mesosphere/RENDLER/pulls/comments/34221463","id":34221463,"diff_hunk":"@@ -1,281 +1,284 @@\n package main\n \n import (\n-\t\"code.google.com/p/goprotobuf/proto\"\n \t\"container/list\"\n \t\"encoding/json\"\n \t\"flag\"\n \t\"fmt\"\n-\t\"github.com/mesosphere/mesos-go/mesos\"\n+\t\"github.com/golang/protobuf/proto\"\n+\tmesos \"github.com/mesos/mesos-go/mesosproto\"\n+\t\"github.com/mesos/mesos-go/mesosutil\"\n+\tsched \"github.com/mesos/mesos-go/scheduler\"\n \t\"github.com/mesosphere/rendler\"\n \t\"log\"\n \t\"os\"\n \t\"os/signal\"\n-\t\"time\"\n \t\"path/filepath\"\n+\t\"time\"\n )\n \n-const TASK_CPUS = 0.1\n-const TASK_MEM = 32.0\n-const SHUTDOWN_TIMEOUT = 30  // in seconds\n-\n-func main() {\n-\tcrawlQueue := list.New()  // list of string\n-\trenderQueue := list.New() // list of string\n+const (\n+\tTASK_CPUS        = 0.1\n+\tTASK_MEM         = 32.0\n+\tSHUTDOWN_TIMEOUT = time.Duration(30) * time.Second\n+)\n \n-\tprocessedURLs := list.New() // list of string\n-\tcrawlResults := list.New()  // list of CrawlEdge\n-\trenderResults := make(map[string]string)\n+var (\n+\tcrawlCommand  = \"python crawl_executor.py\"\n+\trenderCommand = \"python render_executor.py\"\n+)\n \n-\tseedUrl := flag.String(\"seed\", \"http://mesosphere.io\", \"The first URL to crawl\")\n-\tmaster := flag.String(\"master\", \"127.0.1.1:5050\", \"Location of leading Mesos master\")\n-\tlocalMode := flag.Bool(\"local\", true, \"If true, saves rendered web pages on local disk\")\n-\t// TODO(nnielsen): Add flag for artifacts.\n+var (\n+\tDEFAULT_FILTER = &mesos.Filters{RefuseSeconds: proto.Float64(1)}\n+)\n \n-\tflag.Parse()\n+func maxTasksForOffer(offer *mesos.Offer) int {\n+\t// TODO(nnielsen): Parse offer resources.\n+\tcount := 0\n \n-\tcrawlQueue.PushBack(*seedUrl)\n+\tvar cpus float64 = 0\n+\tvar mem float64 = 0\n \n-\ttasksCreated := 0\n-\ttasksRunning := 0\n-\tshuttingDown := false\n+\tfor _, resource := range offer.Resources {\n+\t\tif resource.GetName() == \"cpus\" {\n+\t\t\tcpus = *resource.GetScalar().Value\n+\t\t}\n \n-\tcrawlCommand := \"python crawl_executor.py\"\n-\trenderCommand := \"python render_executor.py\"\n+\t\tif resource.GetName() == \"mem\" {\n+\t\t\tmem = *resource.GetScalar().Value\n+\t\t}\n+\t}\n \n-\tif *localMode {\n-\t\trenderCommand += \" --local\"\n+\tfor cpus >= TASK_CPUS && mem >= TASK_MEM {\n+\t\tcount++\n+\t\tcpus -= TASK_CPUS\n+\t\tmem -= TASK_MEM\n \t}\n \n+\treturn count\n+}\n+\n+type RendlerScheduler struct {\n+\ttasksCreated int\n+\ttasksRunning int\n+\n+\tcrawlQueue    *list.List\n+\trenderQueue   *list.List\n+\tprocessedURLs *list.List\n+\tcrawlResults  *list.List\n+\trenderResults map[string]string\n+\n+\tcrawlExecutor  *mesos.ExecutorInfo\n+\trenderExecutor *mesos.ExecutorInfo\n+\n+\t// this channel is closed when the program receives an interrupt,\n+\t// signalling that the program should shut down.\n+\tshutdown chan interface{}\n+\t// this channel is closed when there are no more outstanding tasks,\n+\t// and that the scheduler does not intend to receive more tasks\n+\tdone chan interface{}\n+}\n+\n+func NewRendlerScheduler(seedUrl string) *RendlerScheduler {\n \t// TODO(nnielsen): In local mode, verify artifact locations.\n \trendlerArtifacts := executorURIs()\n \n-\tcrawlExecutor := &mesos.ExecutorInfo{\n-\t\tExecutorId: &mesos.ExecutorID{Value: proto.String(\"crawl-executor\")},\n-\t\tCommand: &mesos.CommandInfo{\n-\t\t\tValue: proto.String(crawlCommand),\n-\t\t\tUris:  rendlerArtifacts,\n+\ts := &RendlerScheduler{\n+\t\tcrawlQueue:    list.New(),\n+\t\trenderQueue:   list.New(),\n+\t\tprocessedURLs: list.New(),\n+\t\tcrawlResults:  list.New(),\n+\t\trenderResults: make(map[string]string),\n+\n+\t\tcrawlExecutor: &mesos.ExecutorInfo{\n+\t\t\tExecutorId: &mesos.ExecutorID{Value: proto.String(\"crawl-executor\")},\n+\t\t\tCommand: &mesos.CommandInfo{\n+\t\t\t\tValue: proto.String(crawlCommand),\n+\t\t\t\tUris:  rendlerArtifacts,\n+\t\t\t},\n+\t\t\tName: proto.String(\"Crawler\"),\n \t\t},\n-\t\tName: proto.String(\"Crawler\"),\n-\t}\n \n-\trenderExecutor := &mesos.ExecutorInfo{\n-\t\tExecutorId: &mesos.ExecutorID{Value: proto.String(\"render-executor\")},\n-\t\tCommand: &mesos.CommandInfo{\n-\t\t\tValue: proto.String(renderCommand),\n-\t\t\tUris:  rendlerArtifacts,\n+\t\trenderExecutor: &mesos.ExecutorInfo{\n+\t\t\tExecutorId: &mesos.ExecutorID{Value: proto.String(\"render-executor\")},\n+\t\t\tCommand: &mesos.CommandInfo{\n+\t\t\t\tValue: proto.String(renderCommand),\n+\t\t\t\tUris:  rendlerArtifacts,\n+\t\t\t},\n+\t\t\tName: proto.String(\"Renderer\"),\n \t\t},\n-\t\tName: proto.String(\"Renderer\"),\n-\t}\n \n-\tmakeTaskPrototype := func(offer mesos.Offer) *mesos.TaskInfo {\n-\t\ttaskId := tasksCreated\n-\t\ttasksCreated++\n-\t\treturn &mesos.TaskInfo{\n-\t\t\tTaskId: &mesos.TaskID{\n-\t\t\t\tValue: proto.String(fmt.Sprintf(\"RENDLER-%d\", taskId)),\n-\t\t\t},\n-\t\t\tSlaveId: offer.SlaveId,\n-\t\t\tResources: []*mesos.Resource{\n-\t\t\t\tmesos.ScalarResource(\"cpus\", TASK_CPUS),\n-\t\t\t\tmesos.ScalarResource(\"mem\", TASK_MEM),\n-\t\t\t},\n-\t\t}\n+\t\tshutdown: make(chan interface{}),\n+\t\tdone:     make(chan interface{}),\n \t}\n+\ts.crawlQueue.PushBack(seedUrl)\n+\treturn s\n+}\n \n-\tmakeCrawlTask := func(url string, offer mesos.Offer) *mesos.TaskInfo {\n-\t\ttask := makeTaskPrototype(offer)\n-\t\ttask.Name = proto.String(\"CRAWL_\" + *task.TaskId.Value)\n-\t\ttask.Executor = crawlExecutor\n-\t\ttask.Data = []byte(url)\n-\t\treturn task\n+func (s *RendlerScheduler) makeTaskPrototype(offer *mesos.Offer) *mesos.TaskInfo {\n+\ttaskId := s.tasksCreated\n+\ts.tasksCreated++\n+\treturn &mesos.TaskInfo{\n+\t\tTaskId: &mesos.TaskID{\n+\t\t\tValue: proto.String(fmt.Sprintf(\"RENDLER-%d\", taskId)),\n+\t\t},\n+\t\tSlaveId: offer.SlaveId,\n+\t\tResources: []*mesos.Resource{\n+\t\t\tmesosutil.NewScalarResource(\"cpus\", TASK_CPUS),\n+\t\t\tmesosutil.NewScalarResource(\"mem\", TASK_MEM),\n+\t\t},\n \t}\n+}\n \n-\tmakeRenderTask := func(url string, offer mesos.Offer) *mesos.TaskInfo {\n-\t\ttask := makeTaskPrototype(offer)\n-\t\ttask.Name = proto.String(\"RENDER_\" + *task.TaskId.Value)\n-\t\ttask.Executor = renderExecutor\n-\t\ttask.Data = []byte(url)\n-\t\treturn task\n-\t}\n+func (s *RendlerScheduler) makeCrawlTask(url string, offer *mesos.Offer) *mesos.TaskInfo {\n+\ttask := s.makeTaskPrototype(offer)\n+\ttask.Name = proto.String(\"CRAWL_\" + *task.TaskId.Value)\n+\ttask.Executor = s.crawlExecutor\n+\ttask.Data = []byte(url)\n+\treturn task\n+}\n \n-\tmaxTasksForOffer := func(offer mesos.Offer) int {\n-\t\t// TODO(nnielsen): Parse offer resources.\n-\t\tcount := 0\n+func (s *RendlerScheduler) makeRenderTask(url string, offer *mesos.Offer) *mesos.TaskInfo {\n+\ttask := s.makeTaskPrototype(offer)\n+\ttask.Name = proto.String(\"RENDER_\" + *task.TaskId.Value)\n+\ttask.Executor = s.renderExecutor\n+\ttask.Data = []byte(url)\n+\treturn task\n+}\n \n-\t\tvar cpus float64 = 0\n-\t\tvar mem float64 = 0\n+func (s *RendlerScheduler) Registered(\n+\tdriver sched.SchedulerDriver,\n+\tframeworkId *mesos.FrameworkID,\n+\tmasterInfo *mesos.MasterInfo) {\n+\tlog.Printf(\"Registered\")\n+}\n \n-\t\tfor _, resource := range offer.Resources {\n-\t\t\tif resource.GetName() == \"cpus\" {\n-\t\t\t\tcpus = *resource.GetScalar().Value\n-\t\t\t}\n+func (s *RendlerScheduler) Reregistered(driver sched.SchedulerDriver, masterInfo *mesos.MasterInfo) {\n+\tlog.Println(\"Framework Re-Registered with Master \", masterInfo)\n+}\n \n-\t\t\tif resource.GetName() == \"mem\" {\n-\t\t\t\tmem = *resource.GetScalar().Value\n+func (s *RendlerScheduler) Disconnected(sched.SchedulerDriver) {\n+\tlog.Println(\"Framework disconnected with Master\")\n+}\n+\n+func (s *RendlerScheduler) ResourceOffers(driver sched.SchedulerDriver, offers []*mesos.Offer) {\n+\tlog.Printf(\"Received %d resource offers\", len(offers))\n+\tfor _, offer := range offers {\n+\t\tselect {\n+\t\tcase <-s.shutdown:\n+\t\t\tlog.Println(\"Shutting down: declining offer on [\", offer.Hostname, \"]\")\n+\t\t\tdriver.DeclineOffer(offer.Id, DEFAULT_FILTER)\n+\t\t\tcontinue\n+\t\tdefault:\n+\t\t\ttasks := []*mesos.TaskInfo{}\n+\n+\t\t\tfor i := 0; i < maxTasksForOffer(offer)/2; i++ {\n+\t\t\t\tif s.crawlQueue.Front() != nil {\n+\t\t\t\t\turl := s.crawlQueue.Front().Value.(string)\n+\t\t\t\t\ts.crawlQueue.Remove(s.crawlQueue.Front())\n+\t\t\t\t\ttask := s.makeCrawlTask(url, offer)\n+\t\t\t\t\ttasks = append(tasks, task)\n+\t\t\t\t}\n+\t\t\t\tif s.renderQueue.Front() != nil {\n+\t\t\t\t\turl := s.renderQueue.Front().Value.(string)\n+\t\t\t\t\ts.renderQueue.Remove(s.renderQueue.Front())\n+\t\t\t\t\ttask := s.makeRenderTask(url, offer)\n+\t\t\t\t\ttasks = append(tasks, task)\n+\t\t\t\t}\n \t\t\t}\n-\t\t}\n \n-\t\tfor cpus >= TASK_CPUS && mem >= TASK_MEM {\n-\t\t\tcount++\n-\t\t\tcpus -= TASK_CPUS\n-\t\t\tmem -= TASK_MEM\n+\t\t\tif len(tasks) == 0 {\n+\t\t\t\tdriver.DeclineOffer(offer.Id, DEFAULT_FILTER)\n+\t\t\t} else {\n+\t\t\t\tdriver.LaunchTasks([]*mesos.OfferID{offer.Id}, tasks, DEFAULT_FILTER)\n+\t\t\t}\n \t\t}\n-\n-\t\treturn count\n \t}\n+}\n \n-\tprintQueueStatistics := func() {\n-\t\t// TODO(nnielsen): Print queue lengths.\n+func (s *RendlerScheduler) StatusUpdate(driver sched.SchedulerDriver, status *mesos.TaskStatus) {\n+\tlog.Printf(\"Received task status [%s] for task [%s]\", rendler.NameFor(status.State), *status.TaskId.Value)\n+\n+\tif *status.State == mesos.TaskState_TASK_RUNNING {\n+\t\ts.tasksRunning++\n+\t} else if rendler.IsTerminal(status.State) {\n+\t\ts.tasksRunning--\n+\t\tif s.tasksRunning == 0 {","path":"go/src/github.com/mesosphere/rendler/scheduler/main.go","position":292,"original_position":292,"commit_id":"9a132be55b347e993e08685c9fb0f8a0faa58e9f","original_commit_id":"9a132be55b347e993e08685c9fb0f8a0faa58e9f","user":{"login":"derekchiang","id":1535686,"avatar_url":"https://avatars.githubusercontent.com/u/1535686?v=3","gravatar_id":"","url":"https://api.github.com/users/derekchiang","html_url":"https://github.com/derekchiang","followers_url":"https://api.github.com/users/derekchiang/followers","following_url":"https://api.github.com/users/derekchiang/following{/other_user}","gists_url":"https://api.github.com/users/derekchiang/gists{/gist_id}","starred_url":"https://api.github.com/users/derekchiang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/derekchiang/subscriptions","organizations_url":"https://api.github.com/users/derekchiang/orgs","repos_url":"https://api.github.com/users/derekchiang/repos","events_url":"https://api.github.com/users/derekchiang/events{/privacy}","received_events_url":"https://api.github.com/users/derekchiang/received_events","type":"User","site_admin":false},"body":"To reduce nesting?  The code looks fine to me as the logic is pretty clear.","created_at":"2015-07-09T03:44:17Z","updated_at":"2015-07-09T03:44:17Z","html_url":"https://github.com/mesosphere/RENDLER/pull/29#discussion_r34221463","pull_request_url":"https://api.github.com/repos/mesosphere/RENDLER/pulls/29","_links":{"self":{"href":"https://api.github.com/repos/mesosphere/RENDLER/pulls/comments/34221463"},"html":{"href":"https://github.com/mesosphere/RENDLER/pull/29#discussion_r34221463"},"pull_request":{"href":"https://api.github.com/repos/mesosphere/RENDLER/pulls/29"}}},"pull_request":{"url":"https://api.github.com/repos/mesosphere/RENDLER/pulls/29","id":39338235,"html_url":"https://github.com/mesosphere/RENDLER/pull/29","diff_url":"https://github.com/mesosphere/RENDLER/pull/29.diff","patch_url":"https://github.com/mesosphere/RENDLER/pull/29.patch","issue_url":"https://api.github.com/repos/mesosphere/RENDLER/issues/29","number":29,"state":"open","locked":false,"title":"Update the Go code","user":{"login":"derekchiang","id":1535686,"avatar_url":"https://avatars.githubusercontent.com/u/1535686?v=3","gravatar_id":"","url":"https://api.github.com/users/derekchiang","html_url":"https://github.com/derekchiang","followers_url":"https://api.github.com/users/derekchiang/followers","following_url":"https://api.github.com/users/derekchiang/following{/other_user}","gists_url":"https://api.github.com/users/derekchiang/gists{/gist_id}","starred_url":"https://api.github.com/users/derekchiang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/derekchiang/subscriptions","organizations_url":"https://api.github.com/users/derekchiang/orgs","repos_url":"https://api.github.com/users/derekchiang/repos","events_url":"https://api.github.com/users/derekchiang/events{/privacy}","received_events_url":"https://api.github.com/users/derekchiang/received_events","type":"User","site_admin":false},"body":"Comparing to the original code, the new code:\r\n\r\n1. Use the most up-to-date `mesos-go`\r\n2. Is more idiomatic\r\n3. Is less buggy\r\n\r\n@tsenart please take a look.  I will add more text to the README later to make it more like a tutorial.","created_at":"2015-07-07T06:18:08Z","updated_at":"2015-07-09T03:44:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"715ce195673ba9ce03f450d0c0579339ad6f1018","assignee":{"login":"derekchiang","id":1535686,"avatar_url":"https://avatars.githubusercontent.com/u/1535686?v=3","gravatar_id":"","url":"https://api.github.com/users/derekchiang","html_url":"https://github.com/derekchiang","followers_url":"https://api.github.com/users/derekchiang/followers","following_url":"https://api.github.com/users/derekchiang/following{/other_user}","gists_url":"https://api.github.com/users/derekchiang/gists{/gist_id}","starred_url":"https://api.github.com/users/derekchiang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/derekchiang/subscriptions","organizations_url":"https://api.github.com/users/derekchiang/orgs","repos_url":"https://api.github.com/users/derekchiang/repos","events_url":"https://api.github.com/users/derekchiang/events{/privacy}","received_events_url":"https://api.github.com/users/derekchiang/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/mesosphere/RENDLER/pulls/29/commits","review_comments_url":"https://api.github.com/repos/mesosphere/RENDLER/pulls/29/comments","review_comment_url":"https://api.github.com/repos/mesosphere/RENDLER/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mesosphere/RENDLER/issues/29/comments","statuses_url":"https://api.github.com/repos/mesosphere/RENDLER/statuses/9a132be55b347e993e08685c9fb0f8a0faa58e9f","head":{"label":"derekchiang:master","ref":"master","sha":"9a132be55b347e993e08685c9fb0f8a0faa58e9f","user":{"login":"derekchiang","id":1535686,"avatar_url":"https://avatars.githubusercontent.com/u/1535686?v=3","gravatar_id":"","url":"https://api.github.com/users/derekchiang","html_url":"https://github.com/derekchiang","followers_url":"https://api.github.com/users/derekchiang/followers","following_url":"https://api.github.com/users/derekchiang/following{/other_user}","gists_url":"https://api.github.com/users/derekchiang/gists{/gist_id}","starred_url":"https://api.github.com/users/derekchiang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/derekchiang/subscriptions","organizations_url":"https://api.github.com/users/derekchiang/orgs","repos_url":"https://api.github.com/users/derekchiang/repos","events_url":"https://api.github.com/users/derekchiang/events{/privacy}","received_events_url":"https://api.github.com/users/derekchiang/received_events","type":"User","site_admin":false},"repo":{"id":38667660,"name":"RENDLER","full_name":"derekchiang/RENDLER","owner":{"login":"derekchiang","id":1535686,"avatar_url":"https://avatars.githubusercontent.com/u/1535686?v=3","gravatar_id":"","url":"https://api.github.com/users/derekchiang","html_url":"https://github.com/derekchiang","followers_url":"https://api.github.com/users/derekchiang/followers","following_url":"https://api.github.com/users/derekchiang/following{/other_user}","gists_url":"https://api.github.com/users/derekchiang/gists{/gist_id}","starred_url":"https://api.github.com/users/derekchiang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/derekchiang/subscriptions","organizations_url":"https://api.github.com/users/derekchiang/orgs","repos_url":"https://api.github.com/users/derekchiang/repos","events_url":"https://api.github.com/users/derekchiang/events{/privacy}","received_events_url":"https://api.github.com/users/derekchiang/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/derekchiang/RENDLER","description":"A rendering web crawler for Apache Mesos.","fork":true,"url":"https://api.github.com/repos/derekchiang/RENDLER","forks_url":"https://api.github.com/repos/derekchiang/RENDLER/forks","keys_url":"https://api.github.com/repos/derekchiang/RENDLER/keys{/key_id}","collaborators_url":"https://api.github.com/repos/derekchiang/RENDLER/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/derekchiang/RENDLER/teams","hooks_url":"https://api.github.com/repos/derekchiang/RENDLER/hooks","issue_events_url":"https://api.github.com/repos/derekchiang/RENDLER/issues/events{/number}","events_url":"https://api.github.com/repos/derekchiang/RENDLER/events","assignees_url":"https://api.github.com/repos/derekchiang/RENDLER/assignees{/user}","branches_url":"https://api.github.com/repos/derekchiang/RENDLER/branches{/branch}","tags_url":"https://api.github.com/repos/derekchiang/RENDLER/tags","blobs_url":"https://api.github.com/repos/derekchiang/RENDLER/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/derekchiang/RENDLER/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/derekchiang/RENDLER/git/refs{/sha}","trees_url":"https://api.github.com/repos/derekchiang/RENDLER/git/trees{/sha}","statuses_url":"https://api.github.com/repos/derekchiang/RENDLER/statuses/{sha}","languages_url":"https://api.github.com/repos/derekchiang/RENDLER/languages","stargazers_url":"https://api.github.com/repos/derekchiang/RENDLER/stargazers","contributors_url":"https://api.github.com/repos/derekchiang/RENDLER/contributors","subscribers_url":"https://api.github.com/repos/derekchiang/RENDLER/subscribers","subscription_url":"https://api.github.com/repos/derekchiang/RENDLER/subscription","commits_url":"https://api.github.com/repos/derekchiang/RENDLER/commits{/sha}","git_commits_url":"https://api.github.com/repos/derekchiang/RENDLER/git/commits{/sha}","comments_url":"https://api.github.com/repos/derekchiang/RENDLER/comments{/number}","issue_comment_url":"https://api.github.com/repos/derekchiang/RENDLER/issues/comments{/number}","contents_url":"https://api.github.com/repos/derekchiang/RENDLER/contents/{+path}","compare_url":"https://api.github.com/repos/derekchiang/RENDLER/compare/{base}...{head}","merges_url":"https://api.github.com/repos/derekchiang/RENDLER/merges","archive_url":"https://api.github.com/repos/derekchiang/RENDLER/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/derekchiang/RENDLER/downloads","issues_url":"https://api.github.com/repos/derekchiang/RENDLER/issues{/number}","pulls_url":"https://api.github.com/repos/derekchiang/RENDLER/pulls{/number}","milestones_url":"https://api.github.com/repos/derekchiang/RENDLER/milestones{/number}","notifications_url":"https://api.github.com/repos/derekchiang/RENDLER/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/derekchiang/RENDLER/labels{/name}","releases_url":"https://api.github.com/repos/derekchiang/RENDLER/releases{/id}","created_at":"2015-07-07T06:08:20Z","updated_at":"2015-07-07T06:08:21Z","pushed_at":"2015-07-07T06:14:47Z","git_url":"git://github.com/derekchiang/RENDLER.git","ssh_url":"git@github.com:derekchiang/RENDLER.git","clone_url":"https://github.com/derekchiang/RENDLER.git","svn_url":"https://github.com/derekchiang/RENDLER","homepage":null,"size":3198,"stargazers_count":0,"watchers_count":0,"language":"Python","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"}},"base":{"label":"mesosphere:master","ref":"master","sha":"cbb9a15cc9e7439c69d10df86a0783649fb0127c","user":{"login":"mesosphere","id":3458585,"avatar_url":"https://avatars.githubusercontent.com/u/3458585?v=3","gravatar_id":"","url":"https://api.github.com/users/mesosphere","html_url":"https://github.com/mesosphere","followers_url":"https://api.github.com/users/mesosphere/followers","following_url":"https://api.github.com/users/mesosphere/following{/other_user}","gists_url":"https://api.github.com/users/mesosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/mesosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mesosphere/subscriptions","organizations_url":"https://api.github.com/users/mesosphere/orgs","repos_url":"https://api.github.com/users/mesosphere/repos","events_url":"https://api.github.com/users/mesosphere/events{/privacy}","received_events_url":"https://api.github.com/users/mesosphere/received_events","type":"Organization","site_admin":false},"repo":{"id":19680225,"name":"RENDLER","full_name":"mesosphere/RENDLER","owner":{"login":"mesosphere","id":3458585,"avatar_url":"https://avatars.githubusercontent.com/u/3458585?v=3","gravatar_id":"","url":"https://api.github.com/users/mesosphere","html_url":"https://github.com/mesosphere","followers_url":"https://api.github.com/users/mesosphere/followers","following_url":"https://api.github.com/users/mesosphere/following{/other_user}","gists_url":"https://api.github.com/users/mesosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/mesosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mesosphere/subscriptions","organizations_url":"https://api.github.com/users/mesosphere/orgs","repos_url":"https://api.github.com/users/mesosphere/repos","events_url":"https://api.github.com/users/mesosphere/events{/privacy}","received_events_url":"https://api.github.com/users/mesosphere/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mesosphere/RENDLER","description":"A rendering web crawler for Apache Mesos.","fork":false,"url":"https://api.github.com/repos/mesosphere/RENDLER","forks_url":"https://api.github.com/repos/mesosphere/RENDLER/forks","keys_url":"https://api.github.com/repos/mesosphere/RENDLER/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mesosphere/RENDLER/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mesosphere/RENDLER/teams","hooks_url":"https://api.github.com/repos/mesosphere/RENDLER/hooks","issue_events_url":"https://api.github.com/repos/mesosphere/RENDLER/issues/events{/number}","events_url":"https://api.github.com/repos/mesosphere/RENDLER/events","assignees_url":"https://api.github.com/repos/mesosphere/RENDLER/assignees{/user}","branches_url":"https://api.github.com/repos/mesosphere/RENDLER/branches{/branch}","tags_url":"https://api.github.com/repos/mesosphere/RENDLER/tags","blobs_url":"https://api.github.com/repos/mesosphere/RENDLER/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mesosphere/RENDLER/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mesosphere/RENDLER/git/refs{/sha}","trees_url":"https://api.github.com/repos/mesosphere/RENDLER/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mesosphere/RENDLER/statuses/{sha}","languages_url":"https://api.github.com/repos/mesosphere/RENDLER/languages","stargazers_url":"https://api.github.com/repos/mesosphere/RENDLER/stargazers","contributors_url":"https://api.github.com/repos/mesosphere/RENDLER/contributors","subscribers_url":"https://api.github.com/repos/mesosphere/RENDLER/subscribers","subscription_url":"https://api.github.com/repos/mesosphere/RENDLER/subscription","commits_url":"https://api.github.com/repos/mesosphere/RENDLER/commits{/sha}","git_commits_url":"https://api.github.com/repos/mesosphere/RENDLER/git/commits{/sha}","comments_url":"https://api.github.com/repos/mesosphere/RENDLER/comments{/number}","issue_comment_url":"https://api.github.com/repos/mesosphere/RENDLER/issues/comments{/number}","contents_url":"https://api.github.com/repos/mesosphere/RENDLER/contents/{+path}","compare_url":"https://api.github.com/repos/mesosphere/RENDLER/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mesosphere/RENDLER/merges","archive_url":"https://api.github.com/repos/mesosphere/RENDLER/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mesosphere/RENDLER/downloads","issues_url":"https://api.github.com/repos/mesosphere/RENDLER/issues{/number}","pulls_url":"https://api.github.com/repos/mesosphere/RENDLER/pulls{/number}","milestones_url":"https://api.github.com/repos/mesosphere/RENDLER/milestones{/number}","notifications_url":"https://api.github.com/repos/mesosphere/RENDLER/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mesosphere/RENDLER/labels{/name}","releases_url":"https://api.github.com/repos/mesosphere/RENDLER/releases{/id}","created_at":"2014-05-11T23:32:16Z","updated_at":"2015-07-03T09:24:16Z","pushed_at":"2015-07-07T06:18:08Z","git_url":"git://github.com/mesosphere/RENDLER.git","ssh_url":"git@github.com:mesosphere/RENDLER.git","clone_url":"https://github.com/mesosphere/RENDLER.git","svn_url":"https://github.com/mesosphere/RENDLER","homepage":null,"size":3198,"stargazers_count":62,"watchers_count":62,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":19,"mirror_url":null,"open_issues_count":9,"forks":19,"open_issues":9,"watchers":62,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mesosphere/RENDLER/pulls/29"},"html":{"href":"https://github.com/mesosphere/RENDLER/pull/29"},"issue":{"href":"https://api.github.com/repos/mesosphere/RENDLER/issues/29"},"comments":{"href":"https://api.github.com/repos/mesosphere/RENDLER/issues/29/comments"},"review_comments":{"href":"https://api.github.com/repos/mesosphere/RENDLER/pulls/29/comments"},"review_comment":{"href":"https://api.github.com/repos/mesosphere/RENDLER/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mesosphere/RENDLER/pulls/29/commits"},"statuses":{"href":"https://api.github.com/repos/mesosphere/RENDLER/statuses/9a132be55b347e993e08685c9fb0f8a0faa58e9f"}}}}