@procedures/client 0.9.2 → 0.11.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,72 @@
1
1
  # @procedures/client
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 37c96a3: `createProcedureHost()` of `@procedures/peer` is one factory for each procedures server in Node. It gives the parts of a service of `@mark1russell7/service`, and `createPeer()` is a thin wrapper over it (server stack CLI-7, decisions D2, D3 and D4). This change is a break of the server stack, thus it is its own MINOR (decision D13).
8
+
9
+ - New `createProcedureHost({ registry, policy, faces: { http, ws, mcp }, listen, collections })`. It gives `{ handler, upgrade, parts, dependencies, checks, controllers, info }` and `declare(svc)`. It starts nothing and installs no signal handler.
10
+ - The parts: the procedure server (its stop parts of CLI-5), the stop parts of each face, and an `httpTransport` of `@mark1russell7/service/http` for each listener that the host owns. The faces of a listener mount on its mount list, so they share one port.
11
+ - Without a listener, the app mounts `host.handler` and `host.upgrade` on its own listener.
12
+ - The request tracking: each call goes through `life.request`, with the route `<face> <procedure>`. One route pattern for each face (`http *`, `ws *`, `mcp *`) matches each call. The function of the pattern gives the idempotency of each call: `repeatable`, `keyed` (an idempotency key) or `once` (decision D3).
13
+ - Each call is a stream (decision D4). A stream stays in flight until its last item. A cut after the first item ends the stream with an error line, and the line tells the count of the items.
14
+ - The faces are factories: `httpFace()` and `wsFace()` of `@procedures/peer`, and the new `mcpFace()` of `@procedures/mcp-server`. A face of another package has the same shape.
15
+ - The collections come from the option `collections`. The host serves `collections.<name>.*`, and each storage is a dependency handle of the service.
16
+ - `createPeer()` is for a process that has no service of its own. It declares the parts of its host in a service of its own, and starts `run()` of `@mark1russell7/service` on `embeddedProcess()`, a process port that installs no signal handler and never ends the process. `stop()` asks that lifecycle for its shutdown. The new option `profile` gives the profile of that service, and the default is `PEER_PROFILE`.
17
+ - The WebSocket face refuses an upgrade that the server does not admit, with the path of each call: 401 without the token or for a refusal of the request hook, and 403 for a failed browser check. A request hook that admits a request without credentials lets the connection open.
18
+ - New exports of `@procedures/peer`: `createProcedureHost`, `httpFace`, `wsFace`, `LOCAL_LISTENER_KNOBS`, `peerHostOptions`, `PEER_PROFILE`, `faceHandler`, `callOperations`, `operationOfCall`, and their types. `Peer.getHost()` gives the host of a peer.
19
+ - `@procedures/mcp-server`: new `mcpFace()`. New option `httpOptions.mount` and method `McpServerTransport.handleHttp()`: a Streamable HTTP endpoint on a listener of another part. `McpServerTransport` takes each `RequestHandler`, not only a `Server`.
20
+ - `@procedures/client`: new `ProcedureServer.procedureOf(method)`, and `ProcedureServer.admits(credentials)`: the request hook, the token check and the authenticate function of a call, for a connection before its first call.
21
+ - `@procedures/peer` depends on `@mark1russell7/service` `^0.5.2`, for `embeddedProcess()` (SYS-27), and no longer on Express.
22
+
23
+ The behavior that changes:
24
+
25
+ - A peer has no `/health` and no `/api/health` route. The probes come from the runner. `checkServer()` of `@procedures/peer/lockfile` calls `host.info` with the token of the lockfile (a part of CLI-9).
26
+ - A peer has one token: the token of its transports, or else the token of its policy. Two different tokens throw at `createPeer()`. The token applies to each face.
27
+ - The token of a peer applies to the upgrade of each WebSocket connection, also for a transport with no token of its own.
28
+ - `peer.stop({ grace })`: the grace has no effect, and the option is deprecated. The profile of the peer gives the drain, and `PEER_PROFILE` aborts the calls in flight at the start of the drain, as `stop()` without a grace did.
29
+ - A refused browser request gets the error of wire v1: `FORBIDDEN` with a `reason`. Before, the peer sent its own JSON.
30
+ - A peer starts one time. A `start()` after `stop()` throws: create a new peer.
31
+ - A listener that the peer cannot use gives `The HTTP server cannot listen on <host>:<port>` or `The WebSocket server cannot listen on <host>:<port>`.
32
+ - `HttpTransportConfig.cors: true` gives the CORS of `procedureHandler`: each origin, without credentials.
33
+
34
+ Migration steps:
35
+
36
+ - The site and MiniMongo: no change is necessary, unless they read `/health` of a peer. Then call `host.info` with the token.
37
+ - The MCP host of Graph: no change is necessary. To share the port of the Graph host, mount `mcpFace()` on its listener.
38
+ - jarvis and Graph under `run()`: build the procedures with `createProcedureHost()`, and call `host.declare(svc)` in the service of the process. Give `listen` for a port of the host, or mount `host.handler` and `host.upgrade` on the listener of the app.
39
+ - A caller of `createPeer()` with a different token for each transport: give one token.
40
+ - A Docker `HEALTHCHECK` or a probe of Kubernetes that read `/health` of a peer: use the probes of the service. Give the service `probeServer({ port, server_retry_after })` on a port of its own, or mount `probeHandler(health, { prefix: "/health" })` on the port of the app. Both come from `@mark1russell7/service/http`, and they answer `/health/startup`, `/health/readiness` and `/health/liveness`. The lockfile check of a client calls `host.info` with the token of the lockfile.
41
+ - A test that read `/health` of a peer: call `host.info` with the token, or check the status 404.
42
+
43
+ ## 0.10.0
44
+
45
+ ### Minor Changes
46
+
47
+ - 254ee7b: `ProcedureServer` has stop parts in the shape of the runner of `@mark1russell7/service`, and its storages are dependency handles (server stack CLI-5, decision D2). This change is a break of the server stack, thus it is its own MINOR (decision D13).
48
+
49
+ - New methods of `ProcedureServer`: `stopIntake()`, `drain(deadline, signal)`, `inFlight()` and `close()`. The server is a `TransportImpl` of the runner by its shape, and the types are structural: the root and `./browser` import no code of the runner.
50
+ - `stopIntake()` refuses each new call with a retryable `UNAVAILABLE`, and ends each subscription of `events.subscribe`. The calls in flight continue.
51
+ - `drain(deadline, signal)` waits until no call is in flight, or until the deadline on the clock of the server. When the signal aborts, each call that still runs gets the abort. The drain uses only the clock of the server, with no timer of its own.
52
+ - `close()` aborts each call that still runs and stops the transports of the server. The intake stays stopped until the next `start()`, and a second close gives the same promise. `close()` does not close the storages.
53
+ - New `storageHandles()`: one `StorageHandle` for each storage, also for a storage of two collections. A handle is a `DependencyHandle` of the runner by its shape: `connect` does nothing, and `close` closes the storage and removes its collections. The runner closes the handles after the transports close.
54
+ - `start()` opens the intake again after `close()`, and the next calls get a new signal.
55
+ - `stop({ grace })` is the parts in the sequence of the stages: `stopIntake()`, `drain()` for the grace, `close()`, and then `closeStorages()`. The server can start again, as before.
56
+ - New exported types: `StopParts` and `StorageHandle`, from the root, `./browser` and `./server`.
57
+ - `callsInFlight` is deprecated. Use `inFlight()`, which gives the same count.
58
+
59
+ The behavior that changes:
60
+
61
+ - The grace of `stop({ grace })` waits on the option `clock` of the server. Before, it waited on `setTimeout`. A test that gives a fake clock and stops with a grace must advance the clock.
62
+ - During `stop()`, the intake stays stopped until the storages close. Before, a call that came while the transports stopped could start, and then find a closed storage.
63
+
64
+ Migration steps:
65
+
66
+ - The site, MiniMongo and the MCP host of Graph: no change is necessary. `stop({ grace })` keeps its result. Change `server.callsInFlight` to `server.inFlight()`.
67
+ - jarvis and Graph under `run()`: declare the parts in the service of the process. Do not call `stop()`. Declare `svc.server("procedures", {}, server)`, and declare each handle of `server.storageHandles()` with `svc.dependency(handle.name, spec, handle)`. Give the server and `run()` the same clock, with the option `clock` of each.
68
+ - A test with a fake clock that calls `stop({ grace })` with calls in flight: advance the clock by the grace, or stop without a grace.
69
+
3
70
  ## 0.9.2
4
71
 
5
72
  No changes in this release.