Namespace containing the shared code for each adapter.
It contains helpers for working with [[OutputStreams]] and assembling SSE sending function using several strategies and managing exceptions in the adapters.
The main concept here is what we call "write profiles". A write profile is a map of 3 keys:
With these 3 keys we can control buffering aspects of our SSE connection and compression functionality.
Here is an example profile which uses gzip and temporary buffers to concatenate SSE event text:
(def gzip-profile
{wrap-output-stream (fn [^OutputStream os] (-> os ->gzip-os ->os-writer))
content-encoding gzip-content-encoding
write! (->write-with-temp-buffer!)})
The wrap-output-stream
function will use a [[GZIPOutputStream]] and an
[[OutputStreamWriter]] constructed with the ->gzip-os
and ->os-writer
helpers.
To go with this we use a write!
function constructed with
->write-with-temp-buffer!
.
If we wanted specific buffer sizes we could do:
(def gzip-profile
{wrap-output-stream (fn[^OutputStream os]
(-> os
(->gzip-os 1024)
->os-writer))
content-encoding gzip-content-encoding
write! (->write-with-temp-buffer! 4096)})
The output stream wrapping helpers are:
The write function helper to go with them are:
See the rest of the docstrings for more details.
Namespace containing the shared code for each adapter. It contains helpers for working with [[OutputStreams]] and assembling SSE sending function using several strategies and managing exceptions in the adapters. The main concept here is what we call "write profiles". A write profile is a map of 3 keys: - [[wrap-output-stream]] - [[write!]] - [[content-encoding]] With these 3 keys we can control buffering aspects of our SSE connection and compression functionality. Here is an example profile which uses gzip and temporary buffers to concatenate SSE event text: ```clojure (def gzip-profile {wrap-output-stream (fn [^OutputStream os] (-> os ->gzip-os ->os-writer)) content-encoding gzip-content-encoding write! (->write-with-temp-buffer!)}) ``` The `wrap-output-stream` function will use a [[GZIPOutputStream]] and an [[OutputStreamWriter]] constructed with the [[->gzip-os]] and [[->os-writer]] helpers. To go with this we use a `write!` function constructed with [[->write-with-temp-buffer!]]. If we wanted specific buffer sizes we could do: ```clojure (def gzip-profile {wrap-output-stream (fn[^OutputStream os] (-> os (->gzip-os 1024) ->os-writer)) content-encoding gzip-content-encoding write! (->write-with-temp-buffer! 4096)}) ``` The output stream wrapping helpers are: - [[->gzip-os]] - [[->os-writer]] - [[->buffered-writer]] The write function helper to go with them are: - [[->write-with-temp-buffer!]] - [[write-to-buffered-writer!]] See the rest of the docstrings for more details.
(->buffered-writer osw)
(->buffered-writer osw buffer-size)
Make an BufferedWriter from an OutputStreamWriter osw
and an optional
buffer-size
.
Default buffer-size is the BufferedWriter's own.
Make an BufferedWriter from an OutputStreamWriter `osw` and an optional `buffer-size`. Default buffer-size is the BufferedWriter's own.
(->build-event-str)
(->build-event-str buffer-size)
Make a function that will assemble a SSE event using a StringBuiler and return the concatenated string.
Make a function that will assemble a SSE event using a StringBuiler and return the concatenated string.
(->gzip-os os)
(->gzip-os os buffer-size)
Make a GZIPOutputStream from an OutputStream os
and an optional
buffer-size
. The syncFlush always set to true.
Default buffer-size is the GZIPOutputStream's own.
Make a GZIPOutputStream from an OutputStream `os` and an optional `buffer-size`. The syncFlush always set to true. Default buffer-size is the GZIPOutputStream's own.
(->os-writer os)
(->os-writer os charset)
Make an OutputStreamWriter from an OutputStream os
and an optional
[[Charset]] charset
.
Defaut charset is [[StandardCharsets/UTF_8]]
Make an OutputStreamWriter from an OutputStream `os` and an optional [[Charset]] `charset`. Defaut charset is [[StandardCharsets/UTF_8]]
(->write-with-temp-buffer!)
(->write-with-temp-buffer! buffer-size)
Make a function that will assemble a SSE event using a [[StringBuilder]] and then will write the resulting string to an [[OutputStreamWriter]].
Make a function that will assemble a SSE event using a [[StringBuilder]] and then will write the resulting string to an [[OutputStreamWriter]].
Basic write profile using temporary [[StringBuilder]]s and no compression.
Basic write profile using temporary [[StringBuilder]]s and no compression.
Write profile using a permanent [[BufferedWriter]] and no compression.
Write profile using a permanent [[BufferedWriter]] and no compression.
(close-sse! close-io! on-close!)
Closing a sse-gen is a 2 steps process.
close-io!
thunk.on-close
callback by calling the on-close!
thunk.Both thunks are called using try-closing
to capture exceptions.
This function rethrows the first java.lang.Throwable
encountered. Otherwise
it returns either true
when all thunks are exceptions free or an
exception created with [[ex-info]] that contains the thunks exceptions in it's
data under the key closing-exceptions
.
Closing a sse-gen is a 2 steps process. 1. close IO resources calling the `close-io!` thunk. 2. call the sse-gen's `on-close` callback by calling the `on-close!` thunk. Both thunks are called using [[try-closing]] to capture exceptions. This function rethrows the first `java.lang.Throwable` encountered. Otherwise it returns either `true` when all thunks are exceptions free or an exception created with [[ex-info]] that contains the thunks exceptions in it's data under the key [[closing-exceptions]].
Exceptions caught while closing a sse generator using close-sse!
are grouped under this key in the ex-info's data that is returned.
Exceptions caught while closing a sse generator using [[close-sse!]] are grouped under this key in the ex-info's data that is returned.
SSE write profile option:
A string value for the Content-Encoding HTTP header. When using gzip
compression the value should be gzip-content-encoding
.
SSE write profile option: A string value for the Content-Encoding HTTP header. When using gzip compression the value should be [[gzip-content-encoding]].
(default-on-exception _sse e ctx)
Default on-exception
callback, it returns true
on [[IOException]] which
closes, the generator. It rethrows the exception wrapped with ex-infor
otherwise.
Default [[on-exception]] callback, it returns `true` on [[IOException]] which closes, the generator. It rethrows the exception wrapped with `ex-infor` otherwise.
(get-closing-exceptions e)
Extract the exceptions in the ex-data
of a ex-info thrown during the
closing of a sse generator.
Extract the exceptions in the `ex-data` of a ex-info thrown during the closing of a sse generator.
Write profile using a permanent [[BufferedWriter]] and gzip compression.
Write profile using a permanent [[BufferedWriter]] and gzip compression.
Write profile using temporary [[StringBuilder]]s and gzip compression.
Write profile using temporary [[StringBuilder]]s and gzip compression.
(headers ring-request & {:as opts})
Same as [[sse/headers]] with the added responsibility to add the Content-Encoding header based on a write profile.
Same as [[sse/headers]] with the added responsibility to add the Content-Encoding header based on a write profile.
SSE option key:
Callback (fn [sse-gen & args] ...)
called just after the SSE connection is
closed. More specifically this callback is called when:
starfederation.datastar.clojure.api/close-sse!
is called explicitelyWhen this callback is called it is already not possible to send events anymore. It is called synchronously in the same thread that initiates the closing process.
Args:
sse-gen
: the closed SSE generatorReturn value: The return value isn't used.
Exception behavior:
While closing the sse-gen
several exceptions may be caught:
These exceptions are rethrown wrapped in an ex-info
. To get at these see
get-closing-exceptions
.
SSE option key: Callback `(fn [sse-gen & args] ...)` called just after the SSE connection is closed. More specifically this callback is called when: - [[starfederation.datastar.clojure.api/close-sse!]] is called explicitely - the sse-gen detects that the connection is closed by the client. This detection depends on the ring adapter being used. Http-kit AsyncChannel detects a broken connection by itself and calls on-close. With the ring generic adapter, the default behavior is to close the connection when a [[java.io.IOException]] is thrown sending an event. When this callback is called it is already not possible to send events anymore. It is called synchronously in the same thread that initiates the closing process. Args: - `sse-gen`: the closed SSE generator - Depending on the adapter used other arguments may be passed, see doc for the adapter you are using. Return value: The return value isn't used. Exception behavior: While closing the `sse-gen` several exceptions may be caught: - one while closing the underlying output stream - one executing this callback These exceptions are rethrown wrapped in an `ex-info`. To get at these see [[get-closing-exceptions]].
SSE option key:
Callback (fn [sse-gen e ctx] ...)
that will be called when an exception is
thrown sending an event.
Args:
sse-gen
: the SSEGenratore
: the exceptionctx
: context information about the exception, a map whose keys are:
:sse-gen
: the sse generator throwing:event-type
: type of the event that failed:data-lines
: data lines for this event:opts
: options used when sendingReturned value: A truthy value means the sse-gen must close itself.
Exception behavior: Exception thrown here aren't caught.
Defaults to default-on-exception
which will close the sse-gen
on
IOException or rethrow otherwise.
SSE option key: Callback `(fn [sse-gen e ctx] ...)` that will be called when an exception is thrown sending an event. Args: - `sse-gen`: the SSEGenrator - `e`: the exception - `ctx`: context information about the exception, a map whose keys are: - `:sse-gen`: the sse generator throwing - `:event-type`: type of the event that failed - `:data-lines`: data lines for this event - `:opts`: options used when sending Returned value: A truthy value means the sse-gen must close itself. Exception behavior: Exception thrown here aren't caught. Defaults to [[default-on-exception]] which will close the `sse-gen` on IOException or rethrow otherwise.
SSE option key:
Mandatory callback (fn [sse-gen] ...)
called when the SSE connection is
open.
It is called synchronously as soon as the connection is ready. This means that you can block the webserver's thread from here.
Args:
sse-gen
: the SSE generator, ready to send eventsReturn value: The return value isn't used.
Exception behavior: Exception thrown here aren't caught.
SSE option key: Mandatory callback `(fn [sse-gen] ...)` called when the SSE connection is open. It is called synchronously as soon as the connection is ready. This means that you can block the webserver's thread from here. Args: - `sse-gen`: the SSE generator, ready to send events Return value: The return value isn't used. Exception behavior: Exception thrown here aren't caught.
(try-closing f error-msg)
Run a thunk f
that closes some resources. Catches exceptions and returns
them wrapped in a [[ex-info]] with the message error-msg
.
Run a thunk `f` that closes some resources. Catches exceptions and returns them wrapped in a [[ex-info]] with the message `error-msg`.
SSE write profile key:
A function that wraps an OutputStream like:
(fn [os] (clojure.java.io/writer os))
This function will be used to wrap the [[OutputStream]] used for a SSE connection.
It allows you to add compression and buffering to suit you needs.
The SDK provides utilities to implement such a wrapping function, see:
SSE write profile key: A function that wraps an OutputStream like: `(fn [os] (clojure.java.io/writer os))` This function will be used to wrap the [[OutputStream]] used for a SSE connection. It allows you to add compression and buffering to suit you needs. The SDK provides utilities to implement such a wrapping function, see: - [[->gzip-os]] - [[->os-writer]] - [[->buffered-writer]]
SSE write profile option:
A function that writes to a [[java.lang.Appendable]]. It should go in tandem with the way you wrap the [[OutputStream]].
The SDK provide pre-made write functions, see:
SSE write profile option: A function that writes to a [[java.lang.Appendable]]. It should go in tandem with the way you wrap the [[OutputStream]]. The SDK provide pre-made write functions, see: - [[->write-with-temp-buffer!]] - [[write-to-buffered-writer!]]
SSE option key:
This option allows a user to control the way SSE events are assembled and sent. It take a write profile which is a map whose keys are:
wrap-output-stream
write!
content-encoding
(optional if you don't use compression)SSE option key: This option allows a user to control the way SSE events are assembled and sent. It take a write profile which is a map whose keys are: - [[wrap-output-stream]] - [[write!]] - [[content-encoding]] (optional if you don't use compression)
(write-to-buffered-writer! writer event-type data-lines opts)
Write a SSE event to a stream using a [[BufferedWriter]].
Write a SSE event to a stream using a [[BufferedWriter]].
cljdoc builds & hosts documentation for Clojure/Script libraries
Ctrl+k | Jump to recent docs |
← | Move to previous article |
→ | Move to next article |
Ctrl+/ | Jump to the search field |