Class KlientConfigBuilder

  • All Implemented Interfaces:

    
    public final class KlientConfigBuilder
    
                        

    Builder for NatsKlient configuration

    • Constructor Detail

      • KlientConfigBuilder

        KlientConfigBuilder()
    • Method Detail

      • getRequestCleanupInterval

         final Duration getRequestCleanupInterval()

        How often the connection reaps unanswered request inboxes

        A JetStream publish future has no per-call deadline of its own: jnats hands it a null timeout (NatsJetStream.java:171) and falls back to this interval (NatsConnection.java:1484-1486). natsy therefore raises whatever is set here to at least connectionTimeout and the JetStream requestTimeout, so a publish can keep the deadline those knobs report. A jnatsOptions customizer still wins if it sets a shorter interval; the publish deadline is then shortened to match.

      • setRequestCleanupInterval

         final Unit setRequestCleanupInterval(Duration value)

        How often the connection reaps unanswered request inboxes

        A JetStream publish future has no per-call deadline of its own: jnats hands it a null timeout (NatsJetStream.java:171) and falls back to this interval (NatsConnection.java:1484-1486). natsy therefore raises whatever is set here to at least connectionTimeout and the JetStream requestTimeout, so a publish can keep the deadline those knobs report. A jnatsOptions customizer still wins if it sets a shorter interval; the publish deadline is then shortened to match.

      • getReconnectOnConnect

         final Boolean getReconnectOnConnect()

        Whether NatsKlient.connect waits for a server that is not up yet

        With the default false, connecting is a single pass over servers: it either succeeds or throws, which is what a fail-fast startup wants.

        With true natsy uses jnats' connectReconnectOnConnect, which treats the initial connection like any other and hands it to the reconnect loop. That loop runs on the calling thread, sleeping reconnectWait between rounds until it connects or runs out of attempts - and the attempt budget is maxReconnects, whose default of -1 means unlimited. So with the defaults this turns NatsKlient.connect from "connected or throws" into "connected or blocks forever". Set a finite maxReconnects alongside it if startup must not hang.

        Worth it when the broker legitimately starts after the application - compose, or a pod that comes up before the NATS service.

      • setReconnectOnConnect

         final Unit setReconnectOnConnect(Boolean value)

        Whether NatsKlient.connect waits for a server that is not up yet

        With the default false, connecting is a single pass over servers: it either succeeds or throws, which is what a fail-fast startup wants.

        With true natsy uses jnats' connectReconnectOnConnect, which treats the initial connection like any other and hands it to the reconnect loop. That loop runs on the calling thread, sleeping reconnectWait between rounds until it connects or runs out of attempts - and the attempt budget is maxReconnects, whose default of -1 means unlimited. So with the defaults this turns NatsKlient.connect from "connected or throws" into "connected or blocks forever". Set a finite maxReconnects alongside it if startup must not hang.

        Worth it when the broker legitimately starts after the application - compose, or a pod that comes up before the NATS service.

      • getMaxMessagesInOutgoingQueue

         final Integer getMaxMessagesInOutgoingQueue()

        How many messages may wait in the connection's outgoing queue

        null leaves jnats' default (5000). The queue is what makes publishing look instantaneous: a publish hands the message over and returns. When it is full, publishing blocks until space appears, and then fails - see discardMessagesWhenOutgoingQueueFull for the other way out of that.

      • setMaxMessagesInOutgoingQueue

         final Unit setMaxMessagesInOutgoingQueue(Integer value)

        How many messages may wait in the connection's outgoing queue

        null leaves jnats' default (5000). The queue is what makes publishing look instantaneous: a publish hands the message over and returns. When it is full, publishing blocks until space appears, and then fails - see discardMessagesWhenOutgoingQueueFull for the other way out of that.

      • getDiscardMessagesWhenOutgoingQueueFull

         final Boolean getDiscardMessagesWhenOutgoingQueueFull()

        Whether a publish that finds the outgoing queue full drops the message instead of waiting

        The queue being full means the connection cannot write as fast as the application publishes. By default jnats waits for room and then throws, which natsy reports as a eu.vstoyanov.natsy.exception.NatsyConnectionException - correct for a publisher that must not lose messages, but it means a publish can block the calling thread for seconds.

        Set this for telemetry-shaped traffic, where dropping the newest sample beats stalling the caller. It is the only way to make publishing truly non-blocking.

      • setDiscardMessagesWhenOutgoingQueueFull

         final Unit setDiscardMessagesWhenOutgoingQueueFull(Boolean value)

        Whether a publish that finds the outgoing queue full drops the message instead of waiting

        The queue being full means the connection cannot write as fast as the application publishes. By default jnats waits for room and then throws, which natsy reports as a eu.vstoyanov.natsy.exception.NatsyConnectionException - correct for a publisher that must not lose messages, but it means a publish can block the calling thread for seconds.

        Set this for telemetry-shaped traffic, where dropping the newest sample beats stalling the caller. It is the only way to make publishing truly non-blocking.

      • getIoDispatcher

         final CoroutineDispatcher getIoDispatcher()

        The dispatcher every blocking NATS call runs on

        jnats is a blocking client: management calls, key-value and object-store operations, flushes and fetches all park a thread, so natsy moves them off the caller's. Dispatchers.IO is the right default; replace it to isolate NATS traffic from the rest of the application (Dispatchers.IO.limitedParallelism(n)), to run on virtual threads, or to make a test deterministic.

      • setIoDispatcher

         final Unit setIoDispatcher(CoroutineDispatcher value)

        The dispatcher every blocking NATS call runs on

        jnats is a blocking client: management calls, key-value and object-store operations, flushes and fetches all park a thread, so natsy moves them off the caller's. Dispatchers.IO is the right default; replace it to isolate NATS traffic from the rest of the application (Dispatchers.IO.limitedParallelism(n)), to run on virtual threads, or to make a test deterministic.

      • getCredentialsPath

         final String getCredentialsPath()

        Path to a NATS credentials file - the .creds holding a user JWT and its NKey seed

        A path, not the credential material itself: jnats reads the file on every connect and reconnect, so a rotated file is picked up without rebuilding the klient.

      • setCredentialsPath

         final Unit setCredentialsPath(String value)

        Path to a NATS credentials file - the .creds holding a user JWT and its NKey seed

        A path, not the credential material itself: jnats reads the file on every connect and reconnect, so a rotated file is picked up without rebuilding the klient.

      • getToken

         final CharArray getToken()

        Authentication token, held the way password is

        CharArray rather than String so the secret can be zeroed after connecting; jnats takes char[] here too and has deprecated its String overload (io/nats/client/Options.java:1952).

      • setToken

         final Unit setToken(CharArray value)

        Authentication token, held the way password is

        CharArray rather than String so the secret can be zeroed after connecting; jnats takes char[] here too and has deprecated its String overload (io/nats/client/Options.java:1952).

      • codecs

         final Unit codecs(Function1<CodecRegistry.Builder, Unit> block)

        Override how a type is carried, or configure the shared kotlinx.serialization.json.Json

        Nothing has to be registered: any @Serializable type is carried as JSON without appearing here. See CodecRegistry.

        Blocks accumulate rather than replace, so a second codecs { } - from a shared configuration helper, say - adds to the first instead of silently discarding it. This matches CodecRegistry.Builder.configureJson, which composes for the same reason.

      • jnatsOptions

         final Unit jnatsOptions(Function1<Options.Builder, Unit> customize)

        Reach a jnats option this DSL does not model

        Options.Builder carries around sixty settings; the properties above are the ones natsy has an opinion about. Everything else - inboxPrefix, an AuthHandler for NKey or JWT, keystorePath, socketWriteTimeout, tlsFirst, a custom ExecutorService - is reachable here rather than being unreachable until natsy grows a property for it.

        Applied last, after everything else this builder sets, so it can also override those. Blocks accumulate, like codecs.

        jnatsOptions {
            inboxPrefix("_INBOX.orders.")
            socketWriteTimeout(java.time.Duration.ofSeconds(5))
        }
      • build

         final KlientConfig build()

        Assemble the configuration

        Public because the configuration and the client are built in different places: a Ktor plugin or a Koin module reads settings from a file, fills this builder, and hands the result to NatsKlient. Construction validates, so a bad configuration fails here rather than at the first message.