001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.console.bus;
018
019/**
020 * A transport's outbound side, handed to {@link ServerBus#connect(BusSession, FrameSink)} for one connection.
021 *
022 * <p>
023 * {@link #offer(String)} must not block: it queues the frame and returns at once, or returns <jk>false</jk> when the
024 * connection's queue (bounded by {@link BusPolicy#maxQueuedFrames()}) is full.  On <jk>false</jk> the bus detaches
025 * the sink and calls {@link #close(int, String)} with {@code 4429} / {@code bus:slow-consumer}.
026 *
027 * <p>
028 * {@link #close(int, String)} must not block either: the bus calls it while holding its lock.  A transport that needs a
029 * network handshake to close must hand the close off to another thread.
030 *
031 * <p>
032 * Close codes the bus uses: {@code 1001} {@code bus:closed} ({@link ServerBus#close()}), {@code 4401}
033 * {@code bus:unknown-session} (expired), {@code 4409} {@code bus:replaced} (a second connection took over the session)
034 * and {@code 4429} {@code bus:slow-consumer}.  A transport without close codes (SSE) ends its response instead.
035 *
036 * <h5 class='section'>Example:</h5>
037 * <p class='bjava'>
038 *   <jc>// A test double that records what the bus sends:</jc>
039 *   List&lt;String&gt; <jv>frames</jv> = <jk>new</jk> ArrayList&lt;&gt;();
040 *   FrameSink <jv>sink</jv> = <jk>new</jk> FrameSink() {
041 *     <ja>@Override</ja> <jk>public boolean</jk> offer(String <jv>frame</jv>) { <jk>return</jk> <jv>frames</jv>.add(<jv>frame</jv>); }
042 *     <ja>@Override</ja> <jk>public void</jk> close(<jk>int</jk> <jv>code</jv>, String <jv>reason</jv>) { }
043 *   };
044 *   <jv>bus</jv>.connect(<jv>session</jv>, <jv>sink</jv>);   <jc>// resync-begin, retained pubs, resync-end</jc>
045 * </p>
046 *
047 * @since 10.0.0
048 */
049public interface FrameSink {
050
051   /**
052    * Queues one encoded frame for sending.  Must not block.
053    *
054    * @param frame The encoded frame (see {@link BusFrames}).
055    * @return <jk>false</jk> when the connection's queue is full or the sink is closed.
056    */
057   boolean offer(String frame);
058
059   /**
060    * Closes the connection.  Called at most once by the bus for a given sink; must be safe to call again.
061    *
062    * @param code The close code ({@code 1001}, {@code 4401}, {@code 4409} or {@code 4429}).
063    * @param reason The {@code bus:*} reason.
064    */
065   void close(int code, String reason);
066}