Permalink
Browse files

Documented protocol, and removed it from the roadmap.

  • Loading branch information...
michaellperry committed May 3, 2016
1 parent 0b26fd4 commit 3b9880100642c9dd415fd1954c0db54f2492e680
Showing with 151 additions and 90 deletions.
  1. +2 −2 node/package.json
  2. +144 −0 protocol.md
  3. +3 −86 roadmap.md
  4. +2 −2 web/bower.json
View
@@ -1,7 +1,7 @@
{
"name": "jinaga",
- "version": "1.4.0",
- "description": "JSON Messaging Platform",
+ "version": "1.5.0",
+ "description": "Universal Web Backend",
"main": "jinaga.js",
"repository": {
"type": "git",
View
@@ -0,0 +1,144 @@
+The Jinaga wire protocol is designed for resilience and performance. Built on top of WebSockets, the protocol is represented as the exchange of JSON documents. Each side sends a document when they have something to say; there is no request/response cadence.
+
+## Fact
+
+A `fact` message sends a fact from one peer to the other. Facts have ids, which are unique only within the scope of the current session. They also carry a token, which is assumed (but not required) to be the hash of the fact. The token is used with the `received` fact, and is only generated by a client.
+
+```JavaScript
+{
+ type: "fact",
+ id: 1,
+ fact: {
+ type: "Jinaga.User",
+ publicKey: "----BEGIN PUBLIC KEY---XXXXX"
+ },
+ token: -1902729049
+}
+```
+
+These IDs can be used as references in later `fact` messages. A fact reference also includes the hash of the fact, making lookup on the opposite side faster.
+
+```JavaScript
+{
+ type: "fact",
+ id: 3,
+ fact: {
+ type: "List",
+ name: "Chores",
+ from: {
+ id: 1,
+ hash: -1902729049
+ }
+ },
+ token: 430392748
+}
+```
+
+During a given session, the use of references reduces redundancy, and improves the performance of the overall communication.
+
+```JavaScript
+{
+ type: "fact",
+ id: 5,
+ fact: {
+ type: "Task",
+ list: {
+ id: 3,
+ hash: 430392748
+ },
+ description: "Take out the trash"
+ },
+ token: -2014427633
+}
+
+{
+ type: "fact",
+ id: 7,
+ fact: {
+ type: "Task",
+ list: {
+ id: 3,
+ hash: 430392748
+ },
+ description: "Deposit all the cash"
+ },
+ token: -2014427655
+}
+```
+
+Between a given communicating pair of nodes, the ID is determined by the node that generates the fact. The ID has no meaning outside of the communication channel. The same fact may have different IDs between different pairs, or even between the same pair during different sessions.
+
+The ID space within the channel is bifurcated so that the two nodes cannot generate the same ID. Clients generate odd numbered IDs, while servers generate even numbers. If the two nodes are peers, the client is the one that initiated the communication. If a race condition occurs in which both nodes in the pair generate the same fact, then either ID may be used by either party for the remainder of the session to refer to the same fact.
+
+## Received
+
+When a server receives a `fact` message, it responds with a `received` message. This echoes back the token.
+
+```JavaScript
+{
+ type: "received",
+ token: -1902729049
+}
+```
+
+The client uses this message to remove the fact from its retry queue. If the connection is broken and then reestablished, this message does not need to be re-sent.
+
+## Logged In
+
+The server sends a `loggedIn` message when the user has been authenticated. This occurs when the connection is established and a bearer token is included in the `Authorized` header. The token is validated, and the fact containing the user's public key is returned. The user's current profile -- according to the authentication provider -- is also returned.
+
+```JavaScript
+{
+ type: "loggedIn",
+ userFact: {
+ type: "Jinaga.User",
+ publicKey: "----BEGIN PUBLIC KEY---XXXXX"
+ },
+ profile: {
+ displayName: "Cliff Stoll"
+ }
+}
+```
+
+## Watch
+
+The client sends a `watch` message to begin watching for facts satisfying a specified query.
+
+```JavaScript
+{
+ type: "watch",
+ start: {
+ type: "List",
+ name: "Chores",
+ from: {
+ type: "Jinaga.User",
+ publicKey: "----BEGIN PUBLIC KEY---XXXXX"
+ }
+ },
+ query: 'S.list F.type="Task"'
+}
+```
+
+The query is expressed as a descriptive string. Each segment is a
+
+* **P** Predecessor
+* **S** Successor
+* **F** Field
+* **E** Exists condition (nested query in parentheses)
+* **N** Not exists condition (nested query in parentheses)
+
+The server sends facts matching the query immediately. It continues to send facts as they arrive.
+
+## Stop
+
+The client sends a `stop` message to tell the server to stop sending facts matching the specified query. The message contains the same fields as the `watch` message.
+
+## Query
+
+The client sends a `query` message to request facts satisfying a specified query. The server responds with the facts that it currently knows about, and then terminates with a `done` message. It does not continue sending facts as it receives them.
+
+The `query` message is similar to a `watch`, with the addition of a `token`. The token may be any value that the client chooses.
+
+## Done
+
+The server responds to a `query` message with some number of facts followed by `done`. The `done` message carries the token specified in the `query`.
View
@@ -4,92 +4,9 @@ These are the large steps toward the vision of Historical Modeling in JavaScript
## Performance
-The focus of the next few steps is performance. The system is currently functional and resilient, but is not scalable or efficient.
-
-When sending a fact between client and server, it is expressed as raw JSON and includes the full predecessor history.
-
-```JavaScript
-{
- type: "Task",
- list: {
- type: "List",
- name: "Chores",
- from: {
- type: "Jinaga.User",
- publicKey: "----BEGIN PUBLIC KEY---XXXXX"
- }
- },
- description: "Take out the trash"
-}
-```
-
-A related fact will repeat all of the same predecessors.
-
-```JavaScript
-{
- type: "Task",
- list: {
- type: "List",
- name: "Chores",
- from: {
- type: "Jinaga.User",
- publicKey: "----BEGIN PUBLIC KEY---XXXXX"
- }
- },
- description: "Deposit all the cash"
-}
-```
-
-This is low-hanging fruit for the elimination of redundancy. Instead, facts should be transmitted as references:
-
-```JavaScript
-{
- id: "xyz001",
- fact: {
- type: "Jinaga.User",
- publicKey: "----BEGIN PUBLIC KEY---XXXXX"
- }
-}
-
-{
- id: "xyz0002",
- fact: {
- type: "List",
- name: "Chores",
- from: {
- id: "xyz001"
- }
- }
-}
-
-{
- id: "xyz003",
- fact: {
- type: "Task",
- list: {
- id: "xyz002"
- },
- description: "Take out the trash"
- }
-}
-
-{
- id: "xyz004",
- fact: {
- type: "Task",
- list: {
- id: "xyz002"
- },
- description: "Deposit all the cash"
- }
-}
-```
-
-Between a given communicating pair of nodes, the id is determined by the node that generates the fact. The id has no meaning outside of the communication channel. The same fact may have different ids between different pairs.
-
-The id space within the channel is bifurcated so that the two nodes cannot generate the same id. One simple way to accomplish this is to allow the first character or bit to indicate whether the id was generated by the client or the server within this pair. If the two nodes are peers, the client is the one that initiated the communication. If a race condition occurs in which both nodes in the pair generate the same fact, then either id may be used for the remainder of the conversation to refer to the same fact.
-
-Fact references open another optimization opportunity related to resuming a conversation. Currently, when a socket is lost, the client will initiate a new connection. The server has no information about the facts that the client has already received, and so it will restart the stream from the beginning of history. Once fact references are available, a client will be able to inform the server of the last fact that it received. Fact references should be monotonically increasing to help the server resume the stream.
+The focus of the next step is performance. Performance has improved greatly, but there is one significant step left to do.
+
+Currently, when a socket is lost, the client will initiate a new connection. The server has no information about the facts that the client has already received, and so it will restart the stream from the beginning of history. Once fact references are available, a client will be able to inform the server of the last fact that it received. Fact references should be monotonically increasing to help the server resume the stream.
## Security
View
@@ -1,11 +1,11 @@
{
"name": "jinaga",
- "version": "1.4.0",
+ "version": "1.5.0",
"homepage": "https://github.com/michaellperry/jinaga",
"authors": [
"Michael L Perry <michael@qedcode.com>"
],
- "description": "Real-time client-to-server-to-client messaging with persistence",
+ "description": "Universal Web Backend",
"main": "jinaga.js",
"moduleType": [
"amd"

0 comments on commit 3b98801

Please sign in to comment.