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.
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.
{
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.
{
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.
{
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.
When a server receives a fact
message, it responds with a received
message. This echoes back the token.
{
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.
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.
{
type: "loggedIn",
userFact: {
type: "Jinaga.User",
publicKey: "----BEGIN PUBLIC KEY---XXXXX"
},
profile: {
displayName: "Cliff Stoll"
}
}
The client sends a watch
message to begin watching for facts satisfying a specified query.
{
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.
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.
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.
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
.