@procedures/peer 0.13.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,8 @@
11
11
  * repeatable procedure, a call with an idempotency key, or a call that runs one time.
12
12
  * - Each call is a stream (D4). A unary call is a stream of one. A stream call stays in flight
13
13
  * until its last item, and a cut after the first item ends the stream in-band, with an error.
14
+ * Each cut has the code `UNAVAILABLE`, before and after the first item. Its flag `retryable` tells
15
+ * if a retry is safe (CLI-48).
14
16
  */
15
17
 
16
18
  import type { Lifecycle, Operation, OperationOf, RequestEnd, RequestEvent, RouteRequest } from "@mark1russell7/service";
@@ -33,7 +35,8 @@ import {
33
35
  * The operation of a call, which gives its idempotency (D3):
34
36
  * - `repeatable`: the effects of the procedure permit a second run (no writes, or idempotent writes).
35
37
  * - `keyed`: the call has an idempotency key, and the server keeps its result for the window.
36
- * - `once`: each other call. A cut of it before its first item answers 500, because it can have had its effect.
38
+ * - `once`: each other call. A cut of it is `UNAVAILABLE` and not retryable, because it can have had its effect.
39
+ * Before its first item, the HTTP face answers 500 for it.
37
40
  */
38
41
  export type CallOperation = "repeatable" | "keyed" | "once";
39
42
 
@@ -93,17 +96,20 @@ function messageOf(error: unknown): string {
93
96
  }
94
97
 
95
98
  /**
96
- * The response of an end before the first item. A refusal and a retryable cut are `UNAVAILABLE`
97
- * (503, with `Retry-After` from the transport). Another cut and a failure are `INTERNAL_ERROR` (500).
99
+ * The response of an end before the first item. A refusal and each cut are `UNAVAILABLE`, because
100
+ * the server stopped (CLI-48). The flag `retryable` tells if a retry is safe:
101
+ * - A refusal and a retryable cut are retryable. The HTTP face answers 503, with `Retry-After` from the transport.
102
+ * - A cut of a call that can have had its effect is not retryable. The HTTP face answers 500, as the runner does.
103
+ * A failure is `INTERNAL_ERROR` (500).
98
104
  */
99
105
  function endResponse(id: string, end: RequestEnd): ServerResponse {
100
106
  switch (end.kind) {
101
107
  case "refused":
102
108
  return failure(id, "UNAVAILABLE", `The host does not take the call now: ${end.cause}`, true);
103
109
  case "cut":
104
- return end.status === 503
110
+ return end.retryable
105
111
  ? failure(id, "UNAVAILABLE", `The host stopped the call: ${end.cause}`, true)
106
- : failure(id, "INTERNAL_ERROR", `The host stopped the call, and the call can have had its effect: ${end.cause}`, false);
112
+ : failure(id, "UNAVAILABLE", `The host stopped the call, and the call can have had its effect: ${end.cause}`, false);
107
113
  case "failed":
108
114
  return failure(id, "INTERNAL_ERROR", messageOf(end.error), false);
109
115
  case "done":
@@ -114,11 +120,15 @@ function endResponse(id: string, end: RequestEnd): ServerResponse {
114
120
  /**
115
121
  * The error of an end after the first item: the stream ends in-band, with an error line. The count
116
122
  * of the items of the stream goes in the message. The head of the response is not an item.
123
+ *
124
+ * The code is always `UNAVAILABLE`, because the server stopped the stream. A cut is not a failure
125
+ * of the server. The flag `retryable` tells if a retry is safe (CLI-48). Before, a cut that is not
126
+ * retryable had the code `INTERNAL_ERROR`, before and after the first item.
117
127
  */
118
128
  function inBandEnd(end: Extract<RequestEnd, { kind: "refused" | "cut" }>): Error {
119
129
  const delivered = Math.max(0, end.delivered - 1);
120
130
  return Object.assign(new Error(`The host stopped the stream after ${delivered} items: ${end.cause}`), {
121
- code: end.retryable ? "UNAVAILABLE" : "INTERNAL_ERROR",
131
+ code: "UNAVAILABLE",
122
132
  retryable: end.retryable,
123
133
  delivered,
124
134
  });