release: WRNexusJS 0.8.0
This commit is contained in:
@@ -15,11 +15,14 @@ export type Handler<T = unknown> = (message: T, topic: string) => void | Promise
|
||||
export interface PubSubDriver {
|
||||
publish(topic: string, message: unknown): void | Promise<void>;
|
||||
subscribe(pattern: string, handler: Handler): () => void;
|
||||
close?(): void | Promise<void>;
|
||||
}
|
||||
|
||||
export interface PubSub {
|
||||
publish<T = unknown>(topic: string, message: T): Promise<void>;
|
||||
subscribe<T = unknown>(pattern: string, handler: Handler<T>): () => void;
|
||||
/** Stop new work, remove subscriptions, and close the backing driver. */
|
||||
close(): Promise<void>;
|
||||
}
|
||||
|
||||
function patternMatches(pattern: string, topic: string): boolean {
|
||||
@@ -31,14 +34,19 @@ function patternMatches(pattern: string, topic: string): boolean {
|
||||
/** In-process pub/sub driver (default). */
|
||||
export function memoryDriver(): PubSubDriver {
|
||||
const subs = new Map<string, Set<Handler>>();
|
||||
let closed = false;
|
||||
return {
|
||||
publish(topic, message) {
|
||||
async publish(topic, message) {
|
||||
if (closed) throw new Error("WRN-PUBSUB-CLOSED: pubsub driver is closed");
|
||||
const pending: Promise<void>[] = [];
|
||||
for (const [pattern, handlers] of subs) {
|
||||
if (!patternMatches(pattern, topic)) continue;
|
||||
for (const handler of handlers) void handler(message, topic);
|
||||
for (const handler of handlers) pending.push(Promise.resolve(handler(message, topic)));
|
||||
}
|
||||
await Promise.all(pending);
|
||||
},
|
||||
subscribe(pattern, handler) {
|
||||
if (closed) throw new Error("WRN-PUBSUB-CLOSED: pubsub driver is closed");
|
||||
let set = subs.get(pattern);
|
||||
if (!set) subs.set(pattern, (set = new Set()));
|
||||
set.add(handler);
|
||||
@@ -47,19 +55,35 @@ export function memoryDriver(): PubSubDriver {
|
||||
if (!set!.size) subs.delete(pattern);
|
||||
};
|
||||
},
|
||||
close() {
|
||||
closed = true;
|
||||
subs.clear();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/** Create a pub/sub bus over a driver (in-memory by default). */
|
||||
export function createPubSub(driver: PubSubDriver = memoryDriver()): PubSub {
|
||||
let closed = false;
|
||||
return {
|
||||
async publish(topic, message) {
|
||||
if (closed) throw new Error("WRN-PUBSUB-CLOSED: pubsub is closed");
|
||||
if (!topic.trim()) throw new TypeError("pubsub topic cannot be empty");
|
||||
await driver.publish(topic, message);
|
||||
},
|
||||
subscribe(pattern, handler) {
|
||||
if (closed) throw new Error("WRN-PUBSUB-CLOSED: pubsub is closed");
|
||||
if (!pattern.trim()) throw new TypeError("pubsub pattern cannot be empty");
|
||||
return driver.subscribe(pattern, handler as Handler);
|
||||
},
|
||||
async close() {
|
||||
if (closed) return;
|
||||
closed = true;
|
||||
await driver.close?.();
|
||||
},
|
||||
};
|
||||
}
|
||||
export { createResilientPubSub, PresenceChannel } from "./resilient.ts";
|
||||
export type { MessageEnvelope, ResilientPubSubOptions, PresenceMember } from "./resilient.ts";
|
||||
export { natsDriver, kafkaDriver } from "./brokers.ts";
|
||||
export type { NatsClient, KafkaClient } from "./brokers.ts";
|
||||
|
||||
Reference in New Issue
Block a user