{"action":"created","comment":{"url":"https://api.github.com/repos/akka/akka/pulls/comments/152749788","pull_request_review_id":78656950,"id":152749788,"diff_hunk":"@@ -3,70 +3,485 @@\n  */\n package akka.stream.scaladsl\n \n-import akka.stream.ActorMaterializer\n-import akka.stream.ActorMaterializerSettings\n-import akka.stream.Attributes\n+import java.util.Optional\n+import java.util.concurrent.{ CompletableFuture, CompletionStage, TimeUnit }\n+\n+import akka.{ Done, NotUsed }\n import akka.stream.Attributes._\n-import akka.stream.MaterializationContext\n-import akka.stream.SinkShape\n+import akka.stream._\n+import akka.stream.javadsl\n+import akka.stream.stage._\n import akka.stream.testkit._\n-import scala.concurrent.Future\n-import scala.concurrent.Promise\n-import akka.stream.impl.SinkModule\n-import akka.stream.impl.SinkholeSubscriber\n+import com.typesafe.config.ConfigFactory\n \n object AttributesSpec {\n \n-  object AttributesSink {\n-    def apply(): Sink[Nothing, Future[Attributes]] =\n-      Sink.fromGraph[Nothing, Future[Attributes]](new AttributesSink(Attributes.name(\"attributesSink\"), Sink.shape(\"attributesSink\")))\n+  class AttributesSource(_initialAttributes: Attributes = Attributes.none) extends GraphStageWithMaterializedValue[SourceShape[Any], Attributes] {\n+    val out = Outlet[Any](\"out\")\n+    override protected def initialAttributes: Attributes = _initialAttributes\n+    override val shape = SourceShape.of(out)\n+\n+    override def createLogicAndMaterializedValue(inheritedAttributes: Attributes): (GraphStageLogic, Attributes) = {\n+      val logic = new GraphStageLogic(shape) {\n+        setHandler(out, new OutHandler {\n+          def onPull(): Unit = {\n+          }\n+        })\n+      }\n+      (logic, inheritedAttributes)\n+    }\n+\n+  }\n+\n+  class AttributesFlow(_initialAttributes: Attributes = Attributes.none) extends GraphStageWithMaterializedValue[FlowShape[Any, Any], Attributes] {\n+\n+    val in = Inlet[Any](\"in\")\n+    val out = Outlet[Any](\"out\")\n+\n+    override protected def initialAttributes: Attributes = _initialAttributes\n+    override val shape = FlowShape(in, out)\n+    override def createLogicAndMaterializedValue(inheritedAttributes: Attributes): (GraphStageLogic, Attributes) = {\n+      val logic = new GraphStageLogic(shape) {\n+\n+        setHandlers(in, out, new InHandler with OutHandler {\n+          override def onPush(): Unit = push(out, grab(in))\n+          override def onPull(): Unit = pull(in)\n+        })\n+      }\n+\n+      (logic, inheritedAttributes)\n+    }\n   }\n \n-  final class AttributesSink(val attributes: Attributes, shape: SinkShape[Nothing]) extends SinkModule[Nothing, Future[Attributes]](shape) {\n-    override def create(context: MaterializationContext) =\n-      (new SinkholeSubscriber(Promise()), Future.successful(context.effectiveAttributes))\n+  class AttributesSink(_initialAttributes: Attributes = Attributes.none) extends GraphStageWithMaterializedValue[SinkShape[Any], Attributes] {\n+\n+    val in = Inlet[Any](\"in\")\n+\n+    override protected def initialAttributes: Attributes = _initialAttributes\n+    override val shape = SinkShape(in)\n+    override def createLogicAndMaterializedValue(inheritedAttributes: Attributes): (GraphStageLogic, Attributes) = {\n+      val logic = new GraphStageLogic(shape) {\n+        override def preStart(): Unit = {\n+          pull(in)\n+        }\n+        setHandler(in, new InHandler {\n+          override def onPush(): Unit = {\n+            grab(in)\n+            pull(in)\n+          }\n+        })\n+      }\n+\n+      (logic, inheritedAttributes)\n+    }\n+  }\n \n-    override protected def newInstance(shape: SinkShape[Nothing]): SinkModule[Nothing, Future[Attributes]] =\n-      new AttributesSink(attributes, shape)\n+  class ThreadNameSnitchingStage(initialDispatcher: String) extends GraphStage[SourceShape[String]] {\n+    val out = Outlet[String](\"out\")\n+    override val shape = SourceShape.of(out)\n+    override protected def initialAttributes: Attributes = ActorAttributes.dispatcher(initialDispatcher)\n+    def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {\n+      setHandler(out, new OutHandler {\n+        def onPull(): Unit = {\n+          push(out, Thread.currentThread.getName)\n+          completeStage()\n+        }\n+      })\n+    }\n \n-    override def withAttributes(attr: Attributes): SinkModule[Nothing, Future[Attributes]] =\n-      new AttributesSink(attr, amendShape(attr))\n   }\n \n+  def whateverAttribute(label: String): Attributes = Attributes(WhateverAttribute(label))\n+  case class WhateverAttribute(label: String) extends Attribute\n }\n \n-class AttributesSpec extends StreamSpec {\n+class AttributesSpec extends StreamSpec(ConfigFactory.parseString(\n+  \"\"\"\n+    my-dispatcher {\n+      type = Dispatcher\n+      executor = \"thread-pool-executor\"\n+      thread-pool-executor {\n+        fixed-pool-size = 1\n+      }\n+      throughput = 1\n+    }\n+  \"\"\").withFallback(Utils.UnboundedMailboxConfig)) {\n+\n   import AttributesSpec._\n \n   val settings = ActorMaterializerSettings(system)\n     .withInputBuffer(initialSize = 2, maxSize = 16)\n \n   implicit val materializer = ActorMaterializer(settings)\n \n-  \"attributes\" must {\n+  \"an attributes instance\" must {\n+\n+    val attributes = Attributes.name(\"a\") and Attributes.name(\"b\") and Attributes.inputBuffer(1, 2)\n+\n+    \"give access to the least specific attribute\" in {\n+      attributes.getFirst[Name] should ===(Some(Attributes.Name(\"a\")))\n+    }\n+\n+    \"give access to the most specific attribute value\" in {\n+      attributes.get[Name] should ===(Some(Attributes.Name(\"b\")))\n+    }\n+\n+  }\n+\n+  \"attributes on a graph stage\" must {\n+\n+    \"be appended with addAttributes\" in {\n+      val attributes =\n+        Source.fromGraph(new AttributesSource()\n+          .addAttributes(Attributes.name(\"new-name\"))\n+          .addAttributes(Attributes.name(\"re-added\")) // adding twice at same level replaces\n+          .addAttributes(whateverAttribute(\"other-thing\"))\n+        )\n+          .toMat(Sink.head)(Keep.left)\n+          .run()\n+\n+      attributes.get[Name] should contain(Name(\"re-added\"))\n+      attributes.get[WhateverAttribute] should contain(WhateverAttribute(\"other-thing\"))\n+    }\n+\n+    \"be replaced withAttributes directly on a stage\" in {\n+      val attributes =\n+        Source.fromGraph(new AttributesSource()\n+          .withAttributes(Attributes.name(\"new-name\") and whateverAttribute(\"other-thing\"))\n+          .withAttributes(Attributes.name(\"re-added\")) // we loose all previous attributes for same level\n+        )\n+          .toMat(Sink.head)(Keep.left)\n+          .run()\n+\n+      attributes.get[Name] should contain(Name(\"re-added\"))\n+      attributes.get[WhateverAttribute] shouldBe empty\n+    }\n \n     \"be overridable on a module basis\" in {\n-      val runnable = Source.empty.toMat(AttributesSink().withAttributes(Attributes.name(\"new-name\")))(Keep.right)\n-      whenReady(runnable.run()) { attributes ⇒\n-        attributes.get[Name] should contain(Name(\"new-name\"))\n-      }\n+      val attributes =\n+        Source.fromGraph(new AttributesSource().withAttributes(Attributes.name(\"new-name\")))\n+          .toMat(Sink.head)(Keep.left)\n+          .run()\n+\n+      attributes.get[Name] should contain(Name(\"new-name\"))\n     }\n \n     \"keep the outermost attribute as the least specific\" in {\n-      val runnable = Source.empty.toMat(AttributesSink())(Keep.right).withAttributes(Attributes.name(\"new-name\"))\n-      whenReady(runnable.run()) { attributes ⇒\n-        attributes.get[Name] should contain(Name(\"attributesSink\"))\n-      }\n+      val attributes = Source.fromGraph(new AttributesSource(Attributes.name(\"original-name\")))\n+        .map(identity)\n+        .addAttributes(Attributes.name(\"whole-graph\"))\n+        .toMat(Sink.head)(Keep.left)\n+        .run()\n+\n+      // most specific\n+      attributes.get[Name] should contain(Name(\"original-name\"))\n+\n+      // least specific\n+      attributes.getFirst[Name] should contain(Name(\"whole-graph\"))\n     }\n+  }\n \n-    val attributes = Attributes.name(\"a\") and Attributes.name(\"b\") and Attributes.inputBuffer(1, 2)\n+  \"attributes on a source\" must {\n \n-    \"give access to first attribute\" in {\n-      attributes.getFirst[Name] should ===(Some(Attributes.Name(\"a\")))\n+    \"make the attributes on fromGraph(single-source-stage) Source behave the same as the stage itself\" in {\n+      val attributes =\n+        Source.fromGraph(\n+          new AttributesSource(Attributes.name(\"original-name\") and whateverAttribute(\"whatever\"))\n+            .withAttributes(Attributes.name(\"new-name\")))\n+          .toMat(Sink.head)(Keep.left)\n+          .run()\n+\n+      // most specific\n+      attributes.get[Name] should contain(Name(\"new-name\"))\n+\n+      // least specific\n+      attributes.getFirst[Name] should contain(Name(\"new-name\"))\n     }\n \n-    \"give access to attribute byt type\" in {\n-      attributes.get[Name] should ===(Some(Attributes.Name(\"b\")))\n+    \"make the attributes on Source.fromGraph source behave the same as the stage itself\" in {\n+      val attributes =\n+        Source.fromGraph(new AttributesSource(Attributes.name(\"original-name\")))\n+          .withAttributes(Attributes.name(\"replaced\")) // this actually replaces now\n+          .toMat(Sink.head)(Keep.left).withAttributes(Attributes.name(\"whole-graph\"))\n+          .run()\n+\n+      // most specific\n+      attributes.get[Name] should contain(Name(\"replaced\"))\n+      attributes.get[WhateverAttribute] shouldBe empty\n+\n+      // least specific\n+      attributes.getFirst[Name] should contain(Name(\"whole-graph\"))\n+      attributes.getFirst[WhateverAttribute] shouldBe empty\n+    }\n+\n+    \"not replace stage specific attributes with attributes on surrounding composite source\" in {\n+      val attributes = Source.fromGraph(new AttributesSource(Attributes.name(\"original-name\")))\n+        .map(identity)\n+        .addAttributes(Attributes.name(\"composite-graph\"))\n+        .toMat(Sink.head)(Keep.left)\n+        .run()\n+\n+      // most specific still the original as the attribute was added on the composite source\n+      attributes.get[Name] should contain(Name(\"original-name\"))\n+\n+      // least specific\n+      attributes.getFirst[Name] should contain(Name(\"composite-graph\"))\n+    }\n+\n+    \"make the attributes on Sink.fromGraph source behave the same as the stage itself\" in {\n+      val attributes =\n+        Source.maybe.toMat(\n+          Sink.fromGraph(new AttributesSink(Attributes.name(\"original-name\")))\n+            .withAttributes(Attributes.name(\"replaced\")) // this actually replaces now\n+        )(Keep.right)\n+          .withAttributes(Attributes.name(\"whole-graph\"))\n+          .run()\n+\n+      // most specific\n+      attributes.get[Name] should contain(Name(\"replaced\"))\n+\n+      // least specific\n+      attributes.getFirst[Name] should contain(Name(\"whole-graph\"))\n+    }\n+\n+    \"use the initial attributes for dispatcher\" in {\n+      val dispatcher =\n+        Source.fromGraph(new ThreadNameSnitchingStage(\"my-dispatcher\"))\n+          .runWith(Sink.head)\n+          .futureValue\n+\n+      dispatcher should startWith(\"AttributesSpec-my-dispatcher\")\n+    }\n+\n+    \"use an explicit attribute on the stage to select dispatcher\" in {\n+      val dispatcher =\n+        Source.fromGraph(\n+          // directly on stage\n+          new ThreadNameSnitchingStage(\"akka.stream.default-blocking-io-dispatcher\")\n+            .addAttributes(ActorAttributes.dispatcher(\"my-dispatcher\")))\n+          .runWith(Sink.head)\n+          .futureValue\n+\n+      dispatcher should startWith(\"AttributesSpec-my-dispatcher\")\n+    }\n+\n+    \"use the most specific dispatcher when another one is defined on a surrounding composed graph\" in {\n+      val dispatcher =\n+        Source.fromGraph(\n+          new ThreadNameSnitchingStage(\"akka.stream.default-blocking-io-dispatcher\"))\n+          .map(identity)\n+          // this is now for the composed source -> flow graph\n+          .addAttributes(ActorAttributes.dispatcher(\"my-dispatcher\"))\n+          .runWith(Sink.head)\n+          .futureValue\n+\n+      dispatcher should startWith(\"AttributesSpec-akka.stream.default-blocking-io-dispatcher\")\n+    }\n+\n+    \"not change dispatcher from one defined on a surrounding graph\" in {\n+      val dispatcher =\n+        Source.fromGraph(\n+          new ThreadNameSnitchingStage(\"akka.stream.default-blocking-io-dispatcher\"))\n+          // this already introduces an async boundary here\n+          .map(identity)\n+          // this is now just for map since there already is one inbetween stage and map\n+          .async // potential sugar .async(\"my-dispatcher\")\n+          .addAttributes(ActorAttributes.dispatcher(\"my-dispatcher\"))\n+          .runWith(Sink.head)\n+          .futureValue\n+\n+      dispatcher should startWith(\"AttributesSpec-akka.stream.default-blocking-io-dispatcher\")","path":"akka-stream-tests/src/test/scala/akka/stream/scaladsl/AttributesSpec.scala","position":310,"original_position":325,"commit_id":"3ecff8fac23d0ee85e6060f6df0d26c17e248922","original_commit_id":"3ecff8fac23d0ee85e6060f6df0d26c17e248922","user":{"login":"2m","id":422086,"avatar_url":"https://avatars3.githubusercontent.com/u/422086?v=4","gravatar_id":"","url":"https://api.github.com/users/2m","html_url":"https://github.com/2m","followers_url":"https://api.github.com/users/2m/followers","following_url":"https://api.github.com/users/2m/following{/other_user}","gists_url":"https://api.github.com/users/2m/gists{/gist_id}","starred_url":"https://api.github.com/users/2m/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/2m/subscriptions","organizations_url":"https://api.github.com/users/2m/orgs","repos_url":"https://api.github.com/users/2m/repos","events_url":"https://api.github.com/users/2m/events{/privacy}","received_events_url":"https://api.github.com/users/2m/received_events","type":"User","site_admin":false},"body":"As mentioned before, this behaviour is a bit surprising because of the attributes being set on the composite and then not beeing applied to the stage. Here it is possible to follow the code and deduce the outcome. But if a composite comes from a library, then the effect of setting a dispatcher attribute is unknown.","created_at":"2017-11-23T09:16:30Z","updated_at":"2017-11-23T09:16:30Z","html_url":"https://github.com/akka/akka/pull/24000#discussion_r152749788","pull_request_url":"https://api.github.com/repos/akka/akka/pulls/24000","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/akka/akka/pulls/comments/152749788"},"html":{"href":"https://github.com/akka/akka/pull/24000#discussion_r152749788"},"pull_request":{"href":"https://api.github.com/repos/akka/akka/pulls/24000"}}},"pull_request":{"url":"https://api.github.com/repos/akka/akka/pulls/24000","id":152776351,"html_url":"https://github.com/akka/akka/pull/24000","diff_url":"https://github.com/akka/akka/pull/24000.diff","patch_url":"https://github.com/akka/akka/pull/24000.patch","issue_url":"https://api.github.com/repos/akka/akka/issues/24000","number":24000,"state":"open","locked":false,"title":"Attributes on fromGraph(stage) should be treated as on stage","user":{"login":"johanandren","id":666915,"avatar_url":"https://avatars3.githubusercontent.com/u/666915?v=4","gravatar_id":"","url":"https://api.github.com/users/johanandren","html_url":"https://github.com/johanandren","followers_url":"https://api.github.com/users/johanandren/followers","following_url":"https://api.github.com/users/johanandren/following{/other_user}","gists_url":"https://api.github.com/users/johanandren/gists{/gist_id}","starred_url":"https://api.github.com/users/johanandren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/johanandren/subscriptions","organizations_url":"https://api.github.com/users/johanandren/orgs","repos_url":"https://api.github.com/users/johanandren/repos","events_url":"https://api.github.com/users/johanandren/events{/privacy}","received_events_url":"https://api.github.com/users/johanandren/received_events","type":"User","site_admin":false},"body":"","created_at":"2017-11-15T13:38:26Z","updated_at":"2017-11-23T09:16:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4472ce06409717edd45cb3fad47e8fa9bcc6e14c","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/akka/akka/pulls/24000/commits","review_comments_url":"https://api.github.com/repos/akka/akka/pulls/24000/comments","review_comment_url":"https://api.github.com/repos/akka/akka/pulls/comments{/number}","comments_url":"https://api.github.com/repos/akka/akka/issues/24000/comments","statuses_url":"https://api.github.com/repos/akka/akka/statuses/3ecff8fac23d0ee85e6060f6df0d26c17e248922","head":{"label":"johanandren:wip-prototyping-attributes-1-johanandren","ref":"wip-prototyping-attributes-1-johanandren","sha":"3ecff8fac23d0ee85e6060f6df0d26c17e248922","user":{"login":"johanandren","id":666915,"avatar_url":"https://avatars3.githubusercontent.com/u/666915?v=4","gravatar_id":"","url":"https://api.github.com/users/johanandren","html_url":"https://github.com/johanandren","followers_url":"https://api.github.com/users/johanandren/followers","following_url":"https://api.github.com/users/johanandren/following{/other_user}","gists_url":"https://api.github.com/users/johanandren/gists{/gist_id}","starred_url":"https://api.github.com/users/johanandren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/johanandren/subscriptions","organizations_url":"https://api.github.com/users/johanandren/orgs","repos_url":"https://api.github.com/users/johanandren/repos","events_url":"https://api.github.com/users/johanandren/events{/privacy}","received_events_url":"https://api.github.com/users/johanandren/received_events","type":"User","site_admin":false},"repo":{"id":41662207,"name":"akka","full_name":"johanandren/akka","owner":{"login":"johanandren","id":666915,"avatar_url":"https://avatars3.githubusercontent.com/u/666915?v=4","gravatar_id":"","url":"https://api.github.com/users/johanandren","html_url":"https://github.com/johanandren","followers_url":"https://api.github.com/users/johanandren/followers","following_url":"https://api.github.com/users/johanandren/following{/other_user}","gists_url":"https://api.github.com/users/johanandren/gists{/gist_id}","starred_url":"https://api.github.com/users/johanandren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/johanandren/subscriptions","organizations_url":"https://api.github.com/users/johanandren/orgs","repos_url":"https://api.github.com/users/johanandren/repos","events_url":"https://api.github.com/users/johanandren/events{/privacy}","received_events_url":"https://api.github.com/users/johanandren/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/johanandren/akka","description":"Akka Project","fork":true,"url":"https://api.github.com/repos/johanandren/akka","forks_url":"https://api.github.com/repos/johanandren/akka/forks","keys_url":"https://api.github.com/repos/johanandren/akka/keys{/key_id}","collaborators_url":"https://api.github.com/repos/johanandren/akka/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/johanandren/akka/teams","hooks_url":"https://api.github.com/repos/johanandren/akka/hooks","issue_events_url":"https://api.github.com/repos/johanandren/akka/issues/events{/number}","events_url":"https://api.github.com/repos/johanandren/akka/events","assignees_url":"https://api.github.com/repos/johanandren/akka/assignees{/user}","branches_url":"https://api.github.com/repos/johanandren/akka/branches{/branch}","tags_url":"https://api.github.com/repos/johanandren/akka/tags","blobs_url":"https://api.github.com/repos/johanandren/akka/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/johanandren/akka/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/johanandren/akka/git/refs{/sha}","trees_url":"https://api.github.com/repos/johanandren/akka/git/trees{/sha}","statuses_url":"https://api.github.com/repos/johanandren/akka/statuses/{sha}","languages_url":"https://api.github.com/repos/johanandren/akka/languages","stargazers_url":"https://api.github.com/repos/johanandren/akka/stargazers","contributors_url":"https://api.github.com/repos/johanandren/akka/contributors","subscribers_url":"https://api.github.com/repos/johanandren/akka/subscribers","subscription_url":"https://api.github.com/repos/johanandren/akka/subscription","commits_url":"https://api.github.com/repos/johanandren/akka/commits{/sha}","git_commits_url":"https://api.github.com/repos/johanandren/akka/git/commits{/sha}","comments_url":"https://api.github.com/repos/johanandren/akka/comments{/number}","issue_comment_url":"https://api.github.com/repos/johanandren/akka/issues/comments{/number}","contents_url":"https://api.github.com/repos/johanandren/akka/contents/{+path}","compare_url":"https://api.github.com/repos/johanandren/akka/compare/{base}...{head}","merges_url":"https://api.github.com/repos/johanandren/akka/merges","archive_url":"https://api.github.com/repos/johanandren/akka/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/johanandren/akka/downloads","issues_url":"https://api.github.com/repos/johanandren/akka/issues{/number}","pulls_url":"https://api.github.com/repos/johanandren/akka/pulls{/number}","milestones_url":"https://api.github.com/repos/johanandren/akka/milestones{/number}","notifications_url":"https://api.github.com/repos/johanandren/akka/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/johanandren/akka/labels{/name}","releases_url":"https://api.github.com/repos/johanandren/akka/releases{/id}","deployments_url":"https://api.github.com/repos/johanandren/akka/deployments","created_at":"2015-08-31T07:37:07Z","updated_at":"2016-02-02T08:15:23Z","pushed_at":"2017-11-22T14:20:21Z","git_url":"git://github.com/johanandren/akka.git","ssh_url":"git@github.com:johanandren/akka.git","clone_url":"https://github.com/johanandren/akka.git","svn_url":"https://github.com/johanandren/akka","homepage":"http://akka.io","size":205217,"stargazers_count":0,"watchers_count":0,"language":"Scala","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"akka:master","ref":"master","sha":"3e74ca739ef3226fd8bf7846083870a7459ac256","user":{"login":"akka","id":1496237,"avatar_url":"https://avatars2.githubusercontent.com/u/1496237?v=4","gravatar_id":"","url":"https://api.github.com/users/akka","html_url":"https://github.com/akka","followers_url":"https://api.github.com/users/akka/followers","following_url":"https://api.github.com/users/akka/following{/other_user}","gists_url":"https://api.github.com/users/akka/gists{/gist_id}","starred_url":"https://api.github.com/users/akka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akka/subscriptions","organizations_url":"https://api.github.com/users/akka/orgs","repos_url":"https://api.github.com/users/akka/repos","events_url":"https://api.github.com/users/akka/events{/privacy}","received_events_url":"https://api.github.com/users/akka/received_events","type":"Organization","site_admin":false},"repo":{"id":130013,"name":"akka","full_name":"akka/akka","owner":{"login":"akka","id":1496237,"avatar_url":"https://avatars2.githubusercontent.com/u/1496237?v=4","gravatar_id":"","url":"https://api.github.com/users/akka","html_url":"https://github.com/akka","followers_url":"https://api.github.com/users/akka/followers","following_url":"https://api.github.com/users/akka/following{/other_user}","gists_url":"https://api.github.com/users/akka/gists{/gist_id}","starred_url":"https://api.github.com/users/akka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akka/subscriptions","organizations_url":"https://api.github.com/users/akka/orgs","repos_url":"https://api.github.com/users/akka/repos","events_url":"https://api.github.com/users/akka/events{/privacy}","received_events_url":"https://api.github.com/users/akka/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/akka/akka","description":"Build highly concurrent, distributed, and resilient message-driven applications on the JVM","fork":false,"url":"https://api.github.com/repos/akka/akka","forks_url":"https://api.github.com/repos/akka/akka/forks","keys_url":"https://api.github.com/repos/akka/akka/keys{/key_id}","collaborators_url":"https://api.github.com/repos/akka/akka/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/akka/akka/teams","hooks_url":"https://api.github.com/repos/akka/akka/hooks","issue_events_url":"https://api.github.com/repos/akka/akka/issues/events{/number}","events_url":"https://api.github.com/repos/akka/akka/events","assignees_url":"https://api.github.com/repos/akka/akka/assignees{/user}","branches_url":"https://api.github.com/repos/akka/akka/branches{/branch}","tags_url":"https://api.github.com/repos/akka/akka/tags","blobs_url":"https://api.github.com/repos/akka/akka/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/akka/akka/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/akka/akka/git/refs{/sha}","trees_url":"https://api.github.com/repos/akka/akka/git/trees{/sha}","statuses_url":"https://api.github.com/repos/akka/akka/statuses/{sha}","languages_url":"https://api.github.com/repos/akka/akka/languages","stargazers_url":"https://api.github.com/repos/akka/akka/stargazers","contributors_url":"https://api.github.com/repos/akka/akka/contributors","subscribers_url":"https://api.github.com/repos/akka/akka/subscribers","subscription_url":"https://api.github.com/repos/akka/akka/subscription","commits_url":"https://api.github.com/repos/akka/akka/commits{/sha}","git_commits_url":"https://api.github.com/repos/akka/akka/git/commits{/sha}","comments_url":"https://api.github.com/repos/akka/akka/comments{/number}","issue_comment_url":"https://api.github.com/repos/akka/akka/issues/comments{/number}","contents_url":"https://api.github.com/repos/akka/akka/contents/{+path}","compare_url":"https://api.github.com/repos/akka/akka/compare/{base}...{head}","merges_url":"https://api.github.com/repos/akka/akka/merges","archive_url":"https://api.github.com/repos/akka/akka/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/akka/akka/downloads","issues_url":"https://api.github.com/repos/akka/akka/issues{/number}","pulls_url":"https://api.github.com/repos/akka/akka/pulls{/number}","milestones_url":"https://api.github.com/repos/akka/akka/milestones{/number}","notifications_url":"https://api.github.com/repos/akka/akka/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/akka/akka/labels{/name}","releases_url":"https://api.github.com/repos/akka/akka/releases{/id}","deployments_url":"https://api.github.com/repos/akka/akka/deployments","created_at":"2009-02-16T12:51:54Z","updated_at":"2017-11-23T08:17:35Z","pushed_at":"2017-11-23T08:05:59Z","git_url":"git://github.com/akka/akka.git","ssh_url":"git@github.com:akka/akka.git","clone_url":"https://github.com/akka/akka.git","svn_url":"https://github.com/akka/akka","homepage":"http://akka.io","size":204452,"stargazers_count":7875,"watchers_count":7875,"language":"Scala","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2502,"mirror_url":null,"archived":false,"open_issues_count":620,"forks":2502,"open_issues":620,"watchers":7875,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/akka/akka/pulls/24000"},"html":{"href":"https://github.com/akka/akka/pull/24000"},"issue":{"href":"https://api.github.com/repos/akka/akka/issues/24000"},"comments":{"href":"https://api.github.com/repos/akka/akka/issues/24000/comments"},"review_comments":{"href":"https://api.github.com/repos/akka/akka/pulls/24000/comments"},"review_comment":{"href":"https://api.github.com/repos/akka/akka/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/akka/akka/pulls/24000/commits"},"statuses":{"href":"https://api.github.com/repos/akka/akka/statuses/3ecff8fac23d0ee85e6060f6df0d26c17e248922"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"2m"}}