sanity
Version:
Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches
90 lines (89 loc) • 3.5 kB
JavaScript
;
class MessageQueue {
constructor() {
this.resolver = null, this.queue = [];
}
push(message) {
this.resolver ? (this.resolver({ value: message, done: !1 }), this.resolver = null) : this.queue.push(message);
}
next() {
return this.queue.length ? Promise.resolve({ value: this.queue.shift(), done: !1 }) : new Promise((resolve) => this.resolver = resolve);
}
end() {
this.resolver && this.resolver({ value: void 0, done: !0 });
}
}
function isWorkerChannelMessage(message) {
return typeof message != "object" || !message || !("type" in message) || typeof message.type != "string" ? !1 : ["event", "emission", "end"].includes(message.type);
}
function createReceiver(worker) {
const _events = /* @__PURE__ */ new Map(), _streams = /* @__PURE__ */ new Map(), errors = new MessageQueue(), eventQueue = (name) => {
var _a;
const queue = (_a = _events.get(name)) != null ? _a : new MessageQueue();
return _events.has(name) || _events.set(name, queue), queue;
}, streamQueue = (name) => {
var _a;
const queue = (_a = _streams.get(name)) != null ? _a : new MessageQueue();
return _streams.has(name) || _streams.set(name, queue), queue;
}, handleMessage = (message) => {
isWorkerChannelMessage(message) && (message.type === "event" && eventQueue(message.name).push(message), message.type === "emission" && streamQueue(message.name).push(message), message.type === "end" && streamQueue(message.name).end());
}, handleError = (error) => {
errors.push({ type: "error", error });
};
return worker.addListener("message", handleMessage), worker.addListener("error", handleError), {
event: new Proxy({}, {
get: (target, name) => typeof name != "string" ? target[name] : async () => {
const { value } = await Promise.race([eventQueue(name).next(), errors.next()]);
if (value.type === "error")
throw value.error;
return value.payload;
}
}),
stream: new Proxy({}, {
get: (target, prop) => {
if (typeof prop != "string")
return target[prop];
const name = prop;
async function* streamReceiver() {
for (; ; ) {
const { value, done } = await Promise.race([streamQueue(name).next(), errors.next()]);
if (done)
return;
if (value.type === "error")
throw value.error;
yield value.payload;
}
}
return streamReceiver;
}
}),
dispose: () => (worker.removeListener("message", handleMessage), worker.removeListener("error", handleError), worker.terminate())
};
}
function createReporter(parentPort) {
if (!parentPort)
throw new Error("parentPart was falsy");
return {
event: new Proxy({}, {
get: (target, name) => typeof name != "string" ? target[name] : (payload) => {
const message = { type: "event", name, payload };
parentPort.postMessage(message);
}
}),
stream: new Proxy({}, {
get: (target, name) => typeof name != "string" ? target[name] : {
emit: (payload) => {
const message = { type: "emission", name, payload };
parentPort.postMessage(message);
},
end: () => {
const message = { type: "end", name };
parentPort.postMessage(message);
}
}
})
};
}
exports.createReceiver = createReceiver;
exports.createReporter = createReporter;
//# sourceMappingURL=workerChannels.js.map