Skip to content

Commit 7b82df4

Browse files
committed
docs: Add TypeScript docs for implementing multicast notifications by calling RPCs provided by the client from the server
1 parent b325495 commit 7b82df4

1 file changed

Lines changed: 52 additions & 4 deletions

File tree

README.md

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ const registry = new Registry(
922922
);
923923
```
924924

925-
The coffee machine/server and the remote control/client now both know of the new `SetCoffeeMachineBrewing` RPC, but the server doesn't call it yet. To fix this, we can call this RPC transparently from the coffee machine by accessing the connected remote control(s) with `registry.forRemotes` just like we did before in the remote control, and we can handle errors with `try catch` just like if we were making a local function call:
925+
The coffee machine/server and the remote control/client now both know of the new `SetCoffeeMachineBrewing` RPC, but the server doesn't call it yet. To fix this, we can call this RPC transparently from the coffee machine by accessing the connected remote control(s) with `registry.forRemotes` just like we did before in the remote control, and we can handle errors with `try catch` just like if we were making a local function call. We'll also use the first argument to the RPC, `ILocalContext`, to get the ID of the remote control/client that is calling `BrewCoffee`, so that we don't call `SetCoffeeMachineBrewing` on the remote control/client that is calling `BrewCoffee` itself:
926926

927927
```typescript
928928
// coffee-machine.ts
@@ -939,10 +939,13 @@ class CoffeeMachine {
939939
variant: string,
940940
size: number
941941
): Promise<number> {
942+
// Get the ID of the remote control that's calling `BrewCoffee`
942943
const { remoteID: targetID } = ctx;
943944

944945
try {
946+
// Notify connected remote controls that coffee is brewing
945947
await this.forRemotes?.(async (remoteID, remote) => {
948+
// Don't call `SetCoffeeMachineBrewing` if it's the remote control that's calling `BrewCoffee`
946949
if (remoteID === targetID) {
947950
return;
948951
}
@@ -964,7 +967,9 @@ class CoffeeMachine {
964967
setTimeout(r, 5000);
965968
});
966969
} finally {
970+
// Notify connected remote controls that coffee is no longer brewing
967971
await this.forRemotes?.(async (remoteID, remote) => {
972+
// Don't call `SetCoffeeMachineBrewing` if it's the remote control that's calling `BrewCoffee`
968973
if (remoteID === targetID) {
969974
return;
970975
}
@@ -980,9 +985,52 @@ class CoffeeMachine {
980985
}
981986
```
982987

983-
- On the server's `BrewCoffee` RPC, before brewing coffee and after finishing, we'll call `SetCoffeeMachine` RPC for all clients that are connected (except the one that is calling the RPC itself - we can do that by checking the client's ID) with `this.forRemotes?`
984-
- We can set `forRemotes` by getting it from the registry
985-
- Starting the server again and starting three clients, then pressing "a" on one of them, and watching the other connected clients logging the brewing state before it has started/after it has stopped brewing except on the client that requested coffee to be brewed
988+
Note that we've added the `forRemotes` field to the coffee machine/server; we can get the implementation for it from the registry like so:
989+
990+
```typescript
991+
// coffee-machine.ts
992+
993+
const service = // ...
994+
995+
const registry = // ...
996+
997+
service.forRemotes = registry.forRemotes;
998+
```
999+
1000+
Now that's we've added support for this RPC to the coffee machine/server, we can restart it like so:
1001+
1002+
```shell
1003+
npx tsx coffee-machine.ts
1004+
```
1005+
1006+
To test if it works, connect two remote controls/clients to it like so:
1007+
1008+
```shell
1009+
npx tsx remote-control.ts
1010+
# In another terminal
1011+
npx tsx remote-control.ts
1012+
```
1013+
1014+
You can now brew a coffee on either of the remote controls by pressing a number and <kbd>ENTER</kbd>. Once the RPC has been called, the coffee machine should print something like the following again:
1015+
1016+
```plaintext
1017+
Brewing coffee variant latte in size 100 ml
1018+
```
1019+
1020+
And after the coffee has been brewed, the remote control that you've chosen to brew the coffee with should once again return the remaining water level like so:
1021+
1022+
```plaintext
1023+
Remaining water: 900 ml
1024+
```
1025+
1026+
The other connected remote controls will be notified that the coffee machine is brewing, and then once it has finished brewing:
1027+
1028+
```plaintext
1029+
Coffee machine is now brewing
1030+
Coffee machine has stopped brewing
1031+
```
1032+
1033+
**Enjoy your distributed coffee machine!** You've successfully called an RPC provided by a client from the server to implement multicast notifications, something that usually is quite complex to do with RPC systems.
9861034

9871035
#### 6. Passing Closures to RPCs
9881036

0 commit comments

Comments
 (0)