Interface EventDispatcher
-
- All Known Implementing Classes:
DefaultEventDispatcher
,ReplayingEventDispatcher
,SinksEventDispatcher
public interface EventDispatcher
Distributes events to subscribers.Event
instances can be published over this class and dispatched to all subscribers.Individual events can be published to subscribers using
publish(Event)
while they can be used to consumed throughon(Class)
giving the properEvent
class as argument.Each event can be consumed using the following pattern:
dispatcher.on(MessageCreatedEvent.class) .subscribe(event -> event.getMessage());
While events can be published through:fluxOfEvents.doOnNext(dispatcher::publish) .subscribe();
-
-
Nested Class Summary
Nested Classes Modifier and Type Interface Description static interface
EventDispatcher.Builder
-
Field Summary
Fields Modifier and Type Field Description static Supplier<Scheduler>
DEFAULT_EVENT_SCHEDULER
static Logger
log
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Default Methods Deprecated Methods Modifier and Type Method Description static EventDispatcher
buffering()
Create anEventDispatcher
that will buffer incoming events to retain all startup events as each shard connects at the cost of increased memory usage and potentialOutOfMemoryError
if events are not consumed.static EventDispatcher.Builder
builder()
Create anEventDispatcher
builder.default Flux<Event>
on(ReactiveEventAdapter adapter)
Applies a givenadapter
to all events from this dispatcher.<E extends Event>
Flux<E>on(Class<E> eventClass)
default <E extends Event,T>
Flux<T>on(Class<E> eventClass, Function<E,Publisher<T>> mapper)
void
publish(Event event)
Publishes anEvent
to the dispatcher.static EventDispatcher
replaying()
Create anEventDispatcher
that is capable of replaying up to 2 minutes worth of important events likeGuildCreateEvent
andGatewayLifecycleEvent
that arrive while no subscribers are connected to all late subscribers, as long as they subscribe within the replay window of 5 seconds.static EventDispatcher
replayingWithSize(int historySize)
Create anEventDispatcher
that will replay up tohistorySize
elements to late subscribers.static EventDispatcher
replayingWithTimeout(Duration maxAge)
Create anEventDispatcher
that is time-bounded and retains all elements whose age is at mostmaxAge
, replaying them to late subscribers.void
shutdown()
Signal that this event dispatcher must terminate and release its resources.static EventDispatcher
withEarliestEvents(int bufferSize)
Create anEventDispatcher
that will buffer incoming events up to the givenbufferSize
elements, where subsequent events will be dropped in favor of retaining the earliest ones.static EventDispatcher
withLatestEvents(int bufferSize)
Deprecated.due to Processor API being deprecated, we recommend moving toreplayingWithSize(int)
for a dispatcher that is able to retain a given number of latest events
-
-
-
Method Detail
-
on
<E extends Event> Flux<E> on(Class<E> eventClass)
Retrieves aFlux
with elements of the givenEvent
type. ThisFlux
has to be subscribed to in order to start processing. SeeEvent
class for the list of possible event classes.Note: Errors occurring while processing events will terminate your sequence. If you wish to use a version capable of handling errors for you, use
on(Class, Function)
. See Reactive Streams Spec explaining this behavior.A recommended pattern to use this method is wrapping your code that may throw exceptions within a
flatMap
block and useMono.onErrorResume(Function)
,Flux.onErrorResume(Function)
or equivalent methods to maintain the sequence active:client.getEventDispatcher().on(MessageCreateEvent.class) .flatMap(event -> myCodeThatMightThrow(event) .onErrorResume(error -> { // log and then discard the error to keep the sequence alive log.error("Failed to handle event!", error); return Mono.empty(); })) .subscribe();
For more alternatives to handling errors, please see Error Handling docs page.
- Type Parameters:
E
- the type of the event class- Parameters:
eventClass
- the event class to obtain events from- Returns:
- a new
Flux
with the requested events
-
on
default <E extends Event,T> Flux<T> on(Class<E> eventClass, Function<E,Publisher<T>> mapper)
Retrieves aFlux
with elements of the givenEvent
type, to be processed through a givenFunction
upon subscription. Errors occurring within the mapper will be logged and discarded, preventing the termination of the "infinite" event sequence. SeeEvent
class for the list of possible event classes.There are multiple ways of using this event handling method, for example:
client.on(MessageCreateEvent.class, event -> { // myCodeThatMightThrow should return a Reactor type (Mono or Flux) return myCodeThatMightThrow(event); }) .subscribe(); client.on(MessageCreateEvent.class, event -> { // myCodeThatMightThrow *can* be blocking, so wrap it in a Reactor type return Mono.fromRunnable(() -> myCodeThatMightThrow(event)); }) .subscribe();
Continuing the chain after
on(class, event -> ...)
will require your own error handling strategy. Check the docs foron(Class)
for more details.- Type Parameters:
E
- the type of the event classT
- the type of the event mapper function- Parameters:
eventClass
- the event class to obtain events frommapper
- an event mapping function called on each event. If you do not wish to perform further operations you can returnMono.empty()
.- Returns:
- a new
Flux
with the type resulting from the given event mapper
-
on
default Flux<Event> on(ReactiveEventAdapter adapter)
Applies a givenadapter
to all events from this dispatcher. Errors occurring within the mapper will be logged and discarded, preventing the termination of the "infinite" event sequence. This variant allows you to have a single subscriber to this dispatcher, which is useful to collect all startup events.A standard approach to this method is to subclass
ReactiveEventAdapter
, overriding the methods you want to listen for:client.on(new ReactiveEventAdapter() { public Publisher<?> onReady(ReadyEvent event) { return Mono.fromRunnable(() -> System.out.println("Connected as " + event.getSelf().getTag())); } public Publisher<?> onMessageCreate(MessageCreateEvent event) { if (event.getMessage().getContent().equals("!ping")) { return event.getMessage().getChannel() .flatMap(channel -> channel.createMessage("Pong!")); } return Mono.empty(); } }).subscribe(); // nothing happens until you subscribe
Each method requires a
Publisher
return likeMono
orFlux
and all errors will be logged and discarded. To use a synchronous implementation you can wrap your code withMono.fromRunnable(Runnable)
.Continuing the chain will require your own error handling strategy. Check the docs for
on(Class)
for more details.- Parameters:
adapter
- an adapter meant to be subclassed with its appropriate methods overridden- Returns:
- a new
Flux
with the type resulting from the given event mapper
-
publish
void publish(Event event)
Publishes anEvent
to the dispatcher. Might throw an unchecked exception if the dispatcher can't handle this event.- Parameters:
event
- theEvent
to publish
-
shutdown
void shutdown()
Signal that this event dispatcher must terminate and release its resources.
-
builder
static EventDispatcher.Builder builder()
Create anEventDispatcher
builder. It can be configured with a customFluxProcessor
for events, a customFluxSink.OverflowStrategy
to handle backpressure and a customScheduler
to dispatch events.- Returns:
- a
EventDispatcher.Builder
-
buffering
static EventDispatcher buffering()
Create anEventDispatcher
that will buffer incoming events to retain all startup events as each shard connects at the cost of increased memory usage and potentialOutOfMemoryError
if events are not consumed. Startup events collected before the first subscription are only forwarded to that subscriber.- Returns:
- a buffering
EventDispatcher
backed by anEmitterProcessor
-
withEarliestEvents
static EventDispatcher withEarliestEvents(int bufferSize)
Create anEventDispatcher
that will buffer incoming events up to the givenbufferSize
elements, where subsequent events will be dropped in favor of retaining the earliest ones. Startup events collected before the first subscription are only forwarded to that subscriber.- Parameters:
bufferSize
- the number of events to keep in the backlog- Returns:
- an
EventDispatcher
keeping the earliest events up tobufferSize
-
withLatestEvents
static EventDispatcher withLatestEvents(int bufferSize)
Deprecated.due to Processor API being deprecated, we recommend moving toreplayingWithSize(int)
for a dispatcher that is able to retain a given number of latest eventsCreate anEventDispatcher
that will buffer incoming events up to the givenbufferSize
elements, where earliest events will be dropped in favor of retaining the latest ones. Startup events collected before the first subscription are only forwarded to that subscriber.- Parameters:
bufferSize
- the number of events to keep in the backlog- Returns:
- an
EventDispatcher
keeping the latest events backed by anEmitterProcessor
-
replaying
static EventDispatcher replaying()
Create anEventDispatcher
that is capable of replaying up to 2 minutes worth of important events likeGuildCreateEvent
andGatewayLifecycleEvent
that arrive while no subscribers are connected to all late subscribers, as long as they subscribe within the replay window of 5 seconds. After the replay window has closed, it behaves like an emitter event dispatcher.This allows controlling the memory overhead of dispatchers like
buffering()
while still keeping a record of important events to all late subscribers, even after login has completed.This dispatcher can be customized through the use of
ReplayingEventDispatcher.builder()
.- Returns:
- an
EventDispatcher
that is capable of replaying events to late subscribers
-
replayingWithTimeout
static EventDispatcher replayingWithTimeout(Duration maxAge)
Create anEventDispatcher
that is time-bounded and retains all elements whose age is at mostmaxAge
, replaying them to late subscribers. Be aware that using this type of dispatcher with operators such asFlux.retry()
orFlux.repeat()
that re-subscribe to the dispatcher will observe the same elements as the backlog contains.- Parameters:
maxAge
- the maximum age of the contained items- Returns:
- an
EventDispatcher
that will replay elements up tomaxAge
duration to late subscribers
-
replayingWithSize
static EventDispatcher replayingWithSize(int historySize)
Create anEventDispatcher
that will replay up tohistorySize
elements to late subscribers. Be aware that using this type of dispatcher with operators such asFlux.retry()
orFlux.repeat()
that re-subscribe to the dispatcher will observe the same elements as the backlog contains.- Parameters:
historySize
- the backlog size or maximum items retained for replay- Returns:
- an
EventDispatcher
that will replay up tohistorySize
elements to late subscribers
-
-