loopbackaddon
The in-memory wire: a page and its server in one process, on any network shape.
Using it
loopback(accept) returns the page's side of a wire to the server's side of its seat, in one process. The scenemanager's link takes the wire. Make one wire for each seat.
import { loopback } from '#addons/loopback/loopback.addon.ts'
const wire = loopback(accept)
const slow = loopback(accept, time, { up: { delay: 40, jitter: 10 }, down: { delay: 40, jitter: 10, loss: 0.02 }, seed: 7, open: 60 })
With no network, every send arrives in the same call, as it does when a page and its manager share one tab. With a time and a net, each way is given a delay and the faults of a real connection, and the same seed always gives the same faults.
Methods
loopback( accept, time?, net? ) : Wire
Give time and net together or not at all. The wire has send(up), which carries a message to the server, and close(), which lets the seat go once and drops every item still in flight.
With a network, an item is handed on at the very millisecond it arrives, whatever the steps are doing. The page's link then holds it until the page's next frame takes it, and the server's inbox holds it until the server's next step.
accept
The type Accept.
The server's side of one seat. It is handed the function that sends to the page, and gives back { take(up), close() }: where the page's messages go, and how the seat is let go.
time
The type Time.
| Member | Meaning |
|---|---|
now() | The clock, in milliseconds. |
after(ms, f) | Calls f once the clock has moved ms milliseconds on. |
On a machine these are performance.now and setTimeout. The clock may instead be one that someone else holds and moves, as the simulator does.
net
The type Net.
| Key | Meaning |
|---|---|
up, down | A leg for each way: page to server, and server to page. |
seed | The number every random choice comes from. Five are rolled for each item whatever the settings say, so changing one setting moves no other roll. |
open | Optional. Milliseconds the wire takes to open, as a socket's handshake does. The server's side of the seat is made only then, and what the page sends in the meantime waits and then crosses. Left out or 0, the wire opens at once. |
A leg
The type Leg. A leg is read each time an item is sent, so changing its numbers changes the items sent after.
| Key | Meaning |
|---|---|
delay | Milliseconds an item waits. Required. |
jitter | Up to this many milliseconds more, an even spread from 0 to jitter. Default 0. |
tail | When true, the extra wait is instead mostly short and now and then many times jitter: an exponential wait whose mean is jitter. Default false. |
loss | The fraction of items dropped, 0 to 1. Default 0. |
reorder | The fraction of items allowed to pass the one sent before them. Default 0. A leg keeps order, as TCP does: an item arrives no sooner than the one sent before it unless reorder lets it. |
dup | The fraction of items handed on twice at once. Default 0. |
burst | The fraction of items held back and handed on together with the next item, as TCP and a browser's task queue hand on two messages together. Default 0. |
wait | (item, now) => number | null | undefined. Asked first for each item, with the millisecond it is sent at. A number is that item's own wait in place of delay and jitter, null drops it, and undefined leaves it to the other settings. A recording played again uses this to have each item arrive when it arrived. |
Used by
- scenemanagerIts
linktakes the wire this makes. - simulatorRuns pages on it against a server in time.
- socketIts wires have the same shape, so the same page code runs over either.
- accounts, recorderAlso use it.