All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.muserver.AsyncSsePublisher Maven / Gradle / Ivy

There is a newer version: 2.0.3
Show newest version
package io.muserver;

import java.nio.ByteBuffer;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * 

An interface for sending Server-Sent Events (SSE) to a client with async callbacks.

*

This is preferrable to the (blocking) {@link SsePublisher} when you have a large number of subscribers as * messages will be sent in a non-blocking fashion.

*

The usage is that same as for the synchronous version except that each send method returns a {@link CompletionStage} * which contains completion or exception info.

* * @see SsePublisher */ public interface AsyncSsePublisher { /** * Sends a message (without an ID or event type) * * @param message The message to send * @return completion stage that completes when the event has been sent. If there is a problem during sending of * an event, completion stage will be completed exceptionally. */ CompletionStage send(String message); /** *

Sends a message with an event type (without an ID).

*

Clients can use the event type to listen to different types of events, for example if the event type is pricechange * the the following JavaScript can be used:

*

     *     var source = new EventSource('/streamer');
     *     source.addEventListener('pricechange', e => console.log(e.data));
     * 
* * @param message The message to send * @param event An event name. If null is specified, clients default to a message type of message * @return completion stage that completes when the event has been sent. If there is a problem during sending of * an event, completion stage will be completed exceptionally. */ CompletionStage send(String message, String event); /** *

Sends a message with an event type and ID.

*

Clients can use the event type to listen to different types of events, for example if the event type is pricechange * the the following JavaScript can be used:

*

     *     var source = new EventSource('/streamer');
     *     source.addEventListener('pricechange', e => console.log(e.data));
     * 
* * @param message The message to send * @param event An event name. If null is specified, clients default to a message type of message * @param eventID An identifier for the message. If set, and the browser reconnects, then the last event ID will be * sent by the browser in the Last-Event-ID request header. * @return completion stage that completes when the event has been sent. If there is a problem during sending of * an event, completion stage will be completed exceptionally. */ CompletionStage send(String message, String event, String eventID); /** *

Stops the event stream.

*

Warning: most clients will reconnect several seconds after this message is called. To prevent that * happening, close the stream from the client or on the next request return a 204 No Content to the client.

*/ void close(); /** * Sends a comment to the client. Clients will ignore this, however it can be used as a way to keep the connection alive. * * @param comment A single-line string to send as a comment. * @return completion stage that completes when the comment has been sent. If there is a problem during sending of * an event, completion stage will be completed exceptionally. */ CompletionStage sendComment(String comment); /** *

Sends a message to the client instructing it to reconnect after the given time period in case of any disconnection * (including calling {@link #close()} from the server). A common default (controlled by the client) is several seconds.

*

Note: clients could ignore this value.

* * @param timeToWait The time the client should wait before attempting to reconnect in case of any disconnection. * @param unit The unit of time. * @return completion stage that completes when the event has been sent. If there is a problem during sending of * an event, completion stage will be completed exceptionally. */ CompletionStage setClientReconnectTime(long timeToWait, TimeUnit unit); /** *

Creates a new Server-Sent Events publisher. This is designed by be called from within a MuHandler.

*

This will set the content type of the response to text/event-stream and disable caching.

*

The request will also switch to async mode, which means you can use the returned publisher in another thread.

*

IMPORTANT: The {@link #close()} method must be called when publishing is complete.

* * @param request The current MuRequest * @param response The current MuResponse * @return Returns a publisher that can be used to send messages to the client. */ static AsyncSsePublisher start(MuRequest request, MuResponse response) { response.contentType(ContentTypes.TEXT_EVENT_STREAM); response.headers().set(HeaderNames.CACHE_CONTROL, "no-cache, no-transform"); return new AsyncSsePublisherImpl(request.handleAsync()); } } class AsyncSsePublisherImpl implements AsyncSsePublisher { private final AsyncHandle asyncHandle; AsyncSsePublisherImpl(AsyncHandle asyncHandle) { this.asyncHandle = asyncHandle; } @Override public CompletionStage send(String message) { return send(message, null, null); } @Override public CompletionStage send(String message, String event) { return send(message, event, null); } @Override public CompletionStage send(String message, String event, String eventID) { return write(SsePublisherImpl.dataText(message, event, eventID)); } @Override public CompletionStage sendComment(String comment) { return write(SsePublisherImpl.commentText(comment)); } @Override public CompletionStage setClientReconnectTime(long timeToWait, TimeUnit unit) { return write(SsePublisherImpl.clientReconnectText(timeToWait, unit)); } private CompletionStage write(String text) { CompletableFuture stage = new CompletableFuture<>(); asyncHandle.write(ByteBuffer.wrap(text.getBytes(UTF_8)), new WriteCallback() { @Override public void onFailure(Throwable reason) { stage.completeExceptionally(reason); } @Override public void onSuccess() { stage.complete(null); } }); return stage; } @Override public void close() { asyncHandle.complete(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy