{"action":"created","comment":{"url":"https://api.github.com/repos/broadinstitute/rawls/pulls/comments/70687172","id":70687172,"diff_hunk":"@@ -0,0 +1,115 @@\n+package org.broadinstitute.dsde.rawls.dataaccess\n+\n+import _root_.slick.dbio.Effect.{Write, Read}\n+import _root_.slick.dbio._\n+import _root_.slick.driver.JdbcDriver\n+import org.broadinstitute.dsde.rawls.RawlsException\n+import org.broadinstitute.dsde.rawls.dataaccess.slick.WorkflowRecord\n+import org.broadinstitute.dsde.rawls.model._\n+\n+import scala.concurrent._\n+import scala.concurrent.Future._\n+import scala.concurrent.ExecutionContext.Implicits.global\n+import scala.concurrent.{ExecutionContext, Future}\n+import scala.util.{Failure, Success, Try}\n+\n+\n+class ShardedHttpExecutionServiceCluster (members: Map[ExecutionServiceId,ExecutionServiceDAO], default: ExecutionServiceId, dataSource: SlickDataSource) extends ExecutionServiceCluster {\n+\n+  // make a copy of the members map as an array for easy reads\n+  private val memberArray:Array[ClusterMember] = (members map {case (id, dao) => ClusterMember(id, dao)}).toArray\n+\n+  // find the default instance\n+  private val defaultEntry:(ExecutionServiceId, ExecutionServiceDAO) =\n+    members.find{case (esid, dao) => esid.id.equals(default.id)}\n+      .getOrElse(throw new RawlsException(s\"cannot initialize ShardedHttpExecutionServiceCluster: member with default key $default does not exist\"))\n+\n+\n+  // ====================\n+  // facade methods\n+  // ====================\n+\n+  // only used in tests??? TODO: DA update tests to use the same thing runtime does, or remove this.\n+  def submitWorkflow(wdl: String, inputs: String, options: Option[String], userInfo: UserInfo): Future[ExecutionServiceStatus] =\n+    getDefaultMember.submitWorkflow(wdl, inputs, options, userInfo)\n+\n+  // by nature, this is only called for workflows that have not yet been submitted.\n+  // therefore, we want to send the workflows to the cromwell instance chosen\n+  // by the routing algorithm defined in this class.\n+  def submitWorkflows(workflowRecs: Seq[WorkflowRecord], wdl: String, inputs: Seq[String], options: Option[String], userInfo: UserInfo): Future[(ExecutionServiceId, Seq[Either[ExecutionServiceStatus, ExecutionServiceFailure]])] = {\n+    val targetMember = nextAvailableMember(workflowRecs)\n+    targetMember.dao.submitWorkflows(wdl, inputs, options, userInfo) map {results =>\n+      (targetMember.key, results)\n+    }\n+  }\n+\n+  // following are called on a workflow that has already been submitted.\n+  // therefore, we want to use the cromwell instance that has been persisted\n+  // onto that workflow.\n+  def status(wfe: WorkflowExecution, userInfo: UserInfo): Future[ExecutionServiceStatus] =\n+    getMember(wfe).flatMap {memb => memb.status(wfe.id, userInfo)}\n+\n+  def callLevelMetadata(wfe: WorkflowExecution, userInfo: UserInfo): Future[ExecutionMetadata] =\n+    getMember(wfe).flatMap {memb => memb.callLevelMetadata(wfe.id, userInfo)}\n+\n+  def outputs(wfe: WorkflowExecution, userInfo: UserInfo): Future[ExecutionServiceOutputs] =\n+    getMember(wfe).flatMap {memb => memb.outputs(wfe.id, userInfo)}\n+\n+  def logs(wfe: WorkflowExecution, userInfo: UserInfo): Future[ExecutionServiceLogs] =\n+    getMember(wfe).flatMap {memb => memb.logs(wfe.id, userInfo)}\n+\n+  def abort(wfe: WorkflowExecution, userInfo: UserInfo): Future[Try[ExecutionServiceStatus]] =\n+    getMember(wfe).flatMap {memb => memb.abort(wfe.id, userInfo)}\n+\n+\n+  // ====================\n+  // facade-to-cluster entry points\n+  // ====================\n+  // for an already-submitted workflow, get the instance to which it was submitted\n+  private def getMember(wfe: WorkflowExecution):Future[ExecutionServiceDAO] = wfe.executionServiceId match {\n+    case Some(execId) => Future.successful(getMemberById(ExecutionServiceId(execId)))\n+    case None => {\n+      dataSource.inTransaction { dataAccess =>\n+        dataAccess.workflowQuery.getExecutionServiceKey(wfe.id) map {execIdOption =>\n+          execIdOption match {\n+            case Some(execId) => getMemberById(ExecutionServiceId(execId))\n+            case None => getDefaultMember //throw new RawlsException(\"can only process Workflow objects with an execution service key\")\n+          }\n+        }\n+      }\n+    }\n+  }\n+\n+  // for unsubmitted workflows, get the best instance to which we should submit\n+  // we expect that all workflowRecs passed to this method will be a single batch;\n+  // we return one target cromwell instance for the entire batch.\n+  private def nextAvailableMember(workflowRecs: Seq[WorkflowRecord]): ClusterMember = {\n+    // inspect the first workflow in the batch, retrieve a long value of its last-updated timestamp\n+    // (could also use workflowId or some other number)\n+    val shardingSeed = workflowRecs.head.statusLastChangedDate.getTime\n+    val shardIndex = targetIndex(shardingSeed, members.size)\n+\n+    memberArray(shardIndex)\n+  }\n+\n+\n+\n+  // ====================\n+  // clustering methods\n+  // ====================\n+  private def getMemberById(key: ExecutionServiceId): ExecutionServiceDAO = members.get(key).orElse(throw new RawlsException(s\"member with key $key does not exist\")).get\n+\n+  private def getDefaultEntry:(ExecutionServiceId, ExecutionServiceDAO) = defaultEntry\n+  def getDefaultMember: ExecutionServiceDAO = getDefaultEntry._2\n+\n+  def targetIndex(seed: Long, numTargets: Int):Int = Math.ceil( (seed % 100) / (100 / numTargets) ).toInt","path":"src/main/scala/org/broadinstitute/dsde/rawls/dataaccess/ShardedHttpExecutionServiceCluster.scala","position":105,"original_position":105,"commit_id":"c0a41e16d324126c554b042a9603036894729b01","original_commit_id":"9365dab43e36c7fd9f8523bcc114be1c46233918","user":{"login":"davidangb","id":6041577,"avatar_url":"https://avatars.githubusercontent.com/u/6041577?v=3","gravatar_id":"","url":"https://api.github.com/users/davidangb","html_url":"https://github.com/davidangb","followers_url":"https://api.github.com/users/davidangb/followers","following_url":"https://api.github.com/users/davidangb/following{/other_user}","gists_url":"https://api.github.com/users/davidangb/gists{/gist_id}","starred_url":"https://api.github.com/users/davidangb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidangb/subscriptions","organizations_url":"https://api.github.com/users/davidangb/orgs","repos_url":"https://api.github.com/users/davidangb/repos","events_url":"https://api.github.com/users/davidangb/events{/privacy}","received_events_url":"https://api.github.com/users/davidangb/received_events","type":"User","site_admin":false},"body":"HAHAHA I suppose that would be simpler, wouldn't it? I really wanted to prove out a code path that inspects the inbound workflow(s), and routes based on some criteria of that workflow. By the time I ended up here ... I never looked back to re-simplify.","created_at":"2016-07-13T18:57:36Z","updated_at":"2016-07-13T18:57:36Z","html_url":"https://github.com/broadinstitute/rawls/pull/475#discussion_r70687172","pull_request_url":"https://api.github.com/repos/broadinstitute/rawls/pulls/475","_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/rawls/pulls/comments/70687172"},"html":{"href":"https://github.com/broadinstitute/rawls/pull/475#discussion_r70687172"},"pull_request":{"href":"https://api.github.com/repos/broadinstitute/rawls/pulls/475"}}},"pull_request":{"url":"https://api.github.com/repos/broadinstitute/rawls/pulls/475","id":77105014,"html_url":"https://github.com/broadinstitute/rawls/pull/475","diff_url":"https://github.com/broadinstitute/rawls/pull/475.diff","patch_url":"https://github.com/broadinstitute/rawls/pull/475.patch","issue_url":"https://api.github.com/repos/broadinstitute/rawls/issues/475","number":475,"state":"open","locked":false,"title":"GAWB-779: shard cromwell","user":{"login":"davidangb","id":6041577,"avatar_url":"https://avatars.githubusercontent.com/u/6041577?v=3","gravatar_id":"","url":"https://api.github.com/users/davidangb","html_url":"https://github.com/davidangb","followers_url":"https://api.github.com/users/davidangb/followers","following_url":"https://api.github.com/users/davidangb/following{/other_user}","gists_url":"https://api.github.com/users/davidangb/gists{/gist_id}","starred_url":"https://api.github.com/users/davidangb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidangb/subscriptions","organizations_url":"https://api.github.com/users/davidangb/orgs","repos_url":"https://api.github.com/users/davidangb/repos","events_url":"https://api.github.com/users/davidangb/events{/privacy}","received_events_url":"https://api.github.com/users/davidangb/received_events","type":"User","site_admin":false},"body":"Previous commentary at #464; this is a new PR to ease discussion.\r\n\r\nThis PR shards batches of workflows across multiple cromwells. The high-level architecture is:\r\n* create an ExecutionServiceCluster that facades everything ExecutionServiceDAO used to do.\r\n* when submitting a batch of workflows, inspect the last few digits of the timestamp on the first workflow, and route to a cromwell instance based on those digits. The goal is to achieve a random distribution. Once submitted, persist the cromwell instance we used to the database.\r\n* when querying cromwell for status/details of a workflow, read the cromwell instance from the database and use that instance. For legacy workflows submitted prior to sharding, use the default cromwell instance as defined in config.\r\n\r\n\r\n- [x] **Submitter**: Rebase to develop. DO NOT SQUASH\r\n- [x] **Submitter**: Make sure Swagger is updated if API changes\r\n- [x] **Submitter**: Make sure documentation for code is complete\r\n- [x] **Submitter**: Make sure liquibase is updated if appropriate\r\n- [x] **Submitter**: Review code comments; remove done TODOs, create stories for remaining TODOs\r\n- [x] **Submitter**: Include the JIRA issue number in the PR description\r\n- [x] **Submitter**: Add description or comments on the PR explaining the hows/whys (if not obvious)\r\n- [x] **Submitter**: If PR includes new or changed db queries, include the explain plans in the description\r\n- [x] Tell ![](http://i.imgur.com/9dLzbPd.png) that the PR exists if he wants to look at it **(apply requires_doge label)**\r\n- [x] Anoint a lead reviewer (LR). **Assign PR to LR**\r\n- [x] **LR**: Initial review by LR and others.\r\n- [ ] Comment / review / update cycle:\r\n  * Rest of team may comments on PR at will\r\n  * **LR assigns to submitter** for feedback fixes\r\n  * Submitter updates documentation as needed\r\n  * Submitter rebases to develop again if necessary\r\n  * Submitter makes further commits. DO NOT SQUASH. **Reassign to LR** for further feedback\r\n- [ ] ![](http://i.imgur.com/9dLzbPd.png) sign off\r\n- [ ] **LR** sign off\r\n- [ ] **Assign to submitter** to finalize\r\n- [ ] **Submitter**: Squash commits, rebase if necessary\r\n- [ ] **Submitter**: Verify all tests go green, including CI tests\r\n- [ ] **Submitter**: Merge to develop \r\n- [ ] **Submitter**: Delete branch after merge\r\n- [ ] **Submitter**: Check configuration files in Jenkins in case they need changes\r\n- [ ] **Submitter**: **Test this change works on dev environment after deployment**. YOU own getting it fixed if dev isn't working for ANY reason!\r\n- [ ] **Submitter**: Verify swagger UI on dev environment still works after deployment\r\n- [ ] **Submitter**: Inform other teams of any API changes via hipchat and/or email\r\n- [ ] **Submitter**: Mark JIRA issue as resolved once this checklist is completed\r\n","created_at":"2016-07-12T11:40:21Z","updated_at":"2016-07-13T18:57:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e7ee42c189ea2aefa24f3bbe0e45c8937ee14bfb","assignee":{"login":"davidangb","id":6041577,"avatar_url":"https://avatars.githubusercontent.com/u/6041577?v=3","gravatar_id":"","url":"https://api.github.com/users/davidangb","html_url":"https://github.com/davidangb","followers_url":"https://api.github.com/users/davidangb/followers","following_url":"https://api.github.com/users/davidangb/following{/other_user}","gists_url":"https://api.github.com/users/davidangb/gists{/gist_id}","starred_url":"https://api.github.com/users/davidangb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidangb/subscriptions","organizations_url":"https://api.github.com/users/davidangb/orgs","repos_url":"https://api.github.com/users/davidangb/repos","events_url":"https://api.github.com/users/davidangb/events{/privacy}","received_events_url":"https://api.github.com/users/davidangb/received_events","type":"User","site_admin":false},"assignees":[{"login":"davidangb","id":6041577,"avatar_url":"https://avatars.githubusercontent.com/u/6041577?v=3","gravatar_id":"","url":"https://api.github.com/users/davidangb","html_url":"https://github.com/davidangb","followers_url":"https://api.github.com/users/davidangb/followers","following_url":"https://api.github.com/users/davidangb/following{/other_user}","gists_url":"https://api.github.com/users/davidangb/gists{/gist_id}","starred_url":"https://api.github.com/users/davidangb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidangb/subscriptions","organizations_url":"https://api.github.com/users/davidangb/orgs","repos_url":"https://api.github.com/users/davidangb/repos","events_url":"https://api.github.com/users/davidangb/events{/privacy}","received_events_url":"https://api.github.com/users/davidangb/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/broadinstitute/rawls/pulls/475/commits","review_comments_url":"https://api.github.com/repos/broadinstitute/rawls/pulls/475/comments","review_comment_url":"https://api.github.com/repos/broadinstitute/rawls/pulls/comments{/number}","comments_url":"https://api.github.com/repos/broadinstitute/rawls/issues/475/comments","statuses_url":"https://api.github.com/repos/broadinstitute/rawls/statuses/c0a41e16d324126c554b042a9603036894729b01","head":{"label":"broadinstitute:da_GAWB-779_shardCromwell","ref":"da_GAWB-779_shardCromwell","sha":"c0a41e16d324126c554b042a9603036894729b01","user":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"repo":{"id":34129770,"name":"rawls","full_name":"broadinstitute/rawls","owner":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/broadinstitute/rawls","description":"Rawls service for DSDE","fork":false,"url":"https://api.github.com/repos/broadinstitute/rawls","forks_url":"https://api.github.com/repos/broadinstitute/rawls/forks","keys_url":"https://api.github.com/repos/broadinstitute/rawls/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/rawls/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/rawls/teams","hooks_url":"https://api.github.com/repos/broadinstitute/rawls/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/rawls/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/rawls/events","assignees_url":"https://api.github.com/repos/broadinstitute/rawls/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/rawls/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/rawls/tags","blobs_url":"https://api.github.com/repos/broadinstitute/rawls/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/rawls/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/rawls/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/rawls/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/rawls/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/rawls/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/rawls/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/rawls/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/rawls/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/rawls/subscription","commits_url":"https://api.github.com/repos/broadinstitute/rawls/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/rawls/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/rawls/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/rawls/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/rawls/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/rawls/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/rawls/merges","archive_url":"https://api.github.com/repos/broadinstitute/rawls/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/rawls/downloads","issues_url":"https://api.github.com/repos/broadinstitute/rawls/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/rawls/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/rawls/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/rawls/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/rawls/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/rawls/releases{/id}","deployments_url":"https://api.github.com/repos/broadinstitute/rawls/deployments","created_at":"2015-04-17T17:16:07Z","updated_at":"2016-03-04T19:30:59Z","pushed_at":"2016-07-13T18:02:59Z","git_url":"git://github.com/broadinstitute/rawls.git","ssh_url":"git@github.com:broadinstitute/rawls.git","clone_url":"https://github.com/broadinstitute/rawls.git","svn_url":"https://github.com/broadinstitute/rawls","homepage":null,"size":4516,"stargazers_count":5,"watchers_count":5,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":3,"forks":1,"open_issues":3,"watchers":5,"default_branch":"develop"}},"base":{"label":"broadinstitute:develop","ref":"develop","sha":"a6240ee08f46a10d580a84e1c1d4542bb1f372b1","user":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"repo":{"id":34129770,"name":"rawls","full_name":"broadinstitute/rawls","owner":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/broadinstitute/rawls","description":"Rawls service for DSDE","fork":false,"url":"https://api.github.com/repos/broadinstitute/rawls","forks_url":"https://api.github.com/repos/broadinstitute/rawls/forks","keys_url":"https://api.github.com/repos/broadinstitute/rawls/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/rawls/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/rawls/teams","hooks_url":"https://api.github.com/repos/broadinstitute/rawls/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/rawls/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/rawls/events","assignees_url":"https://api.github.com/repos/broadinstitute/rawls/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/rawls/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/rawls/tags","blobs_url":"https://api.github.com/repos/broadinstitute/rawls/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/rawls/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/rawls/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/rawls/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/rawls/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/rawls/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/rawls/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/rawls/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/rawls/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/rawls/subscription","commits_url":"https://api.github.com/repos/broadinstitute/rawls/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/rawls/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/rawls/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/rawls/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/rawls/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/rawls/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/rawls/merges","archive_url":"https://api.github.com/repos/broadinstitute/rawls/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/rawls/downloads","issues_url":"https://api.github.com/repos/broadinstitute/rawls/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/rawls/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/rawls/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/rawls/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/rawls/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/rawls/releases{/id}","deployments_url":"https://api.github.com/repos/broadinstitute/rawls/deployments","created_at":"2015-04-17T17:16:07Z","updated_at":"2016-03-04T19:30:59Z","pushed_at":"2016-07-13T18:02:59Z","git_url":"git://github.com/broadinstitute/rawls.git","ssh_url":"git@github.com:broadinstitute/rawls.git","clone_url":"https://github.com/broadinstitute/rawls.git","svn_url":"https://github.com/broadinstitute/rawls","homepage":null,"size":4516,"stargazers_count":5,"watchers_count":5,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":3,"forks":1,"open_issues":3,"watchers":5,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/rawls/pulls/475"},"html":{"href":"https://github.com/broadinstitute/rawls/pull/475"},"issue":{"href":"https://api.github.com/repos/broadinstitute/rawls/issues/475"},"comments":{"href":"https://api.github.com/repos/broadinstitute/rawls/issues/475/comments"},"review_comments":{"href":"https://api.github.com/repos/broadinstitute/rawls/pulls/475/comments"},"review_comment":{"href":"https://api.github.com/repos/broadinstitute/rawls/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/broadinstitute/rawls/pulls/475/commits"},"statuses":{"href":"https://api.github.com/repos/broadinstitute/rawls/statuses/c0a41e16d324126c554b042a9603036894729b01"}}}}
{"actor":{"display_login":"davidangb"}}