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 through on(Class) giving the proper Event 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();
     
    • Method Detail

      • on

        <E extends EventFlux<E> on​(Class<E> eventClass)
        Retrieves a Flux with elements of the given Event type. This Flux has to be subscribed to in order to start processing. See Event 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 use Mono.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 a Flux with elements of the given Event type, to be processed through a given Function upon subscription. Errors occurring within the mapper will be logged and discarded, preventing the termination of the "infinite" event sequence. See Event 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 for on(Class) for more details.

        Type Parameters:
        E - the type of the event class
        T - the type of the event mapper function
        Parameters:
        eventClass - the event class to obtain events from
        mapper - an event mapping function called on each event. If you do not wish to perform further operations you can return Mono.empty().
        Returns:
        a new Flux with the type resulting from the given event mapper
      • on

        default Flux<Event> on​(ReactiveEventAdapter adapter)
        Applies a given adapter 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 like Mono or Flux and all errors will be logged and discarded. To use a synchronous implementation you can wrap your code with Mono.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 an Event to the dispatcher. Might throw an unchecked exception if the dispatcher can't handle this event.
        Parameters:
        event - the Event to publish
      • shutdown

        void shutdown()
        Signal that this event dispatcher must terminate and release its resources.
      • buffering

        static EventDispatcher buffering()
        Create an EventDispatcher that will buffer incoming events to retain all startup events as each shard connects at the cost of increased memory usage and potential OutOfMemoryError if events are not consumed. Startup events collected before the first subscription are only forwarded to that subscriber.
        Returns:
        a buffering EventDispatcher backed by an EmitterProcessor
      • withEarliestEvents

        static EventDispatcher withEarliestEvents​(int bufferSize)
        Create an EventDispatcher that will buffer incoming events up to the given bufferSize 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 to bufferSize
      • withLatestEvents

        static EventDispatcher withLatestEvents​(int bufferSize)
        Deprecated.
        due to Processor API being deprecated, we recommend moving to replayingWithSize(int) for a dispatcher that is able to retain a given number of latest events
        Create an EventDispatcher that will buffer incoming events up to the given bufferSize 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 an EmitterProcessor
      • replaying

        static EventDispatcher replaying()
        Create an EventDispatcher that is capable of replaying up to 2 minutes worth of important events like GuildCreateEvent and GatewayLifecycleEvent 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 an EventDispatcher that is time-bounded and retains all elements whose age is at most maxAge, replaying them to late subscribers. Be aware that using this type of dispatcher with operators such as Flux.retry() or Flux.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 to maxAge duration to late subscribers
      • replayingWithSize

        static EventDispatcher replayingWithSize​(int historySize)
        Create an EventDispatcher that will replay up to historySize elements to late subscribers. Be aware that using this type of dispatcher with operators such as Flux.retry() or Flux.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 to historySize elements to late subscribers