콘텐츠로 이동
한국어

EventStream

이 콘텐츠는 아직 번역되지 않았습니다.

Defined in: src/EventStream.ts:72

A simple system-wide pub/sub bus. Subscribers register against a channel; publications are matched against it and tell’d to everyone interested.

Two ways to name a channel. A class, matched with instanceof, so subclass instances reach base-class subscribers — which is what makes an abstract base the most useful channel there is. Or an event’s kind, named by an EventKey or by the bare string, matched on the discriminant: the form the project’s own message convention needs, since a kind-discriminated plain type has no constructor to hand over and until recently could not be subscribed to at all — even though publish has always accepted one.

Predicate-filtered subscriptions (#85). Each subscription may carry an optional predicate that runs against the event before delivery — only events the predicate accepts are tell’d to the subscriber. Useful for high-frequency channels (cluster events, metrics) where the consumer only cares about a slice of the traffic and would otherwise have to filter inside its own onReceive. A predicate that throws is treated as “no match” for that delivery; the subscription stays active.

new EventStream(): EventStream

EventStream

optional log?: EventStreamLogger

Defined in: src/EventStream.ts:94

Optional logger used to surface predicate failures. Assigned by ActorSystem once its main logger has been constructed; tests that instantiate EventStream directly can leave it undefined — the bus stays functional, errors just stay silent.

get hasSubscribers(): boolean

Defined in: src/EventStream.ts:231

Whether anything is listening at all.

Coarse on purpose — any channel, any subscriber. Callers use it to skip constructing an event, which is only sound when the answer covers every channel; a per-channel query would let a caller skip building an event a different channel’s subscriber was entitled to. With DevTools attached the cost comes back, which is the intended trade.

boolean

publish(event): void

Defined in: src/EventStream.ts:242

object

void


subscribe<TEvent>(subscriber, channel, predicate?): boolean

Defined in: src/EventStream.ts:129

Subscribe an actor ref to a channel. Returns true if a new subscription was added; false if a duplicate was rejected.

Naming the channel. A class, an EventKey, or the bare kind string. The string is the shorthand and it costs the type: TEvent has nothing to be inferred from and falls back to unknown, so a predicate written against it sees unknown unless the caller spells the argument out — subscribe<UserLoggedInEvent>(ref, 'user-logged-in'), which also makes the string itself checkable against the type’s kind.

A key and its string are the same channel: subscribing both ways dedups, and either one unsubscribes the other. A class and a kind are not, even when the class’s instances carry that kind — those are two channels selecting overlapping events, exactly like a base class and its subclass, and an actor holding both subscriptions receives both deliveries.

Dedup rules. Without predicate, only one subscription per (subscriber, channel) is kept — re-calling subscribe is a no-op. With a predicate, every call adds a new subscription: predicates are values without an identity contract, so dedup’ing across them would be unreliable; users wanting “replace this filter” should unsubscribe first.

TEvent

ActorRef

EventChannel<TEvent>

(event) => boolean

boolean

TypeError when channel is neither a usable instanceof right-hand side nor a non-empty kind. Failing on the line that wrote the subscription is the whole point: the alternative is a subscription that poisons an unrelated publish in another actor much later (#1010). It throws rather than returning false, because false already means “duplicate rejected” and conflating the two destroys the signal the return value carries.


unsubscribe<TEvent>(subscriber, channel?): boolean

Defined in: src/EventStream.ts:171

Unsubscribe a (subscriber, channel) pair, or every subscription the actor holds when channel is omitted. Removes ALL matching entries — including predicate-bearing ones; finer-grained removal (one specific predicate at a time) isn’t supported because predicates have no stable identity.

The test is !== undefined, not truthiness. Truthiness was correct while a channel could only be a constructor; with kind strings legal, '' is a supplied channel that reads as falsy, and the old shape would have taken the omitted-channel branch and dropped every subscription the actor held.

The channel is resolved exactly as subscribe resolved it, so it is named by identity rather than by object: EventKey.of('x') mints a fresh key on every call and would match nothing under ===. An invalid channel throws here too — quietly removing nothing is how a subscription survives a cleanup that believed it had done its job (#645, #763).

TEvent

ActorRef

EventChannel<TEvent>

boolean