Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | 268x 268x 144x 144x 123x 144x 144x 123x 144x 144x 120x 120x 99x 120x 99x 526x 513x 13x 13x 526x 13x 13x 13x 13x 13x 13x | /* eslint-disable @typescript-eslint/no-empty-object-type */
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
type ListenersMap = Map<string, Map<string, Set<Function>>>
/**
* Event bus for service lifecycle events (create, destroy, etc.).
*
* Enables loose coupling between services by allowing them to subscribe
* to lifecycle events of their dependencies without direct references.
* Used primarily for invalidation cascading.
*/
/* eslint-disable @typescript-eslint/no-non-null-assertion */
export class LifecycleEventBus {
private listeners: ListenersMap = new Map()
constructor(private readonly logger: Console | null = null) {}
on<Event extends string | `pre:${string}` | `post:${string}`>(
ns: string,
event: Event,
listener: (event: Event) => void,
) {
this.logger?.debug(`[LifecycleEventBus]#on(): ns:${ns} event:${event}`)
if (!this.listeners.has(ns)) {
this.listeners.set(ns, new Map())
}
const nsEvents = this.listeners.get(ns)!
if (!nsEvents.has(event)) {
nsEvents.set(event, new Set())
}
nsEvents.get(event)!.add(listener)
return () => {
nsEvents.get(event)?.delete(listener)
if (nsEvents.get(event)?.size === 0) {
nsEvents.delete(event)
}
if (nsEvents.size === 0) {
this.listeners.delete(ns)
}
}
}
async emit(key: string, event: string) {
if (!this.listeners.has(key)) {
return
}
const events = this.listeners.get(key)!
this.logger?.debug(`[LifecycleEventBus]#emit(): ${key}:${event}`)
const res = await Promise.allSettled(
[...(events.get(event) ?? [])!].map((listener) => listener(event)),
).then((results) => {
const res = results
.filter((result) => result.status === 'rejected')
.map((result: PromiseRejectedResult) => {
this.logger?.warn(
`[LifecycleEventBus]#emit(): ${key}:${event} rejected with`,
result.reason,
)
return result
})
Iif (res.length > 0) {
return Promise.reject(res)
}
return results
})
return res
}
}
|