Skip to content

Commit 59c4145

Browse files
[chore] PROTOCOL.md tweaks (#293)
## Why Addressing some nits ## What changed Decreasing duplication, typos, and confusion ## Versioning - [ ] Breaking protocol change - [ ] Breaking ts/js API change <!-- Kind reminder to add tests and updated documentation if needed -->
1 parent 6bf2184 commit 59c4145

File tree

1 file changed

+24
-45
lines changed

1 file changed

+24
-45
lines changed

PROTOCOL.md

Lines changed: 24 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ interface ControlAck {
212212

213213
interface ControlHandshakeRequest {
214214
type: 'HANDSHAKE_REQ';
215-
protocolVersion: 'v2.0';
215+
protocolVersion: 'v0' | 'v1' | 'v1.1' | 'v2.0';
216216
sessionId: string;
217217
expectedSessionState: {
218218
nextExpectedSeq: number; // integer
@@ -223,7 +223,22 @@ interface ControlHandshakeRequest {
223223

224224
interface ControlHandshakeResponse {
225225
type: 'HANDSHAKE_RESP';
226-
status: { ok: true; sessionId: string } | { ok: false; reason: string };
226+
status:
227+
| {
228+
ok: true;
229+
sessionId: string;
230+
}
231+
| {
232+
ok: false;
233+
reason: string;
234+
code: // retriable
235+
| 'SESSION_STATE_MISMATCH'
236+
// fatal
237+
| 'MALFORMED_HANDSHAKE_META'
238+
| 'MALFORMED_HANDSHAKE'
239+
| 'PROTOCOL_VERSION_MISMATCH'
240+
| 'REJECTED_BY_CUSTOM_HANDLER';
241+
};
227242
}
228243

229244
type Control =
@@ -238,7 +253,7 @@ type Control =
238253
## Streams
239254

240255
Streams tie together a series of messages into a single logical 'stream' of communication associated with a single remote procedure invocation.
241-
For example, in the case of a `stream` RPC, the client will send a series of messages with the same `streamId`, and the server must respond with a series of messages with the same `streamId`.
256+
For example, in the case of a `stream` procedure type, the client will send a series of messages with the same `streamId`, and the server must respond with a series of messages with the same `streamId`.
242257

243258
### Starting streams
244259

@@ -307,7 +322,7 @@ Then, depending on whether this is a client or server, the message must undergo
307322
For an incoming message to be considered valid on the client, the transport message MUST fulfill the following criteria:
308323

309324
- It should have a `streamId` that the client recognizes. That is, there MUST already be a message listener waiting for messages on the `streamId` of the original request message (recall that streams are only initiated by clients).
310-
- If a server sends an `ProtocolError` message the client MUST NOT send any further messages to the server for that stream including a control messages.
325+
- If a server sends a `ProtocolError` message the client MUST NOT send any further messages to the server for that stream including a control message.
311326

312327
If the message is invalid, the client MUST silently discard the message.
313328
Otherwise, this is a normal message. Unwrap the payload and return it to the caller of the original procedure.
@@ -533,11 +548,11 @@ The process differs slightly between the client and server:
533548
│ connect success ──────────────┤ connect failure
534549
▼ │
535550
3. SessionHandshaking │
536-
│ handshake success ┌────── connection drop
551+
│ handshake success ┌──────╪─ connection drop
537552
5. WaitingForHandshake │ handshake failure ─────┤ │
538553
│ handshake success ▼ │ │ connection drop
539554
├───────────────────────► 4. SessionConnected │ │ heartbeat misses
540-
│ │ invalid message ─────────────┘
555+
│ │ invalid message ─────────────┘
541556
│ ▼ │
542557
└───────────────────────► x. Destroy Session ◄─────┘
543558
handshake failure
@@ -555,43 +570,7 @@ Handshake messages are identical to normal transport messages except with:
555570
2. `ack: 0`
556571
3. no control flags
557572

558-
The handshake request payload schema is the following:
559-
560-
```ts
561-
type HandshakeRequest = {
562-
type: 'HANDSHAKE_REQ';
563-
protocolVersion: 'v0' | 'v1' | 'v1.1' | 'v2.0';
564-
sessionId: string;
565-
expectedSessionState: {
566-
nextExpectedSeq: number;
567-
nextSentSeq: number;
568-
};
569-
};
570-
```
571-
572-
The handshake response payload schema is the following:
573-
574-
```ts
575-
type HandshakeResponse = {
576-
type: 'HANDSHAKE_RESP';
577-
status:
578-
| {
579-
ok: true;
580-
sessionId: string;
581-
}
582-
| {
583-
ok: false;
584-
reason: string;
585-
code: // retriable
586-
| 'SESSION_STATE_MISMATCH'
587-
// fatal
588-
| 'MALFORMED_HANDSHAKE_META'
589-
| 'MALFORMED_HANDSHAKE'
590-
| 'PROTOCOL_VERSION_MISMATCH'
591-
| 'REJECTED_BY_CUSTOM_HANDLER';
592-
};
593-
};
594-
```
573+
The full handshake request and response payload schemas are defined above in the `Control` payload documentation.
595574

596575
The server will send an error response if either:
597576

@@ -616,7 +595,7 @@ Though this is very [TCP](https://jzhao.xyz/thoughts/TCP) inspired, River has th
616595
The send buffer is a queue of messages that have been sent but not yet acknowledged by the other side.
617596
When a message is sent (including `Control` messages like explicit acks), it is added to the send buffer.
618597

619-
All messages have an `ack` and the `ack` corresponds to the number of messages the other side has processed.
598+
All messages have an `ack` field, and the `ack` value corresponds to the number of messages the other side has processed.
620599
When receiving message a valid message (see the 'Handling Messages for Streams' section for the definition of 'valid'), sessions should ensure that the incoming message `msg.seq` MUST match the session's `session.ack`.
621600
This helps to ensure exactly once delivery and ensures that duplicate and out-of-order messages don't mistakingly update the session's bookkeeping.
622601

@@ -641,7 +620,7 @@ The client and server should both have a grace period `sessionDisconnectGraceMs`
641620

642621
It is important to note that this implies that there are two types of 'reconnects' in River:
643622

644-
1. Transparent reconnects: the connection dropped and reconnected but the session metadata is in-tact so resending the buffered messages will restore order. At the application level, nothing happened.
623+
1. Transparent reconnects: the connection dropped and reconnected but the session metadata is intact so resending the buffered messages will restore order. At the application level, nothing happened.
645624
2. Hard reconnect: the other transport has lost all state and current transport should invalidate all state and start from scratch.
646625

647626
The TypeScript implementation of the transport explicitly emits `connectionStatus` events for transparent reconnects and `sessionStatus` events for hard reconnects which the client and server can listen to.

0 commit comments

Comments
 (0)