import * as api from './apiServer.js'; import * as md from './markdown.js'; class Message { constructor(channel, body) { this.channel = channel; this.body = body; this.renderedBody = md.render(body); } } export class Outbox { pending = $state([]); static empty() { return new Outbox([]); } constructor(pending) { this.pending = pending; } send(channel, body) { this.pending.push(new Message(channel, body)); this.start(); } start() { if (this.sending) { return; } // This is a promise transform primarily to keep the management of `this.sending` in one place, // rather than spreading it across multiple methods. this.sending = this.drain().finally(() => { this.sending = null; }); } async drain() { while (this.pending.length > 0) { const { channel, body } = this.pending[0]; await api.retry(() => api.postToChannel(channel, body)); this.pending.shift(); } } }