// EventPool: pending-request registry and signal fan-out. // // Two distinct paths (see issue #33 for why the split matters): // request() — sends a packet AND registers a waiter for the correlated reply. // Use ONLY for handlers that return a reply (my/socketid, joinroom, …). // only() — sends a packet with NO registered waiter (fire-and-forget / WOM). // Use for pack/to, pack/room without handshake, etc. — anything the // engine answers nil to, so there is no reply to wait for. // Confusing the two leaves orphaned Promises or swallowed replies (#33). export default class EventPool { constructor(mwse) { this.wsts = mwse; this.events = new Map(); // id → [resolve, reject] this.signals = new Map(); // signalName → [callback, …] this.count = 0; } // request: sends msg and returns a Promise resolved by the server's reply. request(msg) { return new Promise((ok, rej) => { const id = ++this.count; this.events.set(id, [ok, rej]); this.wsts.WSTSProtocol.SendRequest(msg, id); }); } // only: sends msg without registering a waiter (WOM / fire-and-forget). only(msg) { this.wsts.WSTSProtocol.SendOnly(msg); } // stream: sends msg and calls callback for every 'C'ontinue reply. stream(msg, callback) { const id = ++this.count; this.wsts.WSTSProtocol.StartStream(msg, id); this.events.set(id, [callback, () => {}]); } // signal: registers a listener for a named server-initiated signal. signal(event, callback) { const existing = this.signals.get(event); if (existing) { existing.push(callback); } else { this.signals.set(event, [callback]); } } }