001/*
002 * Copyright 2022-2025 Revetware LLC.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.soklet.core;
018
019import javax.annotation.Nonnull;
020
021/**
022 * Broadcasts a <a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events">Server-Sent Event</a> payload to all clients listening on a {@link ResourcePath}.
023 * <p>
024 * For example:
025 * <pre>{@code  // Acquire our SSE broadcaster (sends to anyone listening to "/examples/123")
026 * ServerSentEventServer server = ...;
027 * ServerSentEventBroadcaster broadcaster = server.acquireBroadcaster(ResourcePath.of("/examples/123")).get();
028 *
029 * // Create our SSE payload
030 * ServerSentEvent serverSentEvent = ServerSentEvent.withEvent("test")
031 *   .data("example")
032 *   .build();
033 *
034 * // Publish SSE payload to all listening clients
035 * broadcaster.broadcast(serverSentEvent);}</pre>
036 * <p>
037 * Soklet guarantees exactly one {@link ServerSentEventBroadcaster} instance exists per {@link ResourcePath}.  Soklet is responsible for the creation and management of {@link ServerSentEventBroadcaster} instances.
038 * <p>
039 * You may acquire a broadcaster via {@link ServerSentEventServer#acquireBroadcaster(ResourcePath)}.
040 * <p>
041 * See <a href="https://www.soklet.com/docs/server-sent-events">https://www.soklet.com/docs/server-sent-events</a> for detailed documentation.
042 * <p>
043 * Formal specification is available at <a href="https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events">https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events</a>.
044 *
045 * @author <a href="https://www.revetkn.com">Mark Allen</a>
046 */
047public interface ServerSentEventBroadcaster {
048        /**
049         * The runtime Resource Path with which this broadcaster is associated.
050         * <p>
051         * Soklet guarantees exactly one {@link ServerSentEventBroadcaster} instance exists per {@link ResourcePath}.
052         * <p>
053         * For example, a client may register for SSE broadcasts for <em>Resource Method</em> {@code @ServerSentEventSource("/examples/{exampleId}")} by making a request to {@code GET /examples/123}.
054         * <p>
055         * A broadcaster specific to {@code /examples/123} is then created (if necessary) and managed by Soklet, and can be used to send SSE payloads to all clients via {@link #broadcast(ServerSentEvent)}.
056         *
057         * @return the runtime Resource Path instance with which this broadcaster is associated
058         */
059        @Nonnull
060        ResourcePath getResourcePath();
061
062        /**
063         * Approximately how many clients are listening to this broadcaster's {@link ResourcePath}?
064         * <p>
065         * For performance reasons, this number may be an estimate, or a snapshot of a recent moment-in-time.
066         * It's possible for some clients to have already disconnected, but we won't know until we attempt to broadcast to them.
067         *
068         * @return the approximate number of clients who will receive a broadcasted event
069         */
070        @Nonnull
071        Long getClientCount();
072
073        /**
074         * Broadcasts a Server-Sent Event payload to all clients listening to this broadcaster's {@link ResourcePath}.
075         * <p>
076         * In practice, implementations will generally return "immediately" and broadcast operation[s] will occur on separate threads of execution.
077         * <p>
078         * However, mock implementations may wish to block until broadcasts have completed - for example, to simplify automated testing.
079         *
080         * @param serverSentEvent the Server-Sent Event payload to broadcast
081         */
082        void broadcast(@Nonnull ServerSentEvent serverSentEvent);
083}