{"action":"created","comment":{"url":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/comments/72507149","id":72507149,"diff_hunk":"@@ -0,0 +1,335 @@\n+---\n+layout: docs.hbs\n+title: Persistence Query\n+---\n+# Persistence Query\n+Akka persistence query complements Persistence by providing a universal asynchronous stream based query interface that various journal plugins can implement in order to expose their query capabilities.\n+\n+The most typical use case of persistence query is implementing the so-called query side (also known as \"read side\") in the popular CQRS architecture pattern - in which the writing side of the application (e.g. implemented using akka persistence) is completely separated from the \"query side\". Akka Persistence Query itself is not directly the query side of an application, however it can help to migrate data from the write side to the query side database. In very simple scenarios Persistence Query may be powerful enough to fulfill the query needs of your app, however we highly recommend (in the spirit of CQRS) of splitting up the write/read sides into separate datastores as the need arises.\n+\n+> **Warning** <br>\n+This module is marked as “experimental” as of its introduction in Akka.Net 1.1.0. We will continue to improve this API based on our users’ feedback, which implies that while we try to keep incompatible changes to a minimum the binary compatibility guarantee for maintenance releases does not apply to the contents of the akka.persistence.query package.\n+\n+## Design overview\n+Akka persistence query is purposely designed to be a very loosely specified API. This is in order to keep the provided APIs general enough for each journal implementation to be able to expose its best features, e.g. a SQL journal can use complex SQL queries or if a journal is able to subscribe to a live event stream this should also be possible to expose the same API - a typed stream of events.\n+\n+Each read journal must explicitly document which types of queries it supports. Refer to your journal's plugins documentation for details on which queries and semantics it supports.\n+\n+While Akka Persistence Query does not provide actual implementations of ReadJournals, it defines a number of pre-defined query types for the most common query scenarios, that most journals are likely to implement (however they are not required to).\n+\n+## Read Journals\n+In order to issue queries one has to first obtain an instance of a ReadJournal. Read journals are implemented as Community plugins, each targeting a specific datastore (for example Cassandra or ADO.NET databases). For example, given a library that provides a akka.persistence.query.my-read-journal obtaining the related journal is as simple as:\n+\n+```csharp\n+var actorSystem = ActorSystem.Create(\"query\");\n+\n+// obtain read journal by plugin id\n+var readJournal = PersistenceQuery.Get(actorSystem)\n+    .ReadJournalFor<SqlReadJournal>(\"akka.persistence.query.my-read-journal\");\n+\n+// issue query to journal\n+Source<EventEnvelope, NotUsed> source = readJournal\n+    .EventsByPersistenceId(\"user-1337\", 0, long.MaxValue);\n+\n+// materialize stream, consuming events\n+var mat = ActorMaterializer.Create(actorSystem);\n+source.RunForeach(envelope =>\n+{\n+    Console.WriteLine($\"event {envelope}\");\n+}, mat);\n+```\n+\n+Journal implementers are encouraged to put this identifier in a variable known to the user, such that one can access it via `ReadJournalFor<SqlReadJournal>(SqlReadJournal.Identifier)`, however this is not enforced.\n+\n+Read journal implementations are available as Community plugins.\n+\n+### Predefined queries\n+Akka persistence query comes with a number of query interfaces built in and suggests Journal implementors to implement them according to the semantics described below. It is important to notice that while these query types are very common a journal is not obliged to implement all of them - for example because in a given journal such query would be significantly inefficient.\n+\n+> **Note**<br>\n+Refer to the documentation of the ReadJournal plugin you are using for a specific list of supported query types. For example, Journal plugins should document their stream completion strategies.\n+\n+The predefined queries are:\n+\n+**AllPersistenceIdsQuery and CurrentPersistenceIdsQuery**\n+\n+`AllPersistenceIds` is used for retrieving all persistenceIds of all persistent actors.\n+\n+```csharp\n+var queries = PersistenceQuery.Get(actorSystem)\n+    .ReadJournalFor<SqlReadJournal>(\"akka.persistence.query.my-read-journal\");\n+\n+var mat = ActorMaterializer.Create(actorSystem);\n+Source<string, NotUsed> src = queries.AllPersistenceIds();\n+```\n+\n+The returned event stream is unordered and you can expect different order for multiple executions of the query.\n+\n+The stream is not completed when it reaches the end of the currently used `PersistenceIds`, but it continues to push new `PersistenceIds` when new persistent actors are created. Corresponding query that is completed when it reaches the end of the currently used `PersistenceIds` is provided by `CurrentPersistenceIds`.\n+\n+The write journal is notifying the query side as soon as new `PersistenceIds` are created and there is no periodic polling or batching involved in this query.\n+\n+The stream is completed with failure if there is a failure in executing the query in the backend journal.\n+\n+\n+**EventsByPersistenceIdQuery and CurrentEventsByPersistenceIdQuery**\n+\n+`EventsByPersistenceId` is used for retrieving events for a specific `PersistentActor` identified by `PersistenceId`.\n+\n+```csharp\n+var queries = PersistenceQuery.Get(actorSystem)\n+    .ReadJournalFor<SqlReadJournal>(\"akka.persistence.query.my-read-journal\");\n+\n+var mat = ActorMaterializer.Create(actorSystem);\n+var src = queries.EventsByPersistenceId(\"some-persistence-id\", 0L, long.MaxValue);\n+Source<object, NotUsed> events = src.Select(c => c.Event);\n+```\n+\n+You can retrieve a subset of all events by specifying `FromSequenceNr` and `ToSequenceNr` or use `0L` and `long.MaxValue` respectively to retrieve all events. Note that the corresponding sequence number of each event is provided in the `EventEnvelope`, which makes it possible to resume the stream at a later point from a given sequence number.\n+\n+The returned event stream is ordered by sequence number, i.e. the same order as the `PersistentActor` persisted the events. The same prefix of stream elements (in same order) are returned for multiple executions of the query, except for when events have been deleted.\n+\n+The stream is not completed when it reaches the end of the currently stored events, but it continues to push new events when new events are persisted. Corresponding query that is completed when it reaches the end of the currently stored events is provided by `CurrentEventsByPersistenceId`.\n+\n+The write journal is notifying the query side as soon as events are persisted, but for efficiency reasons the query side retrieves the events in batches that sometimes can be delayed up to the configured `refresh-interval` or given `RefreshInterval` hint.\n+\n+The stream is completed with failure if there is a failure in executing the query in the backend journal.\n+\n+**EventsByTag and CurrentEventsByTag**\n+\n+`EventsByTag` allows querying events regardless of which `PersistenceId` they are associated with. This query is hard to implement in some journals or may need some additional preparation of the used data store to be executed efficiently. The goal of this query is to allow querying for all events which are \"tagged\" with a specific tag. That includes the use case to query all domain events of an Aggregate Root type. Please refer to your read journal plugin's documentation to find out if and how it is supported.\n+\n+Some journals may support tagging of events via an Event Adapters that wraps the events in a `Akka.Persistence.Journal.Tagged` with the given tags. The journal may support other ways of doing tagging - again, how exactly this is implemented depends on the used journal. Here is an example of such a tagging event adapter:\n+\n+```csharp\n+public class MyTaggingEventAdapter : IWriteEventAdapter\n+{\n+    private ImmutableHashSet<string> colors = ImmutableHashSet.Create(\"green\", \"black\", \"blue\");\n+\n+    public string Manifest(object evt)\n+    {\n+        return string.Empty;\n+    }\n+\n+    public object ToJournal(object evt)\n+    {\n+        var str = evt as string;\n+        if (str != null)\n+        {\n+            var tags = colors.Aggregate(\n+                ImmutableHashSet<string>.Empty,\n+                (acc, c) => str.Equals(c) ? acc.Add(c): acc);\n+            if (tags.IsEmpty)\n+                return evt;\n+            else\n+                return new Tagged(evt, tags);\n+        }\n+        else\n+        {\n+            return evt;\n+        }\n+    }\n+}\n+```\n+\n+> **Note**<br>\n+A very important thing to keep in mind when using queries spanning multiple `PersistenceIds`, such as `EventsByTag` is that the order of events at which the events appear in the stream rarely is guaranteed (or stable between materializations).\n+\n+Journals may choose to opt for strict ordering of the events, and should then document explicitly what kind of ordering guarantee they provide - for example \"ordered by timestamp ascending, independently of `PersistenceId`\" is easy to achieve on relational databases, yet may be hard to implement efficiently on plain key-value datastores.\n+\n+In the example below we query all events which have been tagged (we assume this was performed by the write-side using an EventAdapter, or that the journal is smart enough that it can figure out what we mean by this tag - for example if the journal stored the events as json it may try to find those with the field tag set to this value etc.).\n+\n+```csharp\n+// assuming journal is able to work with numeric offsets we can:\n+Source<EventEnvelope, NotUsed> blueThings = readJournal.EventsByTag(\"blue\", 0L);\n+\n+// find top 10 blue things:\n+Task<ImmutableHashSet<object>> top10BlueThings = blueThings\n+    .Select(c => c.Event)\n+    .Take(10) // cancels the query stream after pulling 10 elements\n+    .RunAggregate(\n+        ImmutableHashSet<object>.Empty,\n+        (acc, c) => acc.Add(c),\n+        mat);\n+\n+// start another query, from the known offset\n+var furtherBlueThings = readJournal.EventsByTag(\"blue\", offset: 10);\n+```\n+\n+As you can see, we can use all the usual stream combinators available from Akka Streams on the resulting query stream, including for example taking the first 10 and cancelling the stream. It is worth pointing out that the built-in `EventsByTag` query has an optionally supported offset parameter (of type Long) which the journals can use to implement resumable-streams. For example a journal may be able to use a WHERE clause to begin the read starting from a specific row, or in a datastore that is able to order events by insertion time it could treat the Long as a timestamp and select only older events.\n+\n+If your usage does not require a live stream, you can use the `CurrentEventsByTag` query.\n+\n+### Materialized values of queries\n+Journals are able to provide additional information related to a query by exposing materialized values, which are a feature of Akka Streams that allows to expose additional values at stream materialization time.\n+\n+More advanced query journals may use this technique to expose information about the character of the materialized stream, for example if it's finite or infinite, strictly ordered or not ordered at all. The materialized value type is defined as the second type parameter of the returned `Source`, which allows journals to provide users with their specialised query object, as demonstrated in the sample below:\n+\n+```csharp\n+public class RichEvent\n+{\n+    public RichEvent(ISet<string> tags, object payload)\n+    {\n+        Tags = tags;\n+        Payload = payload;\n+    }\n+\n+    public ISet<string> Tags { get; }\n+    public object Payload { get; }\n+}\n+\n+public class QueryMetadata\n+{\n+    public QueryMetadata(bool deterministicOrder, bool infinite)\n+    {\n+        DeterministicOrder = deterministicOrder;\n+        Infinite = infinite;\n+    }\n+\n+    public bool DeterministicOrder { get; }\n+    public bool Infinite { get; }\n+}\n+```\n+\n+```scala\n+def byTagsWithMeta(tags: Set[String]): Source[RichEvent, QueryMetadata] = { }\n+```\n+\n+```scala\n+var query = readJournal.ByTagsWithMeta(ImmutableHashSet.Create(\"red\", \"blue\"));\n+query\n+    .MapMaterializedValue(meta =>\n+    {\n+        Console.WriteLine(\n+            $\"The query is: ordered deterministically: {meta.DeterministicOrder}, infinite: {meta.Infinite}\");\n+        return meta;\n+    })\n+    .Select(evt =>\n+    {\n+        Console.WriteLine($\"Event payload: {evt.Payload}\");\n+        return evt;\n+    })\n+    .RunWith(Sink.Ignore<RichEvent>(), mat);\n+```\n+\n+## Performance and denormalization\n+When building systems using Event sourcing and CQRS (Command & Query Responsibility Segregation) techniques it is tremendously important to realise that the write-side has completely different needs from the read-side, and separating those concerns into datastores that are optimised for either side makes it possible to offer the best experience for the write and read sides independently.\n+\n+For example, in a bidding system it is important to \"take the write\" and respond to the bidder that we have accepted the bid as soon as possible, which means that write-throughput is of highest importance for the write-side – often this means that data stores which are able to scale to accommodate these requirements have a less expressive query side.\n+\n+On the other hand the same application may have some complex statistics view or we may have analysts working with the data to figure out best bidding strategies and trends – this often requires some kind of expressive query capabilities like for example SQL or writing Spark jobs to analyse the data. Therefore the data stored in the write-side needs to be projected into the other read-optimised datastore.\n+\n+> **Note**<br>\n+When referring to Materialized Views in Akka Persistence think of it as \"some persistent storage of the result of a Query\". In other words, it means that the view is created once, in order to be afterwards queried multiple times, as in this format it may be more efficient or interesting to query it (instead of the source events directly).\n+\n+### Materialize view to Reactive Streams compatible datastore","path":"src/docs/persistence/persistence-query.md","position":225,"original_position":225,"commit_id":"38c035d79d919cf82ba3393dc9c732c4e22a3e3a","original_commit_id":"38c035d79d919cf82ba3393dc9c732c4e22a3e3a","user":{"login":"alexvaluyskiy","id":4232072,"avatar_url":"https://avatars.githubusercontent.com/u/4232072?v=3","gravatar_id":"","url":"https://api.github.com/users/alexvaluyskiy","html_url":"https://github.com/alexvaluyskiy","followers_url":"https://api.github.com/users/alexvaluyskiy/followers","following_url":"https://api.github.com/users/alexvaluyskiy/following{/other_user}","gists_url":"https://api.github.com/users/alexvaluyskiy/gists{/gist_id}","starred_url":"https://api.github.com/users/alexvaluyskiy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexvaluyskiy/subscriptions","organizations_url":"https://api.github.com/users/alexvaluyskiy/orgs","repos_url":"https://api.github.com/users/alexvaluyskiy/repos","events_url":"https://api.github.com/users/alexvaluyskiy/events{/privacy}","received_events_url":"https://api.github.com/users/alexvaluyskiy/received_events","type":"User","site_admin":false},"body":"I don't know how to translate this example.","created_at":"2016-07-27T19:32:11Z","updated_at":"2016-07-27T19:32:11Z","html_url":"https://github.com/akkadotnet/getakka.net/pull/189#discussion_r72507149","pull_request_url":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/189","_links":{"self":{"href":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/comments/72507149"},"html":{"href":"https://github.com/akkadotnet/getakka.net/pull/189#discussion_r72507149"},"pull_request":{"href":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/189"}}},"pull_request":{"url":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/189","id":79083510,"html_url":"https://github.com/akkadotnet/getakka.net/pull/189","diff_url":"https://github.com/akkadotnet/getakka.net/pull/189.diff","patch_url":"https://github.com/akkadotnet/getakka.net/pull/189.patch","issue_url":"https://api.github.com/repos/akkadotnet/getakka.net/issues/189","number":189,"state":"open","locked":false,"title":"Added Persistence-Query doc","user":{"login":"alexvaluyskiy","id":4232072,"avatar_url":"https://avatars.githubusercontent.com/u/4232072?v=3","gravatar_id":"","url":"https://api.github.com/users/alexvaluyskiy","html_url":"https://github.com/alexvaluyskiy","followers_url":"https://api.github.com/users/alexvaluyskiy/followers","following_url":"https://api.github.com/users/alexvaluyskiy/following{/other_user}","gists_url":"https://api.github.com/users/alexvaluyskiy/gists{/gist_id}","starred_url":"https://api.github.com/users/alexvaluyskiy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexvaluyskiy/subscriptions","organizations_url":"https://api.github.com/users/alexvaluyskiy/orgs","repos_url":"https://api.github.com/users/alexvaluyskiy/repos","events_url":"https://api.github.com/users/alexvaluyskiy/events{/privacy}","received_events_url":"https://api.github.com/users/alexvaluyskiy/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-07-27T19:31:44Z","updated_at":"2016-07-27T19:32:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"533d5c18c466f91a952150e63897bcf6f6de364a","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/189/commits","review_comments_url":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/189/comments","review_comment_url":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/comments{/number}","comments_url":"https://api.github.com/repos/akkadotnet/getakka.net/issues/189/comments","statuses_url":"https://api.github.com/repos/akkadotnet/getakka.net/statuses/38c035d79d919cf82ba3393dc9c732c4e22a3e3a","head":{"label":"alexvaluyskiy:persistencequery","ref":"persistencequery","sha":"38c035d79d919cf82ba3393dc9c732c4e22a3e3a","user":{"login":"alexvaluyskiy","id":4232072,"avatar_url":"https://avatars.githubusercontent.com/u/4232072?v=3","gravatar_id":"","url":"https://api.github.com/users/alexvaluyskiy","html_url":"https://github.com/alexvaluyskiy","followers_url":"https://api.github.com/users/alexvaluyskiy/followers","following_url":"https://api.github.com/users/alexvaluyskiy/following{/other_user}","gists_url":"https://api.github.com/users/alexvaluyskiy/gists{/gist_id}","starred_url":"https://api.github.com/users/alexvaluyskiy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexvaluyskiy/subscriptions","organizations_url":"https://api.github.com/users/alexvaluyskiy/orgs","repos_url":"https://api.github.com/users/alexvaluyskiy/repos","events_url":"https://api.github.com/users/alexvaluyskiy/events{/privacy}","received_events_url":"https://api.github.com/users/alexvaluyskiy/received_events","type":"User","site_admin":false},"repo":{"id":54824198,"name":"getakka.net","full_name":"alexvaluyskiy/getakka.net","owner":{"login":"alexvaluyskiy","id":4232072,"avatar_url":"https://avatars.githubusercontent.com/u/4232072?v=3","gravatar_id":"","url":"https://api.github.com/users/alexvaluyskiy","html_url":"https://github.com/alexvaluyskiy","followers_url":"https://api.github.com/users/alexvaluyskiy/followers","following_url":"https://api.github.com/users/alexvaluyskiy/following{/other_user}","gists_url":"https://api.github.com/users/alexvaluyskiy/gists{/gist_id}","starred_url":"https://api.github.com/users/alexvaluyskiy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexvaluyskiy/subscriptions","organizations_url":"https://api.github.com/users/alexvaluyskiy/orgs","repos_url":"https://api.github.com/users/alexvaluyskiy/repos","events_url":"https://api.github.com/users/alexvaluyskiy/events{/privacy}","received_events_url":"https://api.github.com/users/alexvaluyskiy/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/alexvaluyskiy/getakka.net","description":"Trying out Assemble.io for site generation","fork":true,"url":"https://api.github.com/repos/alexvaluyskiy/getakka.net","forks_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/forks","keys_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/teams","hooks_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/hooks","issue_events_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/issues/events{/number}","events_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/events","assignees_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/assignees{/user}","branches_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/branches{/branch}","tags_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/tags","blobs_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/git/refs{/sha}","trees_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/statuses/{sha}","languages_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/languages","stargazers_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/stargazers","contributors_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/contributors","subscribers_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/subscribers","subscription_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/subscription","commits_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/commits{/sha}","git_commits_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/git/commits{/sha}","comments_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/comments{/number}","issue_comment_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/issues/comments{/number}","contents_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/contents/{+path}","compare_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/merges","archive_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/downloads","issues_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/issues{/number}","pulls_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/pulls{/number}","milestones_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/milestones{/number}","notifications_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/labels{/name}","releases_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/releases{/id}","deployments_url":"https://api.github.com/repos/alexvaluyskiy/getakka.net/deployments","created_at":"2016-03-27T10:56:11Z","updated_at":"2016-03-27T10:56:13Z","pushed_at":"2016-07-26T16:00:08Z","git_url":"git://github.com/alexvaluyskiy/getakka.net.git","ssh_url":"git@github.com:alexvaluyskiy/getakka.net.git","clone_url":"https://github.com/alexvaluyskiy/getakka.net.git","svn_url":"https://github.com/alexvaluyskiy/getakka.net","homepage":null,"size":33760,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":false,"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":"akkadotnet:master","ref":"master","sha":"66c56cdca97835fd9c6cc94076300749c67753fc","user":{"login":"akkadotnet","id":7003835,"avatar_url":"https://avatars.githubusercontent.com/u/7003835?v=3","gravatar_id":"","url":"https://api.github.com/users/akkadotnet","html_url":"https://github.com/akkadotnet","followers_url":"https://api.github.com/users/akkadotnet/followers","following_url":"https://api.github.com/users/akkadotnet/following{/other_user}","gists_url":"https://api.github.com/users/akkadotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/akkadotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akkadotnet/subscriptions","organizations_url":"https://api.github.com/users/akkadotnet/orgs","repos_url":"https://api.github.com/users/akkadotnet/repos","events_url":"https://api.github.com/users/akkadotnet/events{/privacy}","received_events_url":"https://api.github.com/users/akkadotnet/received_events","type":"Organization","site_admin":false},"repo":{"id":30822032,"name":"getakka.net","full_name":"akkadotnet/getakka.net","owner":{"login":"akkadotnet","id":7003835,"avatar_url":"https://avatars.githubusercontent.com/u/7003835?v=3","gravatar_id":"","url":"https://api.github.com/users/akkadotnet","html_url":"https://github.com/akkadotnet","followers_url":"https://api.github.com/users/akkadotnet/followers","following_url":"https://api.github.com/users/akkadotnet/following{/other_user}","gists_url":"https://api.github.com/users/akkadotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/akkadotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akkadotnet/subscriptions","organizations_url":"https://api.github.com/users/akkadotnet/orgs","repos_url":"https://api.github.com/users/akkadotnet/repos","events_url":"https://api.github.com/users/akkadotnet/events{/privacy}","received_events_url":"https://api.github.com/users/akkadotnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/akkadotnet/getakka.net","description":"Trying out Assemble.io for site generation","fork":false,"url":"https://api.github.com/repos/akkadotnet/getakka.net","forks_url":"https://api.github.com/repos/akkadotnet/getakka.net/forks","keys_url":"https://api.github.com/repos/akkadotnet/getakka.net/keys{/key_id}","collaborators_url":"https://api.github.com/repos/akkadotnet/getakka.net/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/akkadotnet/getakka.net/teams","hooks_url":"https://api.github.com/repos/akkadotnet/getakka.net/hooks","issue_events_url":"https://api.github.com/repos/akkadotnet/getakka.net/issues/events{/number}","events_url":"https://api.github.com/repos/akkadotnet/getakka.net/events","assignees_url":"https://api.github.com/repos/akkadotnet/getakka.net/assignees{/user}","branches_url":"https://api.github.com/repos/akkadotnet/getakka.net/branches{/branch}","tags_url":"https://api.github.com/repos/akkadotnet/getakka.net/tags","blobs_url":"https://api.github.com/repos/akkadotnet/getakka.net/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/akkadotnet/getakka.net/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/akkadotnet/getakka.net/git/refs{/sha}","trees_url":"https://api.github.com/repos/akkadotnet/getakka.net/git/trees{/sha}","statuses_url":"https://api.github.com/repos/akkadotnet/getakka.net/statuses/{sha}","languages_url":"https://api.github.com/repos/akkadotnet/getakka.net/languages","stargazers_url":"https://api.github.com/repos/akkadotnet/getakka.net/stargazers","contributors_url":"https://api.github.com/repos/akkadotnet/getakka.net/contributors","subscribers_url":"https://api.github.com/repos/akkadotnet/getakka.net/subscribers","subscription_url":"https://api.github.com/repos/akkadotnet/getakka.net/subscription","commits_url":"https://api.github.com/repos/akkadotnet/getakka.net/commits{/sha}","git_commits_url":"https://api.github.com/repos/akkadotnet/getakka.net/git/commits{/sha}","comments_url":"https://api.github.com/repos/akkadotnet/getakka.net/comments{/number}","issue_comment_url":"https://api.github.com/repos/akkadotnet/getakka.net/issues/comments{/number}","contents_url":"https://api.github.com/repos/akkadotnet/getakka.net/contents/{+path}","compare_url":"https://api.github.com/repos/akkadotnet/getakka.net/compare/{base}...{head}","merges_url":"https://api.github.com/repos/akkadotnet/getakka.net/merges","archive_url":"https://api.github.com/repos/akkadotnet/getakka.net/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/akkadotnet/getakka.net/downloads","issues_url":"https://api.github.com/repos/akkadotnet/getakka.net/issues{/number}","pulls_url":"https://api.github.com/repos/akkadotnet/getakka.net/pulls{/number}","milestones_url":"https://api.github.com/repos/akkadotnet/getakka.net/milestones{/number}","notifications_url":"https://api.github.com/repos/akkadotnet/getakka.net/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/akkadotnet/getakka.net/labels{/name}","releases_url":"https://api.github.com/repos/akkadotnet/getakka.net/releases{/id}","deployments_url":"https://api.github.com/repos/akkadotnet/getakka.net/deployments","created_at":"2015-02-15T08:26:22Z","updated_at":"2016-07-27T11:53:01Z","pushed_at":"2016-07-27T19:31:44Z","git_url":"git://github.com/akkadotnet/getakka.net.git","ssh_url":"git@github.com:akkadotnet/getakka.net.git","clone_url":"https://github.com/akkadotnet/getakka.net.git","svn_url":"https://github.com/akkadotnet/getakka.net","homepage":null,"size":33716,"stargazers_count":10,"watchers_count":10,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":60,"mirror_url":null,"open_issues_count":28,"forks":60,"open_issues":28,"watchers":10,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/189"},"html":{"href":"https://github.com/akkadotnet/getakka.net/pull/189"},"issue":{"href":"https://api.github.com/repos/akkadotnet/getakka.net/issues/189"},"comments":{"href":"https://api.github.com/repos/akkadotnet/getakka.net/issues/189/comments"},"review_comments":{"href":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/189/comments"},"review_comment":{"href":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/akkadotnet/getakka.net/pulls/189/commits"},"statuses":{"href":"https://api.github.com/repos/akkadotnet/getakka.net/statuses/38c035d79d919cf82ba3393dc9c732c4e22a3e3a"}}}}
{"actor":{"display_login":"alexvaluyskiy"}}