// Copyright 2015-2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef NATS_H_ #define NATS_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include "status.h" #include "version.h" /** \def NATS_EXTERN * \brief Needed for shared library. * * Based on the platform this is compiled on, it will resolve to * the appropriate instruction so that objects are properly exported * when building the shared library. */ #if defined(_WIN32) #include #if defined(nats_EXPORTS) #define NATS_EXTERN __declspec(dllexport) #elif defined(nats_IMPORTS) #define NATS_EXTERN __declspec(dllimport) #else #define NATS_EXTERN #endif typedef SOCKET natsSock; #else #define NATS_EXTERN typedef int natsSock; #endif /*! \mainpage %NATS C client. * * \section intro_sec Introduction * * The %NATS C Client is part of %NATS, an open-source cloud-native * messaging system, and is supported by [Synadia Communications Inc.](http://www.synadia.com). * This client, written in C, follows the go client closely, but * diverges in some places. * * \section install_sec Installation * * Instructions to build and install the %NATS C Client can be * found at the [NATS C Client GitHub page](https://github.com/nats-io/nats.c) * * \section faq_sec Frequently Asked Questions * * Some of the frequently asked questions can be found [here](https://github.com/nats-io/nats.c#faq) * * \section other_doc_section Other Documentation * * This documentation focuses on the %NATS C Client API; for additional * information, refer to the following: * * - [General Documentation for nats.io](http://nats.io/documentation) * - [NATS C Client found on GitHub](https://github.com/nats-io/nats.c) * - [The NATS Server (nats-server) found on GitHub](https://github.com/nats-io/nats-server) */ /** \brief The default `NATS Server` URL. * * This is the default URL a `NATS Server`, running with default listen * port, can be reached at. */ #define NATS_DEFAULT_URL "nats://localhost:4222" /** \brief Message header for JetStream messages representing the message payload size * * When creating a JetStream consumer, if the `HeadersOnly` boolean is specified, * the subscription will receive messages with headers only (no message payload), * and a header of this name containing the size of the message payload that was * omitted. * * @see jsConsumerConfig */ #define JSMsgSize "Nats-Msg-Size" /** \brief Message header for JetStream message for rollup * * If message is sent to a stream's subject with this header set, and the stream * is configured with `AllowRollup` option, then the server will insert this * message and delete all previous messages in the stream. * * If the header is set to #JSMsgRollupSubject, then only messages on the * specific subject this message is sent to are deleted. * * If the header is set to #JSMsgRollupAll, then all messages on all subjects * are deleted. */ #define JSMsgRollup "Nats-Rollup" /** \brief Message header value causing rollup per subject * * This is a possible value for the #JSMsgRollup header indicating that only * messages for the subject the rollup message is sent will be removed. * * @see JSMsgRollup */ #define JSMsgRollupSubject "sub" /** \brief Message header value causing rollup for all subjects * * This is a possible value for the #JSMsgRollup header indicating that all * messages for all subjects will be removed. * * @see JSMsgRollup */ #define JSMsgRollupAll "all" // Headers for republished messages and direct get. #define JSStream "Nats-Stream" #define JSSequence "Nats-Sequence" #define JSLastSequence "Nats-Last-Sequence" #define JSTimeStamp "Nats-Time-Stamp" #define JSSubject "Nats-Subject" // // Types. // /** \defgroup typesGroup Types * * NATS Types. * @{ */ /** \brief A connection to a `NATS Server`. * * A #natsConnection represents a bare connection to a `NATS Server`. It will * send and receive byte array payloads. */ typedef struct __natsConnection natsConnection; /** \brief Statistics of a #natsConnection * * Tracks various statistics received and sent on a connection, * including counts for messages and bytes. */ typedef struct __natsStatistics natsStatistics; /** \brief Interest on a given subject. * * A #natsSubscription represents interest in a given subject. */ typedef struct __natsSubscription natsSubscription; /** \brief A structure holding a subject, optional reply and payload. * * #natsMsg is a structure used by Subscribers and * #natsConnection_PublishMsg(). */ typedef struct __natsMsg natsMsg; /** \brief Way to configure a #natsConnection. * * Options can be used to create a customized #natsConnection. */ typedef struct __natsOptions natsOptions; /** \brief Unique subject often used for point-to-point communication. * * This can be used as the reply for a request. Inboxes are meant to be * unique so that replies can be sent to a specific subscriber. That * being said, inboxes can be shared across multiple subscribers if * desired. */ typedef char natsInbox; /** \brief A list of NATS messages. * * Used by some APIs which return a list of #natsMsg objects. * * Those APIs will not create the object, but instead initialize * the object to which a pointer to that object will be passed to it. * Typically, the user will define the object on the stack and * pass a pointer to this object to APIs that require a pointer * to a #natsMsgList object. * * Similarly, calling #natsMsgList_Destroy will call #natsMsg_Destroy * on any message still in the list, free the array containing pointers * to the messages, but not free the #natsMsgList object itself. * * \note If the user wants to keep some of the messages from the * list, the pointers of those messages in the `Msgs` array should * be set to `NULL`. The value `Count` MUST not be changed. The * function #natsMsgList_Destroy will iterate through all * pointers in the list and only destroy the ones that have not * been set to `NULL`. * * @see natsMsgList_Destroy */ typedef struct natsMsgList { natsMsg **Msgs; int Count; } natsMsgList; /** * The JetStream context. Use for JetStream assets management and communication. * * \warning A context MUST not be destroyed concurrently with #jsCtx API calls * (for instance #js_Publish or #js_PublishAsync, etc...). However, it * is safe to destroy the context while a #jsPubAckErrHandler callback is * running or while inside #js_PublishAsyncComplete. */ typedef struct __jsCtx jsCtx; /** * JetStream publish options. * * These are options that you can provide to JetStream publish APIs. * * The common usage will be to initialize a structure on the stack by * calling #jsPubOptions_Init. Note that strings are owned by * the application and need to be valid for the duration of the API * call this object is passed to. * * \note It is the user responsibility to free the strings if they * have been allocated. * * @see jsPubOptions_Init */ typedef struct jsPubOptions { int64_t MaxWait; ///< Amount of time (in milliseconds) to wait for a publish response, default will the context's Wait value. const char *MsgId; ///< Message ID used for de-duplication. const char *ExpectStream; ///< Expected stream to respond from the publish call. const char *ExpectLastMsgId; ///< Expected last message ID in the stream. uint64_t ExpectLastSeq; ///< Expected last message sequence in the stream. uint64_t ExpectLastSubjectSeq; ///< Expected last message sequence for the subject in the stream. bool ExpectNoMessage; ///< Expected no message (that is, sequence == 0) for the subject in the stream. } jsPubOptions; /** * Determines how messages in a set are retained. */ typedef enum { js_LimitsPolicy = 0, ///< Specifies that messages are retained until any given limit is reached, which could be one of MaxMsgs, MaxBytes, or MaxAge. This is the default. js_InterestPolicy, ///< Specifies that when all known observables have acknowledged a message it can be removed. js_WorkQueuePolicy, ///< Specifies that when the first worker or subscriber acknowledges the message it can be removed. } jsRetentionPolicy; /** * Determines how to proceed when limits of messages or bytes are reached. */ typedef enum { js_DiscardOld = 0, ///< Will remove older messages to return to the limits. This is the default. js_DiscardNew, ///< Will fail to store new messages. } jsDiscardPolicy; /** * Determines how messages are stored for retention. */ typedef enum { js_FileStorage = 0, ///< Specifies on disk storage. It's the default. js_MemoryStorage, ///< Specifies in memory only. } jsStorageType; /** * Determines how the consumer should select the first message to deliver. */ typedef enum { js_DeliverAll = 0, ///< Starts from the very beginning of a stream. This is the default. js_DeliverLast, ///< Starts with the last sequence received. js_DeliverNew, ///< Starts with messages sent after the consumer is created. js_DeliverByStartSequence, ///< Starts from a given sequence. js_DeliverByStartTime, ///< Starts from a given UTC time (number of nanoseconds since epoch) js_DeliverLastPerSubject, ///< Starts with the last message for all subjects received. } jsDeliverPolicy; /** * Determines how the consumer should acknowledge delivered messages. */ typedef enum { js_AckExplicit = 0, ///< Requires ack or nack for all messages. js_AckNone, ///< Requires no acks for delivered messages. js_AckAll, ///< When acking a sequence number, this implicitly acks all sequences below this one as well. } jsAckPolicy; /** * Determines how the consumer should replay messages it already has queued in the stream. */ typedef enum { js_ReplayInstant = 0, ///< Replays messages as fast as possible. js_ReplayOriginal, ///< Maintains the same timing as the messages were received. } jsReplayPolicy; /** * Used to guide placement of streams in clustered JetStream. * * Initialize the object with #jsPlacement_Init. * * \note The strings are applications owned and will not be freed by the library. * * See #jsStreamConfig for information on how to configure a stream. * * @see jsPlacement_Init */ typedef struct jsPlacement { const char *Cluster; const char **Tags; int TagsLen; } jsPlacement; /** * Allows you to qualify access to a stream source in another account. * * Initialize the object with #jsExternalStream_Init. * * \note The strings are applications owned and will not be freed by the library. * * See #jsStreamConfig for information on how to configure a stream. */ typedef struct jsExternalStream { const char *APIPrefix; const char *DeliverPrefix; } jsExternalStream; /** * Dictates how streams can source from other streams. * * Initialize the object with #jsStreamSource_Init. * * \note The strings are applications owned and will not be freed by the library. * * \note The `OptStartTime` needs to be expressed as the number of nanoseconds * passed since 00:00:00 UTC Thursday, 1 January 1970. * * See #jsStreamConfig for information on how to configure a stream. */ typedef struct jsStreamSource { const char *Name; uint64_t OptStartSeq; int64_t OptStartTime; ///< UTC time expressed as number of nanoseconds since epoch. const char *FilterSubject; jsExternalStream *External; // Domain and External are mutually exclusive. // If Domain is set, an External value will be created with // the APIPrefix constructed based on the Domain value. const char *Domain; } jsStreamSource; /** * Allows a source subject to be mapped to a destination subject for republishing. */ typedef struct jsRePublish { const char *Source; const char *Destination; bool HeadersOnly; } jsRePublish; /** * Configuration of a JetStream stream. * * There are sensible defaults for most. If no subjects are * given the name will be used as the only subject. * * In order to add/update a stream, a configuration needs to be set. * The typical usage would be to initialize all required objects on the stack * and configure them, then pass the pointer to the configuration to * #js_AddStream or #js_UpdateStream. * * \note The strings are applications owned and will not be freed by the library. * * @see jsStreamConfig_Init * * \code{.unparsed} * jsStreamConfig sc; * jsPlacement p; * jsStreamSource m; * jsExternalStream esm; * jsStreamSource s1; * jsStreamSource s2; * jsExternalStream esmS2; * const char *subjects[] = {"foo", "bar"}; * const char *tags[] = {"tag1", "tag2"}; * jsStreamSource *sources[] = {&s1, &s2}; * jsRePublish rp; * * jsStreamConfig_Init(&sc); * * jsPlacement_Init(&p); * p.Cluster = "MyCluster"; * p.Tags = tags; * p.TagsLen = 2; * * jsStreamSource_Init(&m); * m.Name = "AStream"; * m.OptStartSeq = 100; * m.FilterSubject = "foo"; * jsExternalStream_Init(&esm); * esm.APIPrefix = "mirror.prefix."; * esm.DeliverPrefix = "deliver.prefix."; * m.External = &esm; * * jsStreamSource_Init(&s1); * s1.Name = "StreamOne"; * s1.OptStartSeq = 10; * s1.FilterSubject = "stream.one"; * * jsStreamSource_Init(&s2); * s2.Name = "StreamTwo"; * s2.FilterSubject = "stream.two"; * jsExternalStream_Init(&esmS2); * esmS2.APIPrefix = "mirror.prefix."; * esmS2.DeliverPrefix = "deliver.prefix."; * s2.External = &esmS2; * * sc.Name = "MyStream"; * sc.Subjects = subjects; * sc.SubjectsLen = 2; * sc.Retention = js_InterestPolicy; * sc.Replicas = 3; * sc.Placement = &p; * sc.Mirror = &m; * sc.Sources = sources; * sc.SourcesLen = 2; * * // For RePublish subject: * jsRePublish_Init(&rp); * rp.Source = ">"; * rp.Destination = "RP.>"; * sc.RePublish = &rp; * * s = js_AddStream(&si, js, &sc, NULL, &jerr); * \endcode */ typedef struct jsStreamConfig { const char *Name; const char *Description; const char **Subjects; int SubjectsLen; jsRetentionPolicy Retention; int64_t MaxConsumers; int64_t MaxMsgs; int64_t MaxBytes; int64_t MaxAge; int64_t MaxMsgsPerSubject; int32_t MaxMsgSize; jsDiscardPolicy Discard; jsStorageType Storage; int64_t Replicas; bool NoAck; const char *Template; int64_t Duplicates; jsPlacement *Placement; jsStreamSource *Mirror; jsStreamSource **Sources; int SourcesLen; bool Sealed; ///< Seal a stream so no messages can get our or in. bool DenyDelete; ///< Restrict the ability to delete messages. bool DenyPurge; ///< Restrict the ability to purge messages. /** * Allows messages to be placed into the system and purge * all older messages using a special message header. */ bool AllowRollup; // Allow republish of the message after being sequenced and stored. jsRePublish *RePublish; // Allow higher performance, direct access to get individual messages. E.g. KeyValue bool AllowDirect; // Allow higher performance and unified direct access for mirrors as well. bool MirrorDirect; // Allow KV like semantics to also discard new on a per subject basis bool DiscardNewPerSubject; } jsStreamConfig; /** * Information about messages that have been lost */ typedef struct jsLostStreamData { uint64_t *Msgs; int MsgsLen; uint64_t Bytes; } jsLostStreamData; /** * This indicate that the given `Subject` in a stream contains `Msgs` messages. * * @see jsStreamStateSubjects */ typedef struct jsStreamStateSubject { const char *Subject; uint64_t Msgs; } jsStreamStateSubject; /** * List of subjects optionally returned in the stream information request. * * This structure indicates the number of elements in the list, that is, * the list contains `Count` #jsStreamStateSubject elements. * * To get this list in #jsStreamState, you have to ask for it through #jsOptions. * * \code{.unparsed} * jsStreamInfo *si = NULL; * jsOptions o; * * jsOptions_Init(&o); * o.Stream.Info.SubjectsFilter = "foo.>"; * s = js_GetStreamInfo(&si, js, "MY_STREAM", &o, &jerr); * * // handle errors and assume si->State.Subjects is not NULL * * for (i=0; iState.Subjects->Count; i++) * { * jsStreamStateSubject *subj = &(si->State.Subjects->List[i]); * printf("Subject=%s Messages count=%d\n", subj->Subject, (int) subj->Msgs); * } * \endcode * * @see jsStreamStateSubject * @see js_GetStreamInfo * @see jsOptions.Stream.Info.SubjectsFilter */ typedef struct jsStreamStateSubjects { jsStreamStateSubject *List; int Count; } jsStreamStateSubjects; /** * Information about the given stream * * \note `FirstTime` and `LastTime` are message timestamps expressed as the number * of nanoseconds passed since 00:00:00 UTC Thursday, 1 January 1970. */ typedef struct jsStreamState { uint64_t Msgs; uint64_t Bytes; uint64_t FirstSeq; int64_t FirstTime; ///< UTC time expressed as number of nanoseconds since epoch. uint64_t LastSeq; int64_t LastTime; ///< UTC time expressed as number of nanoseconds since epoch. int64_t NumSubjects; jsStreamStateSubjects *Subjects; uint64_t NumDeleted; uint64_t *Deleted; int DeletedLen; jsLostStreamData *Lost; int64_t Consumers; } jsStreamState; /** * Information about all the peers in the cluster that * are supporting the stream or consumer. */ typedef struct jsPeerInfo { char *Name; bool Current; bool Offline; int64_t Active; uint64_t Lag; } jsPeerInfo; /** * Information about the underlying set of servers * that make up the stream or consumer. */ typedef struct jsClusterInfo { char *Name; char *Leader; jsPeerInfo **Replicas; int ReplicasLen; } jsClusterInfo; /** * Information about an upstream stream source. */ typedef struct jsStreamSourceInfo { char *Name; jsExternalStream *External; uint64_t Lag; int64_t Active; } jsStreamSourceInfo; /** * Information about an alternate stream represented by a mirror. */ typedef struct jsStreamAlternate { const char *Name; const char *Domain; const char *Cluster; } jsStreamAlternate; /** * Configuration and current state for this stream. * * \note `Created` is the timestamp when the stream was created, expressed as * the number of nanoseconds passed since 00:00:00 UTC Thursday, 1 January 1970. */ typedef struct jsStreamInfo { jsStreamConfig *Config; int64_t Created; ///< UTC time expressed as number of nanoseconds since epoch. jsStreamState State; jsClusterInfo *Cluster; jsStreamSourceInfo *Mirror; jsStreamSourceInfo **Sources; int SourcesLen; jsStreamAlternate **Alternates; int AlternatesLen; } jsStreamInfo; /** * List of stream information objects returned by #js_Streams * * \note Once done, the list should be destroyed calling #jsStreamInfoList_Destroy * * @see jsStreamInfoList_Destroy */ typedef struct jsStreamInfoList { jsStreamInfo **List; int Count; } jsStreamInfoList; /** * List of stream names returned by #js_StreamNames * * \note Once done, the list should be destroyed calling #jsStreamNamesList_Destroy * * @see jsStreamNamesList_Destroy */ typedef struct jsStreamNamesList { char **List; int Count; } jsStreamNamesList; /** * Configuration of a JetStream consumer. * * In order to add a consumer, a configuration needs to be set. * The typical usage would be to initialize all required objects on the stack * and configure them, then pass the pointer to the configuration to * #js_AddConsumer. * * \note `OptStartTime` needs to be expressed as the number of nanoseconds * passed since 00:00:00 UTC Thursday, 1 January 1970. * * \note The strings are applications owned and will not be freed by the library. * * \note `SampleFrequency` is a sampling value, represented as a string such as "50" * for 50%, that causes the server to produce advisories for consumer ack metrics. * * \note `Durable` cannot contain the character ".". * * \note `HeadersOnly` means that the subscription will not receive any message payload, * instead, it will receive only messages headers (if present) with the addition of * the header #JSMsgSize ("Nats-Msg-Size"), whose value is the payload size. * * @see jsConsumerConfig_Init * * \code{.unparsed} * jsConsumerInfo *ci = NULL; * jsConsumerConfig cc; * * jsConsumerConfig_Init(&cc); * cc.Durable = "MY_DURABLE"; * cc.DeliverSubject = "foo"; * cc.DeliverPolicy = js_DeliverNew; * * s = js_AddConsumer(&ci, js, &cc, NULL, &jerr); * \endcode */ typedef struct jsConsumerConfig { const char *Name; const char *Durable; const char *Description; jsDeliverPolicy DeliverPolicy; uint64_t OptStartSeq; int64_t OptStartTime; ///< UTC time expressed as number of nanoseconds since epoch. jsAckPolicy AckPolicy; int64_t AckWait; int64_t MaxDeliver; int64_t *BackOff; ///< Redelivery durations expressed in nanoseconds int BackOffLen; const char *FilterSubject; jsReplayPolicy ReplayPolicy; uint64_t RateLimit; const char *SampleFrequency; int64_t MaxWaiting; int64_t MaxAckPending; bool FlowControl; int64_t Heartbeat; ///< Heartbeat interval expressed in number of nanoseconds. bool HeadersOnly; // Pull based options. int64_t MaxRequestBatch; ///< Maximum Pull Consumer request batch size. int64_t MaxRequestExpires; ///< Maximum Pull Consumer request expiration, expressed in number of nanoseconds. int64_t MaxRequestMaxBytes; ///< Maximum Pull Consumer request maximum bytes. // Push based options. const char *DeliverSubject; const char *DeliverGroup; // Ephemeral inactivity threshold. int64_t InactiveThreshold; ///< How long the server keeps an ephemeral after detecting loss of interest, expressed in number of nanoseconds. // Generally inherited by parent stream and other markers, now can be configured directly. int64_t Replicas; // Force memory storage. bool MemoryStorage; } jsConsumerConfig; /** * This represents a consumer sequence mismatch between the server and client * views. * * This can help applications find out if messages have been missed. Without * this and during a disconnect, it would be possible that a subscription * is not aware that it missed messages from the server. When acknowledgment * mode is other than #js_AckNone, messages would ultimately be redelivered, * but for #js_AckNone, they would not. But even with an acknowledgment mode * this may help finding sooner that something went wrong and let the application * decide if it wants to recreate the subscription starting at a given * sequence. * * The gap of missing messages could be calculated as `ConsumerServer-ConsumerClient`. * * @see natsSubscription_GetSequenceMismatch */ typedef struct jsConsumerSequenceMismatch { uint64_t Stream; ///< This is the stream sequence that the application should resume from. uint64_t ConsumerClient; ///< This is the consumer sequence that was last received by the library. uint64_t ConsumerServer; ///< This is the consumer sequence last sent by the server. } jsConsumerSequenceMismatch; /** * JetStream subscribe options. * * These are options that you can provide to JetStream subscribe APIs. * * The common usage will be to initialize a structure on the stack by * calling #jsSubOptions_Init. Note that strings are owned by * the application and need to be valid for the duration of the API * call this object is passed to. * * \note It is the user responsibility to free the strings if they * have been allocated. * * @see jsSubOptions_Init */ typedef struct jsSubOptions { /** * If specified, the library will only bind to this stream, * otherwise, the library communicates with the server to * get the stream name that has the matching subject given * to the #js_Subscribe family calls. */ const char *Stream; ///< If specified, the consumer will be bound to this stream name. /** * If specified, the #js_Subscribe family calls will only * attempt to create a subscription for this matching consumer. * * That is, the consumer should exist prior to the call, * either created by the application calling #js_AddConsumer * or it should have been created with some other tools * such as the NATS cli. */ const char *Consumer; ///< If specified, the subscription will be bound to an existing consumer from the `Stream` without attempting to create. /** * If specified, the low level NATS subscription will be a * queue subscription, which means that the load on the * delivery subject will be balanced across multiple members * of the same queue group. * * This makes sense only if the delivery subject in the * `Config` field of #jsSubOptions is the same for the * members of the same group. * * When no `Durable` name is specified in the `Config` block, then the * queue name will be used as the consumer's durable name. In this case, * the queue name cannot contain the character ".". */ const char *Queue; ///< Queue name for queue subscriptions. /** * This has meaning only for asynchronous subscriptions, * and only if the consumer's acknowledgment mode is * other than #js_AckNone. * * For asynchronous subscriptions, the default behavior * is for the library to acknowledge the message once * the user callback returns. * * This option allows you to take control of when the * message should be acknowledged. */ bool ManualAck; ///< If true, the user will have to acknowledge the messages. /** * This allows the user to fully configure the JetStream * consumer. */ jsConsumerConfig Config; ///< Consumer configuration. /** * This will create a fifo ephemeral consumer for in order delivery of * messages. There are no redeliveries and no acks. * Flow control and heartbeats are required and set by default, but * the heartbeats value can be overridden in the consumer configuration. */ bool Ordered; ///< If true, this will be an ordered consumer. } jsSubOptions; /** * Includes the consumer and stream sequence info from a JetStream consumer. */ typedef struct jsSequencePair { uint64_t Consumer; uint64_t Stream; } jsSequencePair; /** * Has both the consumer and the stream sequence and last activity. */ typedef struct jsSequenceInfo { uint64_t Consumer; uint64_t Stream; int64_t Last; ///< UTC time expressed as number of nanoseconds since epoch. } jsSequenceInfo; /** * Configuration and current state for this consumer. * * \note `Created` is the timestamp when the consumer was created, expressed as the number * of nanoseconds passed since 00:00:00 UTC Thursday, 1 January 1970. */ typedef struct jsConsumerInfo { char *Stream; char *Name; int64_t Created; ///< UTC time expressed as number of nanoseconds since epoch. jsConsumerConfig *Config; jsSequenceInfo Delivered; jsSequenceInfo AckFloor; int64_t NumAckPending; int64_t NumRedelivered; int64_t NumWaiting; uint64_t NumPending; jsClusterInfo *Cluster; bool PushBound; } jsConsumerInfo; /** * List of consumers information objects returned by #js_Consumers * * \note Once done, the list should be destroyed calling #jsConsumerInfoList_Destroy * * @see jsStreamInfoList_Destroy */ typedef struct jsConsumerInfoList { jsConsumerInfo **List; int Count; } jsConsumerInfoList; /** * List of consumer names returned by #js_ConsumerNames * * \note Once done, the list should be destroyed calling #jsConsumerNamesList_Destroy * * @see jsConsumerNamesList_Destroy */ typedef struct jsConsumerNamesList { char **List; int Count; } jsConsumerNamesList; /** * Reports on API calls to JetStream for this account. */ typedef struct jsAPIStats { uint64_t Total; uint64_t Errors; } jsAPIStats; /** * Includes the JetStream limits of the current account. */ typedef struct jsAccountLimits { int64_t MaxMemory; int64_t MaxStore; int64_t MaxStreams; int64_t MaxConsumers; int64_t MaxAckPending; int64_t MemoryMaxStreamBytes; int64_t StoreMaxStreamBytes; bool MaxBytesRequired; } jsAccountLimits; typedef struct jsTier { const char *Name; uint64_t Memory; uint64_t Store; int64_t Streams; int64_t Consumers; jsAccountLimits Limits; } jsTier; /** * Information about the JetStream usage from the current account. */ typedef struct jsAccountInfo { uint64_t Memory; uint64_t Store; int64_t Streams; int64_t Consumers; char *Domain; jsAPIStats API; jsAccountLimits Limits; jsTier **Tiers; int TiersLen; } jsAccountInfo; /** * This represents the JetStream metadata associated with received messages. * * @see natsMsg_GetMetaData * @see jsMsgMetaData_Destroy * */ typedef struct jsMsgMetaData { jsSequencePair Sequence; uint64_t NumDelivered; uint64_t NumPending; int64_t Timestamp; char *Stream; char *Consumer; char *Domain; } jsMsgMetaData; /** * Ack received after successfully publishing a message. */ typedef struct jsPubAck { char *Stream; uint64_t Sequence; char *Domain; bool Duplicate; } jsPubAck; /** * Publish acknowledgment failure that will be passed to the optional * #jsPubAckErrHandler callback. */ typedef struct jsPubAckErr { natsMsg *Msg; natsStatus Err; jsErrCode ErrCode; const char *ErrText; } jsPubAckErr; #ifndef BUILD_IN_DOXYGEN // Forward declarations typedef void (*jsPubAckErrHandler)(jsCtx *js, jsPubAckErr *pae, void *closure); typedef void (*jsPubAckHandler)(jsCtx *js, natsMsg *msg, jsPubAck *pa, jsPubAckErr *pae, void *closure); #endif /** * Options for the js_DirectGetMsg() call, which retrieves a message * from any server (not only the leader) as long as the stream has * been created with a AllowDirect option. * * Note that some options are mutually exclusive but are not checked * byt the library. The server will reject invalid requests and * the library will return the error returned from the server. */ typedef struct jsDirectGetMsgOptions { uint64_t Sequence; ///< Get the message at this sequence const char *NextBySubject; ///< Get the next message (based on sequence) for that subject const char *LastBySubject; ///< Get the last message on that subject } jsDirectGetMsgOptions; /** * Options for the natsSubscription_FetchRequest() call, which is * similar to natsSubscription_Fetch() but gives more control in * the configuration of the fetch. */ typedef struct jsFetchRequest { int64_t Expires; ///< Expiration of the request, expressed in nanoseconds int Batch; ///< Maximum number of messages to be received (see MaxBytes) int64_t MaxBytes; ///< Maximum bytes for the request (request complete based on whichever Batch or MaxBytes comes first) bool NoWait; ///< Will not wait if the request cannot be completed int64_t Heartbeat; ///< Have server sends heartbeats to help detect communication failures } jsFetchRequest; /** * JetStream context options. * * Initialize the object with #jsOptions_Init. */ typedef struct jsOptions { const char *Prefix; ///< JetStream prefix, default is "$JS.API" const char *Domain; ///< Domain changes the domain part of JetSteam API prefix. int64_t Wait; ///< Amount of time (in milliseconds) to wait for various JetStream API requests, default is 5000 ms (5 seconds). /** * Publish Async options */ struct jsOptionsPublishAsync { int64_t MaxPending; ///< Maximum outstanding asynchronous publishes that can be inflight at one time. // If jsPubAckHandler is specified, the callback will be invoked // for every asynchronous published message, either as a positive // result, or with the error encountered when publishing that // message. If this callback is specified, ErrHandler (see below) // will be ignored. jsPubAckHandler AckHandler; ///< Callback invoked for each asynchronous published message. void *AckHandlerClosure; ///< Closure (or user data) passed to #jsPubAckHandler callback. // This callback is invoked for messages published asynchronously // when an error is returned by the server or if the library has // timed-out waiting for an acknowledgment back from the server // (if publish uses the jsPubOptions.MaxWait). jsPubAckErrHandler ErrHandler; ///< Callback invoked when error encountered publishing a given message. void *ErrHandlerClosure; ///< Closure (or user data) passed to #jsPubAckErrHandler callback. int64_t StallWait; ///< Amount of time (in milliseconds) to wait in a PublishAsync call when there is MaxPending inflight messages, default is 200 ms. } PublishAsync; /** * Advanced stream options * * * `Purge` for advanced purge options. * * `Info` for advanced information retrieval options. */ struct jsOptionsStream { /** * Advanced stream purge options * * * `Subject` will filter the purge request to only messages that match the subject, which can have wildcards.
* * `Sequence` will purge up to but not including this sequence and can be combined with subject filtering.
* * `Keep` will specify how many messages to keep and can be combined with subject filtering.
* * \note `Sequence` and `Keep` are mutually exclusive, so both can not be set at the same time. */ struct jsOptionsStreamPurge { const char *Subject; ///< This is the subject to match against messages for the purge command. uint64_t Sequence; ///< Purge up to but not including sequence. uint64_t Keep; ///< Number of messages to keep. } Purge; ///< Optional stream purge options. /** * Advance stream information retrieval options */ struct jsOptionsStreamInfo { bool DeletedDetails; ///< Get the list of deleted message sequences. const char *SubjectsFilter; ///< Get the list of subjects in this stream. } Info; ///< Optional stream information retrieval options. } Stream; ///< Optional stream options. } jsOptions; /** * The KeyValue store object. */ typedef struct __kvStore kvStore; /** * The KeyValue entry object. */ typedef struct __kvEntry kvEntry; /** * The KeyValue status object. */ typedef struct __kvStatus kvStatus; /** * The KeyValue watcher object. */ typedef struct __kvWatcher kvWatcher; /** * Determines the type of operation of a #kvEntry */ typedef enum { kvOp_Unknown = 0, kvOp_Put, kvOp_Delete, kvOp_Purge, } kvOperation; /** * KeyValue configuration object. * * Initialize the object with #kvConfig_Init. */ typedef struct kvConfig { const char *Bucket; const char *Description; int32_t MaxValueSize; uint8_t History; int64_t TTL; int64_t MaxBytes; jsStorageType StorageType; int Replicas; jsRePublish *RePublish; jsStreamSource *Mirror; jsStreamSource **Sources; int SourcesLen; } kvConfig; /** * KeyValue watcher options object. * * Initialize the object with #kvWatchOptions_Init */ typedef struct kvWatchOptions { bool IgnoreDeletes; bool IncludeHistory; bool MetaOnly; int64_t Timeout; ///< How long to wait (in milliseconds) for some operations to complete. } kvWatchOptions; /** * KeyValue purge options object. * * Initialize the object with #kvPurgeOptions_Init */ typedef struct kvPurgeOptions { // How long to wait (in milliseconds) for some operations to complete. int64_t Timeout; // When calling kvStore_PurgeDeletes(), all keys that have a delete or // purge marker as the last entry are gathered and then those keys // are purged of their content, including the marker. // Starting with NATS C client v3.3.0, if this option is not specified, // only the markers older than 30 minutes will be deleted. Use this // option to set the limit or a negative value to force removal of // markers regardless of their age. // The value is expressed as a time in nanoseconds. int64_t DeleteMarkersOlderThan; } kvPurgeOptions; /** \brief A list of KeyValue store entries. * * Used by some APIs which return a list of #kvEntry objects. * * Those APIs will not create the object, but instead initialize * the object. * * Typically, the user will define the object on the stack and * pass a pointer to this object to APIs that require a pointer * to a #kvEntryList object. * * Similarly, calling #kvEntryList_Destroy will call #kvEntry_Destroy * on entries in the list, free the array containing pointers * to the entries, but not free the #kvEntryList object itself. * * @see kvEntryList_Destroy */ typedef struct kvEntryList { kvEntry **Entries; int Count; } kvEntryList; /** \brief A list of KeyValue store keys. * * Used by some APIs which return a list of key names. * * Those APIs will not create the object, but instead initialize * the object. * * Typically, the user will define the object on the stack and * pass a pointer to this object to APIs that require a pointer * to a #kvKeysList object. * * Similarly, calling #kvKeysList_Destroy will free key strings * in the list, free the array containing pointers to the keys, * but not free the #kvKeysList object itself. * * @see kvKeysList_Cleanup */ typedef struct kvKeysList { char **Keys; int Count; } kvKeysList; #if defined(NATS_HAS_STREAMING) /** \brief A connection to a `NATS Streaming Server`. * * A #stanConnection represents a connection to a `NATS Streaming Server`. */ typedef struct __stanConnection stanConnection; /** \brief Interest on a given channel. * * A #stanSubscription represents interest in a given channel. */ typedef struct __stanSubscription stanSubscription; /** \brief The Streaming message. * * #stanMsg is the object passed to the subscriptions' message callbacks. */ typedef struct __stanMsg stanMsg; /** \brief Way to configure a #stanConnection. * * Options can be used to create a customized #stanConnection. */ typedef struct __stanConnOptions stanConnOptions; /** \brief Way to configure a #stanSubscription. * * Options can be used to create a customized #stanSubscription. */ typedef struct __stanSubOptions stanSubOptions; #endif /** @} */ // end of typesGroup // // Callbacks. // /** \defgroup callbacksGroup Callbacks * * NATS Callbacks. * @{ */ /** \brief Callback used to deliver messages to the application. * * This is the callback that one provides when creating an asynchronous * subscription. The library will invoke this callback for each message * arriving through the subscription's connection. * * \warning If this callback is setup for a subject that is used as the reply * subject to #natsConnection_PublishRequest calls (and its variants), it * is possible to get an empty message with a header "Status" with value * "503" that is sent by the server when there were no responders on the * request's subject. Use #natsMsg_IsNoResponders to know if that is the case. * * @see natsConnection_Subscribe() * @see natsConnection_QueueSubscribe() * @see natsMsg_IsNoResponders() */ typedef void (*natsMsgHandler)( natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure); /** \brief Callback used to notify the user of asynchronous connection events. * * This callback is used for asynchronous events such as disconnected * and closed connections. * * @see natsOptions_SetClosedCB() * @see natsOptions_SetDisconnectedCB() * @see natsOptions_SetReconnectedCB() * * \warning Such callback is invoked from a dedicated thread and the state * of the connection that triggered the event may have changed since * that event was generated. */ typedef void (*natsConnectionHandler)( natsConnection *nc, void *closure); /** \brief Callback used to notify the user of errors encountered while processing * inbound messages. * * This callback is used to process asynchronous errors encountered while processing * inbound messages, such as #NATS_SLOW_CONSUMER. */ typedef void (*natsErrHandler)( natsConnection *nc, natsSubscription *subscription, natsStatus err, void *closure); /** \brief Attach this connection to the external event loop. * * After a connection has (re)connected, this callback is invoked. It should * perform the necessary work to start polling the given socket for READ events. * * @param userData location where the adapter implementation will store the * object it created and that will later be passed to all other callbacks. If * `*userData` is not `NULL`, this means that this is a reconnect event. * @param loop the event loop (as a generic void*) this connection is being * attached to. * @param nc the connection being attached to the event loop. * @param socket the socket to poll for read/write events. */ typedef natsStatus (*natsEvLoop_Attach)( void **userData, void *loop, natsConnection *nc, natsSock socket); /** \brief Read event needs to be added or removed. * * The `NATS` library will invoke this callback to indicate if the event * loop should start (`add is `true`) or stop (`add` is `false`) polling * for read events on the socket. * * @param userData the pointer to an user object created in #natsEvLoop_Attach. * @param add `true` if the event library should start polling, `false` otherwise. */ typedef natsStatus (*natsEvLoop_ReadAddRemove)( void *userData, bool add); /** \brief Write event needs to be added or removed. * * The `NATS` library will invoke this callback to indicate if the event * loop should start (`add is `true`) or stop (`add` is `false`) polling * for write events on the socket. * * @param userData the pointer to an user object created in #natsEvLoop_Attach. * @param add `true` if the event library should start polling, `false` otherwise. */ typedef natsStatus (*natsEvLoop_WriteAddRemove)( void *userData, bool add); /** \brief Detach from the event loop. * * The `NATS` library will invoke this callback to indicate that the connection * no longer needs to be attached to the event loop. User can cleanup some state. * * @param userData the pointer to an user object created in #natsEvLoop_Attach. */ typedef natsStatus (*natsEvLoop_Detach)( void *userData); /** \brief Callback used to fetch and return account signed user JWT. * * This handler is invoked when connecting and reconnecting. It should * return the user JWT that will be sent to the server. * * The user JWT is returned as a string that is allocated by the user and is * freed by the library after the handler is invoked. * * If the user is unable to return the JWT, a status other than `NATS_OK` should * be returned (we recommend `NATS_ERR`). A custom error message can be returned * through `customErrTxt`. The user must allocate the memory for this error * message and the library will free it after the invocation of the handler. * * \warning There may be repeated invocations of this handler for a given connection * so it is crucial to always return a copy of the user JWT maintained by the * application, since again, the library will free the memory pointed by `userJWT` * after each invocation of this handler. * * @see natsOptions_SetUserCredentialsCallbacks() * @see natsOptions_SetUserCredentialsFromFiles() */ typedef natsStatus (*natsUserJWTHandler)( char **userJWT, char **customErrTxt, void *closure); /** \brief Callback used to sign a nonce sent by the server. * * This handler is invoked when connecting and reconnecting. It should * sign the given `nonce` and return a raw signature through `signature` and * specify how many characters the signature has using `signatureLength`. * * The memory pointed by `signature` must be allocated by the user and * will be freed by the library after each invocation of this handler. * * If the user is unable to sign, a status other than `NATS_OK` (we recommend * `NATS_ERR`) should be returned. A custom error message can be returned * through `customErrTxt`. The user must allocate the memory for this error * message and the library will free it after the invocation of this handler. * * The library will base64 encode this raw signature and send that to the server. * * \warning There may be repeated invocations of this handler for a given connection * so it is crucial to always return a copy of the signature, since again, * the library will free the memory pointed by `signature` after each invocation * of this handler. * * @see natsOptions_SetUserCredentialsCallbacks() * @see natsOptions_SetUserCredentialsFromFiles() * @see natsOptions_SetNKey() */ typedef natsStatus (*natsSignatureHandler)( char **customErrTxt, unsigned char **signature, int *signatureLength, const char *nonce, void *closure); /** \brief Callback used to build a token on connections and reconnections. * * This is the function that one provides to build a different token at each reconnect. * * @see natsOptions_SetTokenHandler() * * \warning Such callback is invoked synchronously from the connection thread. */ typedef const char* (*natsTokenHandler)(void *closure); /** \brief Callback used to notify that an object lifecycle is complete. * * Currently used for asynchronous #natsSubscription objects. When set, this callback will * be invoked after the subscription is closed and the message handler has returned. * * @see natsSubscription_SetOnCompleteCB() */ typedef void (*natsOnCompleteCB)(void *closure); /** \brief Callback used to specify how long to wait between reconnects. * * This callback is used to get from the user the desired delay the library * should pause before attempting to reconnect again. Note that this is invoked * after the library tried the whole list of URLs and failed to reconnect. * * \note This callback is invoked from the connection reconnect thread and waits * for user input. It should not block and instead quickly return the desired * reconnect delay. * The state of the connection is disconnected when this callback is invoked. * Not much can be done with the passed connection, but user can call * #natsConnection_Close() if desired. This will abort the reconnect attempts * and close the connection. * * @param nc the pointer to the #natsConnection invoking this handler. * @param attempts the number of times the library tried the whole list of server URLs. * @param closure an optional pointer to a user defined object that was specified when * registering the callback. * @return the number of milliseconds to wait before trying to reconnect. */ typedef int64_t (*natsCustomReconnectDelayHandler)(natsConnection *nc, int attempts, void *closure); #ifdef BUILD_IN_DOXYGEN /** \brief Callback used to process asynchronous publish errors from JetStream. * * Callback used to process asynchronous publish errors from JetStream #js_PublishAsync * and #js_PublishMsgAsync calls. The provided #jsPubAckErr object gives the user * access to the encountered error along with the original message sent to the server * for possible restransmitting. * * \note If the message is resent, the library will not destroy the original * message and once again take ownership of it. To resend the message, do the * following so that the library knows not to destroy the message (since the * call will clear the `Msg` field from the #jsPubAckErr object). * * \code{.unparsed} * void myPAECallback(jsCtx *js, jsPubAckErr *pae, void* closure) * { * ... * // Resend the message * js_PublishMsgAsync(js, &(pae->Msg), NULL); * } * \endcode * * \warning The #jsPubAckErr object and its content will be invalid as * soon as the callback returns. * * \warning Unlike a NATS message callback, the user does not have to destroy * the original NATS message (present in the #jsPubAckErr object), the * library will do it. * * @param js the pointer to the #jsCtx object. * @param pae the pointer to the #jsPubAckErr object. * @param closure an optional pointer to a user defined object that was specified when * registering the callback. */ typedef void (*jsPubAckErrHandler)(jsCtx *js, jsPubAckErr *pae, void *closure); /** \brief Callback used to process asynchronous publish responses from JetStream. * * Callback used to process asynchronous publish responses (positive and negatives) * from JetStream #js_PublishAsync and #js_PublishMsgAsync calls. The provided * #jsPubAck or #jsPubAckErr objects give the user access to the successful * acknowledgment from the server or the encountered error along with the original * message sent to the server for possible restransmitting. * * \warning The user is responsible for destroying the message. If the message * is resent using the #js_PublishMsgAsync call, the library is taking ownership * of the message and calling #natsMsg_Destroy will have no effect because * the pointer will have been set to `NULL`. So it is recommended to always * call #natsMsg_Destroy at the end of the function. * * \code{.unparsed} * void myAckHandler(jsCtx *js, natsMsg *msg, jsPubAck *pa, jsPubAckErr *pae, void *closure) * { * if (pa != NULL) * { * // Success case... * } * else if (pae != NULL) * { * // Error case... * // If the application wants to resend the message: * js_PublishMsgAsync(js, &msg, NULL); * } * natsMsg_Destroy(msg); * } * \endcode * * \warning The #jsPubAck and #jsPubAckErr objects and their content will be * invalid as soon as the callback returns. * * @param js the pointer to the #jsCtx object. * @param msg the pointer to the original published #natsMsg. * @param pa the pointer to the #jsPubAck object. * @param pae the pointer to the #jsPubAckErr object. * @param closure an optional pointer to a user defined object that was specified when * registering the callback. */ typedef void (*jsPubAckHandler)(jsCtx *js, natsMsg *msg, jsPubAck *pa, jsPubAckErr *pae, void *closure); #endif #if defined(NATS_HAS_STREAMING) /** \brief Callback used to notify of an asynchronous publish result. * * This is used for asynchronous publishing to provide status of the acknowledgment. * The function will be passed the GUID and any error state. No error means the * message was successfully received by NATS Streaming. * * @see stanConnection_PublishAsync() */ typedef void (*stanPubAckHandler)(const char *guid, const char *error, void *closure); /** \brief Callback used to deliver messages to the application. * * This is the callback that one provides when creating an asynchronous * subscription. The library will invoke this callback for each message * arriving through the subscription's connection. * * @see stanConnection_Subscribe() * @see stanConnection_QueueSubscribe() */ typedef void (*stanMsgHandler)( stanConnection *sc, stanSubscription *sub, const char *channel, stanMsg *msg, void *closure); /** \brief Callback used to notify the user of the permanent loss of the connection. * * This callback is used to notify the user that the connection to the Streaming * server is permanently lost. * */ typedef void (*stanConnectionLostHandler)( stanConnection *sc, const char* errorTxt, void *closure); #endif /** @} */ // end of callbacksGroup // // Functions. // /** \defgroup funcGroup Functions * * NATS Functions. * @{ */ /** \defgroup libraryGroup Library * * Library and helper functions. * @{ */ /** \brief Initializes the library. * * This initializes the library. * * It is invoked automatically when creating a connection, using a default * spin count. However, you can call this explicitly before creating the very * first connection in order for your chosen spin count to take effect. * * \warning You must not call #nats_Open and #nats_Close concurrently. * * @param lockSpinCount The number of times the library will spin trying to * lock a mutex object. */ NATS_EXTERN natsStatus nats_Open(int64_t lockSpinCount); /** \brief Returns the Library's version. * * Returns the version of the library your application is linked with. */ NATS_EXTERN const char* nats_GetVersion(void); /** \brief Returns the Library's version as a number. * * The version is returned as an hexadecimal number. For instance, if the * string version is "1.2.3", the value returned will be: * * > 0x010203 */ NATS_EXTERN uint32_t nats_GetVersionNumber(void); #ifdef BUILD_IN_DOXYGEN /** \brief Check that the header is compatible with the library. * * The version of the header you used to compile your application may be * incompatible with the library the application is linked with. * * This function will check that the two are compatibles. If they are not, * a message is printed and the application will exit. * * @return `true` if the header and library are compatibles, otherwise the * application exits. * * @see nats_GetVersion * @see nats_GetVersionNumber */ NATS_EXTERN bool nats_CheckCompatibility(void); #else #define nats_CheckCompatibility() nats_CheckCompatibilityImpl(NATS_VERSION_REQUIRED_NUMBER, \ NATS_VERSION_NUMBER, \ NATS_VERSION_STRING) NATS_EXTERN bool nats_CheckCompatibilityImpl(uint32_t reqVerNumber, uint32_t verNumber, const char *verString); #endif /** \brief Gives the current time in milliseconds. * * Gives the current time in milliseconds. */ NATS_EXTERN int64_t nats_Now(void); /** \brief Gives the current time in nanoseconds. * * Gives the current time in nanoseconds. When such granularity is not * available, the time returned is still expressed in nanoseconds. */ NATS_EXTERN int64_t nats_NowInNanoSeconds(void); /** \brief Sleeps for a given number of milliseconds. * * Causes the current thread to be suspended for at least the number of * milliseconds. * * @param sleepTime the number of milliseconds. */ NATS_EXTERN void nats_Sleep(int64_t sleepTime); /** \brief Returns the calling thread's last known error. * * Returns the calling thread's last known error. This can be useful when * #natsConnection_Connect fails. Since no connection object is returned, * you would not be able to call #natsConnection_GetLastError. * * @param status if not `NULL`, this function will store the last error status * in there. * @return the thread local error string. * * \warning Do not free the string returned by this function. */ NATS_EXTERN const char* nats_GetLastError(natsStatus *status); /** \brief Returns the calling thread's last known error stack. * * Copies the calling thread's last known error stack into the provided buffer. * If the buffer is not big enough, #NATS_INSUFFICIENT_BUFFER is returned. * * @param buffer the buffer into the stack is copied. * @param bufLen the size of the buffer */ NATS_EXTERN natsStatus nats_GetLastErrorStack(char *buffer, size_t bufLen); /** \brief Prints the calling thread's last known error stack into the file. * * This call prints the calling thread's last known error stack into the file `file`. * It first prints the error status and the error string, then the stack. * * Here is an example for a call: * * \code{.unparsed} * Error: 29 - SSL Error - (conn.c:565): SSL handshake error: sslv3 alert bad certificate * Stack: (library version: 1.2.3-beta) * 01 - _makeTLSConn * 02 - _checkForSecure * 03 - _processExpectedInfo * 04 - _processConnInit * 05 - _connect * 06 - natsConnection_Connect * \endcode * * @param file the file the stack is printed to. */ NATS_EXTERN void nats_PrintLastErrorStack(FILE *file); /** \brief Sets the maximum size of the global message delivery thread pool. * * Normally, each asynchronous subscriber that is created has its own * message delivery thread. The advantage is that it reduces lock * contentions, therefore improving performance.
* However, if an application creates many subscribers, this is not scaling * well since the process would use too many threads. * * The library has a thread pool that can perform message delivery. If * a connection is created with the proper option set * (#natsOptions_UseGlobalMessageDelivery), then this thread pool * will be responsible for delivering the messages. The thread pool is * lazily initialized, that is, no thread is used as long as no subscriber * (requiring global message delivery) is created. * * Each subscriber will be attached to a given worker on the pool so that * message delivery order is guaranteed. * * This call allows you to set the maximum size of the pool. * * \note At this time, a pool does not shrink, but the caller will not get * an error when calling this function with a size smaller than the current * size. * * @see natsOptions_UseGlobalMessageDelivery() * @see \ref envVariablesGroup * * @param max the maximum size of the pool. */ NATS_EXTERN natsStatus nats_SetMessageDeliveryPoolSize(int max); /** \brief Release thread-local memory possibly allocated by the library. * * This needs to be called on user-created threads where NATS calls are * performed. This does not need to be called in threads created by * the library. For instance, do not call this function in the * message handler that you specify when creating a subscription. * * Also, you do not need to call this in an user thread (or the main) * if you are calling nats_Close() there. */ NATS_EXTERN void nats_ReleaseThreadMemory(void); /** \brief Signs a given text using the provided private key. * * The key is the encoded string representation of the private key, or seed. * This is what you get when generating an NKey using NATS tooling. * * The input is a string, generally the nonce sent by the server when * accepting a connection. * * This function signs the input and returns the signature through the * output arguments. This call allocates memory necessary to hold * the signature. If this is used as part of the signature callback * passed to #natsOptions_SetNKey(), then the memory will be automatically * freed by the library after the signature has been inserted in the CONNECT * protocol. * If this function is used outside of this context, it is the user responsibility * to free the allocated memory when no longer needed. * * @see natsOptions_SetNKey() * * @param encodedSeed the string encoded private key, also known as seed. * @param input the input to be signed. * @param signature the memory location of allocated memory containing the signed input. * @param signatureLength the size of the allocated signature. */ NATS_EXTERN natsStatus nats_Sign(const char *encodedSeed, const char *input, unsigned char **signature, int *signatureLength); /** \brief Tear down the library. * * Releases memory used by the library. * * For this to take effect, all NATS objects that you have created * must first be destroyed. * * This call does not block and it is possible that the library * is not unloaded right away if there are still internal threads referencing * it, so calling #nats_Open() right away may fail. If you want to ensure * that the library is fully unloaded, call #nats_CloseAndWait() instead. * * \note There are still a small number of thread local keys and a mutex * that are not freed until the application exit (in which case a final cleanup * is executed). * * \warning You must not call #nats_Open and #nats_Close concurrently. * * @see nats_CloseAndWait() */ NATS_EXTERN void nats_Close(void); /** \brief Tear down the library and wait for all resources to be released. * * Similar to #nats_Close() except that this call will make sure that all * references to the library are decremented before returning (up to the * given timeout). Internal threads (such as subscriptions dispatchers, * etc..) hold a reference to the library. Only when all references have * been released that this call will return. It means that you must call * all the "destroy" calls before calling this function, otherwise it will * block forever (or up to given timeout). * * For instance, this code would "deadlock": * \code{.unparsed} * natsConnection_ConnectTo(&nc, NATS_DEFAULT_URL); * nats_CloseWait(0); * natsConnection_Destroy(nc); * \endcode * But this would work as expected: * \code{.unparsed} * natsConnection_ConnectTo(&nc, NATS_DEFAULT_URL); * natsConnection_Destroy(nc); * nats_CloseWait(0); * \endcode * The library and other objects (such as connections, subscriptions, etc) * use internal threads. After the destroy call, it is possible or even likely * that some threads are still running, holding references to the library. * Unlike #nats_Close(), which will simply ensure that the library is ultimately * releasing memory, the #nats_CloseAndWait() API will ensure that all those internal * threads have unrolled and that the memory used by the library is released before * returning. * * \note If a timeout is specified, the call may return #NATS_TIMEOUT but the * library is still being tear down and memory will be released. The error is just * to notify you that the operation did not complete in the allotted time. Calling * #nats_Open() in this case (or any implicit opening of the library) may result * in an error since the library may still be in the process of being closed. * * \warning Due to the blocking nature it is illegal to call this from any * NATS thread (such as message or connection callbacks). If trying to do so, * a #NATS_ILLEGAL_STATE error will be returned. * * @see nats_Close() * * @param timeout the maximum time to wait for the library to be closed. If * negative or 0, waits for as long as needed. */ NATS_EXTERN natsStatus nats_CloseAndWait(int64_t timeout); /** @} */ // end of libraryGroup /** \defgroup statusGroup Status * * Functions related to #natsStatus. * @{ */ /** \brief Get the text corresponding to a #natsStatus. * * Returns the static string corresponding to the given status. * * \warning The returned string is a static string, do not attempt to free * it. * * @param s status to get the text representation from. */ NATS_EXTERN const char* natsStatus_GetText(natsStatus s); /** @} */ // end of statusGroup /** \defgroup statsGroup Statistics * * Statistics Functions. * @{ */ /** \brief Creates a #natsStatistics object. * * Creates a statistics object that can be passed to #natsConnection_GetStats(). * * \note The object needs to be destroyed when no longer needed. * * @see #natsStatistics_Destroy() * * @param newStats the location where to store the pointer to the newly created * #natsStatistics object. */ NATS_EXTERN natsStatus natsStatistics_Create(natsStatistics **newStats); /** \brief Extracts the various statistics values. * * Gets the counts out of the statistics object. * * \note You can pass `NULL` to any of the count your are not interested in * getting. * * @see natsConnection_GetStats() * * @param stats the pointer to the #natsStatistics object to get the values from. * @param inMsgs total number of inbound messages. * @param inBytes total size (in bytes) of inbound messages. * @param outMsgs total number of outbound messages. * @param outBytes total size (in bytes) of outbound messages. * @param reconnects total number of times the client has reconnected. */ NATS_EXTERN natsStatus natsStatistics_GetCounts(const natsStatistics *stats, uint64_t *inMsgs, uint64_t *inBytes, uint64_t *outMsgs, uint64_t *outBytes, uint64_t *reconnects); /** \brief Destroys the #natsStatistics object. * * Destroys the statistics object, freeing up memory. * * @param stats the pointer to the #natsStatistics object to destroy. */ NATS_EXTERN void natsStatistics_Destroy(natsStatistics *stats); /** @} */ // end of statsGroup /** \defgroup optsGroup Options * * NATS Options. * @{ */ /** \brief Creates a #natsOptions object. * * Creates a #natsOptions object. This object is used when one wants to set * specific options prior to connecting to the `NATS Server`. * * After making the appropriate natsOptions_Set calls, this object is passed * to the #natsConnection_Connect() call, which will clone this object. After * natsConnection_Connect() returns, modifications to the options object * will not affect the connection. * * \note The object needs to be destroyed when no longer needed.* * * @see natsConnection_Connect() * @see natsOptions_Destroy() * * @param newOpts the location where store the pointer to the newly created * #natsOptions object. */ NATS_EXTERN natsStatus natsOptions_Create(natsOptions **newOpts); /** \brief Sets the URL to connect to. * * Sets the URL of the `NATS Server` the client should try to connect to. * The URL can contain optional user name and password. * * Some valid URLS: * * - nats://localhost:4222 * - nats://user\@localhost:4222 * - nats://user:password\@localhost:4222 * * @see natsOptions_SetServers * @see natsOptions_SetUserInfo * @see natsOptions_SetToken * * @param opts the pointer to the #natsOptions object. * @param url the string representing the URL the connection should use * to connect to the server. * */ /* * The above is for doxygen. The proper syntax for username/password * is without the '\' character: * * nats://localhost:4222 * nats://user@localhost:4222 * nats://user:password@localhost:4222 */ NATS_EXTERN natsStatus natsOptions_SetURL(natsOptions *opts, const char *url); /** \brief Set the list of servers to try to (re)connect to. * * This specifies a list of servers to try to connect (or reconnect) to. * Note that if you call #natsOptions_SetURL() too, the actual list will contain * the one from #natsOptions_SetURL() and the ones specified in this call. * * @see natsOptions_SetURL * @see natsOptions_SetUserInfo * @see natsOptions_SetToken * * @param opts the pointer to the #natsOptions object. * @param servers the array of strings representing the server URLs. * @param serversCount the size of the array. */ NATS_EXTERN natsStatus natsOptions_SetServers(natsOptions *opts, const char** servers, int serversCount); /** \brief Sets the user name/password to use when not specified in the URL. * * Credentials are usually provided through the URL in the form: * nats://foo:bar\@localhost:4222.
* Until now, you could specify URLs in two ways, with #natsOptions_SetServers * or #natsConnection_ConnectTo. The client library would connect (or reconnect) * only to this given list of URLs, so if any of the server in the list required * authentication, you were responsible for providing the appropriate credentials * in the URLs.
*
* However, with cluster auto-discovery, the client library asynchronously receives * URLs of servers in the cluster. These URLs do not contain any embedded credentials. *
* You need to use this function (or #natsOptions_SetToken) to instruct the client * library to use those credentials when connecting to a server that requires * authentication and for which there is no embedded credentials in the URL. * * @see natsOptions_SetToken * @see natsOptions_SetURL * @see natsOptions_SetServers * * @param opts the pointer to the #natsOptions object. * @param user the user name to send to the server during connect. * @param password the password to send to the server during connect. */ NATS_EXTERN natsStatus natsOptions_SetUserInfo(natsOptions *opts, const char *user, const char *password); /** \brief Sets the token to use when not specified in the URL. * * Tokens are usually provided through the URL in the form: * nats://mytoken\@localhost:4222.
* Until now, you could specify URLs in two ways, with #natsOptions_SetServers * or #natsConnection_ConnectTo. The client library would connect (or reconnect) * only to this given list of URLs, so if any of the server in the list required * authentication, you were responsible for providing the appropriate token * in the URLs.
*
* However, with cluster auto-discovery, the client library asynchronously receives * URLs of servers in the cluster. These URLs do not contain any embedded tokens. *
* You need to use this function (or #natsOptions_SetUserInfo) to instruct the client * library to use this token when connecting to a server that requires * authentication and for which there is no embedded token in the URL. * * @see natsOptions_SetUserInfo * @see natsOptions_SetURL * @see natsOptions_SetServers * * @param opts the pointer to the #natsOptions object. * @param token the token to send to the server during connect. */ NATS_EXTERN natsStatus natsOptions_SetToken(natsOptions *opts, const char *token); /** \brief Sets the tokenCb to use whenever a token is needed. * * For use cases where setting a static token through the URL
* or through #natsOptions_SetToken is not desirable.
*
* This function can be used to generate a token whenever the client needs one.
* Some example of use cases: expiring token, credential rotation, ... * * @see natsOptions_SetToken * * @param opts the pointer to the #natsOptions object. * @param tokenCb the tokenCb to use to generate a token to the server during connect. * @param closure a pointer to an user defined object (can be `NULL`). See * the #natsMsgHandler prototype. */ NATS_EXTERN natsStatus natsOptions_SetTokenHandler(natsOptions *opts, natsTokenHandler tokenCb, void *closure); /** \brief Indicate if the servers list should be randomized. * * If 'noRandomize' is true, then the list of server URLs is used in the order * provided by #natsOptions_SetURL() + #natsOptions_SetServers(). Otherwise, the * list is formed in a random order. * * @param opts the pointer to the #natsOptions object. * @param noRandomize if `true`, the list will be used as-is. */ NATS_EXTERN natsStatus natsOptions_SetNoRandomize(natsOptions *opts, bool noRandomize); /** \brief Sets the (re)connect process timeout. * * This timeout, expressed in milliseconds, is used to interrupt a (re)connect * attempt to a `NATS Server`. This timeout is used both for the low level TCP * connect call, and for timing out the response from the server to the client's * initial `PING` protocol. * * @param opts the pointer to the #natsOptions object. * @param timeout the time, in milliseconds, allowed for an individual connect * (or reconnect) to complete. * */ NATS_EXTERN natsStatus natsOptions_SetTimeout(natsOptions *opts, int64_t timeout); /** \brief Sets the name. * * This name is sent as part of the `CONNECT` protocol. There is no default name. * * @param opts the pointer to the #natsOptions object. * @param name the name to set. */ NATS_EXTERN natsStatus natsOptions_SetName(natsOptions *opts, const char *name); /** \brief Sets the secure mode. * * Indicates to the server if the client wants a secure (SSL/TLS) connection. * * The default is `false`. * * @param opts the pointer to the #natsOptions object. * @param secure `true` for a secure connection, `false` otherwise. */ NATS_EXTERN natsStatus natsOptions_SetSecure(natsOptions *opts, bool secure); /** \brief Loads the trusted CA certificates from a file. * * Loads the trusted CA certificates from a file. * * Note that the certificates are added to a SSL context for this #natsOptions * object at the time of this call, so possible errors while loading the * certificates will be reported now instead of when a connection is created. * You can get extra information by calling #nats_GetLastError. * * @param opts the pointer to the #natsOptions object. * @param fileName the file containing the CA certificates. * */ NATS_EXTERN natsStatus natsOptions_LoadCATrustedCertificates(natsOptions *opts, const char *fileName); /** \brief Sets the trusted CA certificates from memory. * * Similar to #natsOptions_LoadCATrustedCertificates expect that instead * of loading from file, this loads from the given memory location. * * If more than one certificate need to be provided, they need to be * concatenated. For instance: * * \code{.unparsed} * const char *certs = * "-----BEGIN CERTIFICATE-----\n" * "MIIGjzCCBHegAwIBAgIJAKT2W9SKY7o4MA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD\n" * (...) * "-----END CERTIFICATE-----\n" * "-----BEGIN CERTIFICATE-----\n" * "MIIXyz...\n" * (...) * "-----END CERTIFICATE-----\n" * \endcode * * @see natsOptions_LoadCATrustedCertificates * * @param opts the pointer to the #natsOptions object. * @param certificates the string containing the concatenated CA certificates. */ NATS_EXTERN natsStatus natsOptions_SetCATrustedCertificates(natsOptions *opts, const char *certificates); /** \brief Loads the certificate chain from a file, using the given key. * * The certificates must be in PEM format and must be sorted starting with * the subject's certificate, followed by intermediate CA certificates if * applicable, and ending at the highest level (root) CA. * * The private key file format supported is also PEM. * * See #natsOptions_LoadCATrustedCertificates regarding error reports. * * @param opts the pointer to the #natsOptions object. * @param certsFileName the file containing the client certificates. * @param keyFileName the file containing the client private key. */ NATS_EXTERN natsStatus natsOptions_LoadCertificatesChain(natsOptions *opts, const char *certsFileName, const char *keyFileName); /** \brief Sets the client certificate and key. * * Similar to #natsOptions_LoadCertificatesChain expect that instead * of loading from file, this loads from the given memory locations. * * @see natsOptions_LoadCertificatesChain() * * @param opts the pointer to the #natsOptions object. * @param cert the memory location containing the client certificates. * @param key the memory location containing the client private key. */ NATS_EXTERN natsStatus natsOptions_SetCertificatesChain(natsOptions *opts, const char *cert, const char *key); /** \brief Sets the list of available ciphers. * * \note This function does not impact TLSv1.3 ciphersuites. * * Sets the list of available ciphers. * Check https://www.openssl.org/docs/man1.1.1/man1/ciphers.html for the * proper syntax. Here is an example: * * > "-ALL:HIGH" * * See #natsOptions_LoadCATrustedCertificates regarding error reports. * * @param opts the pointer to the #natsOptions object. * @param ciphers the ciphers suite. */ NATS_EXTERN natsStatus natsOptions_SetCiphers(natsOptions *opts, const char *ciphers); /** \brief Sets the list of available ciphers for TLSv1.3. * * Sets the list of available ciphers. * Check https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_ciphersuites.html for the * proper syntax. Here is an example: * * > "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" * * See #natsOptions_LoadCATrustedCertificates regarding error reports. * * @param opts the pointer to the #natsOptions object. * @param ciphers the ciphers suite. */ NATS_EXTERN natsStatus natsOptions_SetCipherSuites(natsOptions *opts, const char *ciphers); /** \brief Sets the server certificate's expected hostname. * * If set, the library will check that the hostname in the server * certificate matches the given `hostname`. This will occur when a connection * is created, not at the time of this call. * * @param opts the pointer to the #natsOptions object. * @param hostname the expected server certificate hostname. */ NATS_EXTERN natsStatus natsOptions_SetExpectedHostname(natsOptions *opts, const char *hostname); /** \brief Switch server certificate verification. * * By default, the server certificate is verified. You can disable the verification * by passing true to this function. * * \warning This is fine for tests but use with caution since this is not secure. * * @param opts the pointer to the #natsOptions object. * @param skip set it to true to disable - or skip - server certificate verification. */ NATS_EXTERN natsStatus natsOptions_SkipServerVerification(natsOptions *opts, bool skip); /** \brief Sets the verbose mode. * * Sets the verbose mode. If `true`, sends are echoed by the server with * an `OK` protocol message. * * The default is `false`. * * @param opts the pointer to the #natsOptions object. * @param verbose `true` for a verbose protocol, `false` otherwise. */ NATS_EXTERN natsStatus natsOptions_SetVerbose(natsOptions *opts, bool verbose); /** \brief Sets the pedantic mode. * * Sets the pedantic mode. If `true` some extra checks will be performed * by the server. * * The default is `false` * * @param opts the pointer to the #natsOptions object. * @param pedantic `true` for a pedantic protocol, `false` otherwise. */ NATS_EXTERN natsStatus natsOptions_SetPedantic(natsOptions *opts, bool pedantic); /** \brief Sets the ping interval. * * Interval, expressed in milliseconds, in which the client sends `PING` * protocols to the `NATS Server`. * * @param opts the pointer to the #natsOptions object. * @param interval the interval, in milliseconds, at which the connection * will send `PING` protocols to the server. */ NATS_EXTERN natsStatus natsOptions_SetPingInterval(natsOptions *opts, int64_t interval); /** \brief Sets the limit of outstanding `PING`s without corresponding `PONG`s. * * Specifies the maximum number of `PING`s without corresponding `PONG`s (which * should be received from the server) before closing the connection with * the #NATS_STALE_CONNECTION status. If reconnection is allowed, the client * library will try to reconnect. * * @param opts the pointer to the #natsOptions object. * @param maxPingsOut the maximum number of `PING`s without `PONG`s * (positive number). */ NATS_EXTERN natsStatus natsOptions_SetMaxPingsOut(natsOptions *opts, int maxPingsOut); /** \brief Sets the size of the internal read/write buffers. * * Sets the size, in bytes, of the internal read/write buffers used for * reading/writing data from a socket. * If not specified, or the value is 0, the library will use a default value, * currently set to 32KB. * * @param opts the pointer to the #natsOptions object. * @param ioBufSize the size, in bytes, of the internal buffer for read/write * operations. */ NATS_EXTERN natsStatus natsOptions_SetIOBufSize(natsOptions *opts, int ioBufSize); /** \brief Indicates if the connection will be allowed to reconnect. * * Specifies whether or not the client library should try to reconnect when * losing the connection to the `NATS Server`. * * The default is `true`. * * @param opts the pointer to the #natsOptions object. * @param allow `true` if the connection is allowed to reconnect, `false` * otherwise. */ NATS_EXTERN natsStatus natsOptions_SetAllowReconnect(natsOptions *opts, bool allow); /** \brief Sets the maximum number of reconnect attempts. * * Specifies the maximum number of reconnect attempts. * * @param opts the pointer to the #natsOptions object. * @param maxReconnect the maximum number of reconnects (positive number). */ NATS_EXTERN natsStatus natsOptions_SetMaxReconnect(natsOptions *opts, int maxReconnect); /** \brief Sets the time between reconnect attempts. * * Specifies how long to wait between two reconnect attempts from the same * server. This means that if you have a list with S1,S2 and are currently * connected to S1, and get disconnected, the library will immediately * attempt to connect to S2. If this fails, it will go back to S1, and this * time will wait for `reconnectWait` milliseconds since the last attempt * to connect to S1. * * @param opts the pointer to the #natsOptions object. * @param reconnectWait the time, in milliseconds, to wait between attempts * to reconnect to the same server. */ NATS_EXTERN natsStatus natsOptions_SetReconnectWait(natsOptions *opts, int64_t reconnectWait); /** \brief Set the upper bound of a random delay added to reconnect wait. * * After a disconnect, the library will try to reconnect to any server URLs * in its list (the URLs are either provided by the user or discovered through * gossip protocol). * * After the library failed to reconnect to every server in the list, it * will wait for `reconnectWait` as specified with #natsOptions_SetReconnectWait(). * This option adds some random jitter to the reconnect wait delay. * * This will help minimize the thundering herd phenomenon. For instance, suppose * a server has 1000 connections, all were created at different times, but * have the same reconnect wait option. If this server suddenly stops, then all * connections will detect the failure and initiate a reconnect at the same time. * The issue is even greater when those connections are TLS because of the added * cost of the TLS handshake. * * @see natsOptions_SetReconnectWait() * * @param opts the pointer to the #natsOptions object. * @param jitter the jitter in milliseconds for non TLS connections. * @param jitterTLS the jitter in milliseconds for TLS connections. */ NATS_EXTERN natsStatus natsOptions_SetReconnectJitter(natsOptions *opts, int64_t jitter, int64_t jitterTLS); /** \brief Sets the handler to invoke when the library needs to wait before the next reconnect attempts. * * This callback is invoked after the library tried every URL in the server list * and failed to reconnect. It passes to the user the current number of attempts. * This function shall return the amount of time the library will sleep before attempting * to reconnect again. * * It is strongly recommended that this value contains some jitter to prevent all * connections to attempt reconnecting at the same time. * * \note When using this approach, the reconnect wait as specified by #natsOptions_SetReconnectWait() * is ignored. * * @param opts the pointer to the #natsOptions object. * @param cb the custom reconnect delay handler to invoke. * @param closure a pointer to an user defined object (can be `NULL`). See * the #natsCustomReconnectDelayHandler prototype. */ NATS_EXTERN natsStatus natsOptions_SetCustomReconnectDelay(natsOptions *opts, natsCustomReconnectDelayHandler cb, void *closure); /** \brief Sets the size of the backing buffer used during reconnect. * * Sets the size, in bytes, of the backing buffer holding published data * while the library is reconnecting. Once this buffer has been exhausted, * publish operations will return the #NATS_INSUFFICIENT_BUFFER error. * If not specified, or the value is 0, the library will use a default value, * currently set to 8MB. * * @param opts the pointer to the #natsOptions object. * @param reconnectBufSize the size, in bytes, of the backing buffer for * write operations during a reconnect. */ NATS_EXTERN natsStatus natsOptions_SetReconnectBufSize(natsOptions *opts, int reconnectBufSize); /** \brief Sets the maximum number of pending messages per subscription. * * Specifies the maximum number of inbound messages that can be buffered in the * library, for each subscription, before inbound messages are dropped and * #NATS_SLOW_CONSUMER status is reported to the #natsErrHandler callback (if * one has been set). * * @see natsOptions_SetErrorHandler() * * @param opts the pointer to the #natsOptions object. * @param maxPending the number of messages allowed to be buffered by the * library before triggering a slow consumer scenario. */ NATS_EXTERN natsStatus natsOptions_SetMaxPendingMsgs(natsOptions *opts, int maxPending); /** \brief Sets the error handler for asynchronous events. * * Specifies the callback to invoke when an asynchronous error * occurs. This is used by applications having only asynchronous * subscriptions that would not know otherwise that a problem with the * connection occurred. * * @see natsErrHandler * * @param opts the pointer to the #natsOptions object. * @param errHandler the error handler callback. * @param closure a pointer to an user object that will be passed to * the callback. `closure` can be `NULL`. */ NATS_EXTERN natsStatus natsOptions_SetErrorHandler(natsOptions *opts, natsErrHandler errHandler, void *closure); /** \brief Sets the callback to be invoked when a connection to a server * is permanently lost. * * Specifies the callback to invoke when a connection is terminally closed, * that is, after all reconnect attempts have failed (when reconnection is * allowed). * * @param opts the pointer to the #natsOptions object. * @param closedCb the callback to be invoked when the connection is closed. * @param closure a pointer to an user object that will be passed to * the callback. `closure` can be `NULL`. */ NATS_EXTERN natsStatus natsOptions_SetClosedCB(natsOptions *opts, natsConnectionHandler closedCb, void *closure); /** \brief Sets the callback to be invoked when the connection to a server is * lost. * * Specifies the callback to invoke when a connection to the `NATS Server` * is lost. * * \warning Invocation of this callback is asynchronous, which means that * the state of the connection may have changed when this callback is * invoked. * * @param opts the pointer to the #natsOptions object. * @param disconnectedCb the callback to be invoked when a connection to * a server is lost * @param closure a pointer to an user object that will be passed to * the callback. `closure` can be `NULL`. */ NATS_EXTERN natsStatus natsOptions_SetDisconnectedCB(natsOptions *opts, natsConnectionHandler disconnectedCb, void *closure); /** \brief Sets the callback to be invoked when the connection has reconnected. * * Specifies the callback to invoke when the client library has successfully * reconnected to a `NATS Server`. * * \warning Invocation of this callback is asynchronous, which means that * the state of the connection may have changed when this callback is * invoked. * * @param opts the pointer to the #natsOptions object. * @param reconnectedCb the callback to be invoked when the connection to * a server has been re-established. * @param closure a pointer to an user object that will be passed to * the callback. `closure` can be `NULL`. */ NATS_EXTERN natsStatus natsOptions_SetReconnectedCB(natsOptions *opts, natsConnectionHandler reconnectedCb, void *closure); /** \brief Sets the callback to be invoked when new servers are discovered. * * Specifies the callback to invoke when the client library has been notified * of one or more new `NATS Servers`. * * \warning Invocation of this callback is asynchronous, which means that * the state may have changed when this callback is invoked. * * @param opts the pointer to the #natsOptions object. * @param discoveredServersCb the callback to be invoked when new servers * have been discovered. * @param closure a pointer to an user object that will be passed to * the callback. `closure` can be `NULL`. */ NATS_EXTERN natsStatus natsOptions_SetDiscoveredServersCB(natsOptions *opts, natsConnectionHandler discoveredServersCb, void *closure); /** \brief Sets if the library should ignore or not discovered servers. * * By default, when a server joins a cluster, a client is notified * of the new URL and added to the list so it can be used in case * of a reconnect. * * The servers can be configured to disable this gossip, however, if * not done at the servers level, this option allows the discovered * servers to be ignored. * * @param opts the pointer to the #natsOptions object. * @param ignore if discovered server should be ignored or not. */ NATS_EXTERN natsStatus natsOptions_SetIgnoreDiscoveredServers(natsOptions *opts, bool ignore); /** \brief Sets the callback to be invoked when server enters lame duck mode. * * Specifies the callback to invoke when the server notifies * the connection that it entered lame duck mode, that is, going to * gradually disconnect all its connections before shuting down. This is * often used in deployments when upgrading NATS Servers. * * \warning Invocation of this callback is asynchronous, which means that * the state may have changed when this callback is invoked. * * @param opts the pointer to the #natsOptions object. * @param lameDuckCb the callback to be invoked when server enters * lame duck mode. * @param closure a pointer to an user object that will be passed to * the callback. `closure` can be `NULL`. */ NATS_EXTERN natsStatus natsOptions_SetLameDuckModeCB(natsOptions *opts, natsConnectionHandler lameDuckCb, void *closure); /** \brief Sets the external event loop and associated callbacks. * * If you want to use an external event loop, the `NATS` library will not * create a thread to read data from the socket, and will not directly write * data to the socket. Instead, the library will invoke those callbacks * for various events. * * @param opts the pointer to the #natsOptions object. * @param loop the `void*` pointer to the external event loop. * @param attachCb the callback invoked after the connection is connected, * or reconnected. * @param readCb the callback invoked when the event library should start or * stop polling for read events. * @param writeCb the callback invoked when the event library should start or * stop polling for write events. * @param detachCb the callback invoked when a connection is closed. */ NATS_EXTERN natsStatus natsOptions_SetEventLoop(natsOptions *opts, void *loop, natsEvLoop_Attach attachCb, natsEvLoop_ReadAddRemove readCb, natsEvLoop_WriteAddRemove writeCb, natsEvLoop_Detach detachCb); /** \brief Switch on/off the use of a central message delivery thread pool. * * Normally, each asynchronous subscriber that is created has its own * message delivery thread. The advantage is that it reduces lock * contentions, therefore improving performance.
* However, if an application creates many subscribers, this is not scaling * well since the process would use too many threads. * * When a connection is created from a `nats_Options` that has enabled * global message delivery, asynchronous subscribers from this connection * will use a shared thread pool responsible for message delivery. * * \note The message order per subscription is still guaranteed. * * @see nats_SetMessageDeliveryPoolSize() * @see \ref envVariablesGroup * * @param opts the pointer to the #natsOptions object. * @param global if `true`, uses the global message delivery thread pool, * otherwise, each asynchronous subscriber will create their own message * delivery thread. */ NATS_EXTERN natsStatus natsOptions_UseGlobalMessageDelivery(natsOptions *opts, bool global); /** \brief Dictates the order in which host name are resolved during connect. * * The library would previously favor IPv6 addresses during the connect process. *
* You can now change the order, or even exclude a family of addresses, using * this option. Here is the list of possible values: *
* Value | Meaning * ------|-------- * 46 | try IPv4 first, if it fails try IPv6 * 64 | try IPv6 first, if it fails try IPv4 * 4 | use only IPv4 * 6 | use only IPv6 * 0 | any family, no specific order * * \note If this option is not set, or you specify `0` for the order, the * library will use the first IP (based on the DNS configuration) for which * a successful connection can be made. * * @param opts the pointer to the #natsOptions object. * @param order a string representing the order for the IP resolution. */ NATS_EXTERN natsStatus natsOptions_IPResolutionOrder(natsOptions *opts, int order); /** \brief Sets if Publish calls should send data right away. * * For throughput performance, the client library tries by default to buffer * as much data as possible before sending it over TCP. * * Setting this option to `true` will make Publish calls send the * data right away, reducing latency, but also throughput. * * A good use-case would be a connection used to solely send replies. * Imagine, a requestor sending a request, waiting for the reply before * sending the next request.
* The replier application will send only one reply at a time (since * it will not receive the next request until the requestor receives * the reply).
* In such case, it makes sense for the reply to be sent right away. * * The alternative would be to call #natsConnection_Flush(), * but this call requires a round-trip with the server, which is less * efficient than using this option. * * Note that the Request() call already automatically sends the request * as fast as possible, there is no need to set an option for that. * * @param opts the pointer to the #natsOptions object. * @param sendAsap a boolean indicating if published data should be * sent right away or be buffered. */ NATS_EXTERN natsStatus natsOptions_SetSendAsap(natsOptions *opts, bool sendAsap); /** \brief Switches the use of old style requests. * * Setting `useOldStyle` to `true` forces the request calls to use the original * behavior, which is to create a new inbox, a new subscription on that inbox * and set auto-unsubscribe to 1. * * @param opts the pointer to the #natsOptions object. * @param useOldStyle a boolean indicating if old request style should be used. */ NATS_EXTERN natsStatus natsOptions_UseOldRequestStyle(natsOptions *opts, bool useOldStyle); /** \brief Fails pending requests on disconnect event. * * If this option is enabled, all pending #natsConnection_Request() family * calls will fail with the #NATS_CONNECTION_DISCONNECTED status. * * \note This does not apply to requests from connections that use the * old style requests. * * @see natsOptions_UseOldRequestStyle * * @param opts the pointer to the #natsOptions object. * @param failRequests a boolean indicating if pending requests should fail * when a disconnect event occurs. */ NATS_EXTERN natsStatus natsOptions_SetFailRequestsOnDisconnect(natsOptions *opts, bool failRequests); /** \brief Sets if connection receives its own messages. * * This configures whether the server will echo back messages * that are sent on this connection if there is also matching subscriptions. * * Set this to `true` to prevent the server from sending back messages * produced by this connection. The default is false, that is, messages * originating from this connection will be sent by the server if the * connection has matching subscriptions. * * \note This is supported on servers >= version 1.2.0. Calling * #natsConnection_Connect() with the option set to `true` to server below * this version will return the `NATS_NO_SERVER_SUPPORT` error. * * @param opts the pointer to the #natsOptions object. * @param noEcho a boolean indicating if sent messages can be delivered back * to this connection or not. */ NATS_EXTERN natsStatus natsOptions_SetNoEcho(natsOptions *opts, bool noEcho); /** \brief Indicates if initial connect failure should be retried or not. * * By default, #natsConnection_Connect() attempts to connect to a server * specified in provided list of servers. If it cannot connect and the list has been * fully tried, the function returns an error. * * This option is used to changed this default behavior. * * If `retry` is set to `true` and connection cannot be established right away, the * library will attempt to connect based on the reconnect attempts * and delay settings. * * \note The connect retry logic uses reconnect settings even if #natsOptions_SetAllowReconnect() * has been set to false. In other words, a failed connect may be retried even though * a reconnect will not be allowed should the connection to the server be lost * after initial connect. * * The behavior will then depend on the value of the `connectedCb` parameter: * * * If `NULL`, then the call blocks until it can connect * or exhausts the reconnect attempts. * * * If not `NULL`, and no connection can be immediately * established, the #natsConnection_Connect() calls returns #NATS_NOT_YET_CONNECTED * to indicate that no connection is currently established, but will * try asynchronously to connect using the reconnect attempts/delay settings. If * the connection is later established, the specified callback will be * invoked. If no connection can be made and the retry attempts are exhausted, * the callback registered with #natsOptions_SetClosedCB(), if any, will be * invoked. * * \note If #natsConnection_Connect() returns `NATS_OK` (that is, a connection to * a `NATS Server` was established in that call), then the `connectedCb` callback * will not be invoked. * * If `retry` is set to false, #natsConnection_Connect() behaves as originally * designed, that is, returns an error and no connection object if failing to connect * to any server in the list. * * \note The `connectedCb` parameter is ignored and set to `NULL` in the options object * when `retry` is set to `false`. * * @see natsOptions_SetMaxReconnect() * @see natsOptions_SetReconnectWait() * @see natsOptions_SetClosedCB() * * @param opts the pointer to the #natsOptions object. * @param retry a boolean indicating if a failed connect should be retried. * @param connectedCb if `retry` is true and this is not `NULL`, then the * connect may be asynchronous and this callback will be invoked if the connect * succeeds. * @param closure a pointer to an user object that will be passed to the callback. `closure` can be `NULL`. */ NATS_EXTERN natsStatus natsOptions_SetRetryOnFailedConnect(natsOptions *opts, bool retry, natsConnectionHandler connectedCb, void* closure); /** \brief Sets the callbacks to fetch user JWT and sign server's nonce. * * Any time the library creates a TCP connection to the server, the server * in response sends an `INFO` protocol. That `INFO` protocol, for NATS Server * at v2.0.0+, may include a `nonce` for the client to sign. * * If this option is set, the library will invoke the two handlers to fetch * the user JWT and sign the server's nonce. * * This is an option that will be used only by users that are able to * sign using Ed25519 (public-key signature system). Most users will probably * prefer the user of #natsOptions_SetUserCredentialsFromFiles(). * * \note natsOptions_SetUserCredentialsCallbacks() and natsOptions_SetNKey() * are mutually exclusive. Calling this function will remove the NKey and * replace the signature handler, that was set with natsOptions_SetNKey(), * with this one. * * @see natsUserJWTHandler * @see natsSignatureHandler * @see natsOptions_SetUserCredentialsFromFiles() * * @param opts the pointer to the #natsOptions object. * @param ujwtCB the callback to invoke to fetch the user JWT. * @param ujwtClosure the closure that will be passed to the `ujwtCB` callback. * @param sigCB the callback to invoke to sign the server nonce. * @param sigClosure the closure that will be passed to the `sigCB` callback. */ NATS_EXTERN natsStatus natsOptions_SetUserCredentialsCallbacks(natsOptions *opts, natsUserJWTHandler ujwtCB, void *ujwtClosure, natsSignatureHandler sigCB, void *sigClosure); /** \brief Sets the file(s) to use to fetch user JWT and seed required to sign nonce. * * This is a convenient option that specifies the files(s) to use to fetch * the user JWT and the user seed to be used to sign the server's nonce. * * The `userOrChainedFile` contains the user JWT token and possibly the user * NKey seed. Note the format of this file: * * \code{.unparsed} * -----BEGIN NATS USER JWT----- * ...an user JWT token... * ------END NATS USER JWT------ * * ************************* IMPORTANT ************************* * NKEY Seed printed below can be used to sign and prove identity. * NKEYs are sensitive and should be treated as secrets. * * -----BEGIN USER NKEY SEED----- * SU... * ------END USER NKEY SEED------ * \endcode * * The `---BEGIN NATS USER JWT---` header is used to detect where the user * JWT is in this file. * * If the file does not contain the user NKey seed, then the `seedFile` file * name must be specified and must contain the user NKey seed. * * \note natsOptions_SetUserCredentialsFromFiles() and natsOptions_SetNKey() * are mutually exclusive. Calling this function will remove the NKey and * replace the signature handler, that was set with natsOptions_SetNKey(), * with an internal one that will handle the signature. * * @param opts the pointer to the #natsOptions object. * @param userOrChainedFile the name of the file containing the user JWT and * possibly the user NKey seed. * @param seedFile the name of the file containing the user NKey seed. */ NATS_EXTERN natsStatus natsOptions_SetUserCredentialsFromFiles(natsOptions *opts, const char *userOrChainedFile, const char *seedFile); /** \brief Sets JWT handler and handler to sign nonce that uses seed. * * This function acts similarly to natsOptions_SetUserCredentialsFromFiles() but reads from memory instead * from a file. Also it assumes that `jwtAndSeedContent` contains both the JWT and NKey seed. * * As for the format, see natsOptions_SetUserCredentialsFromFiles() documentation. * * @see natsOptions_SetUserCredentialsFromFiles() * * @param opts the pointer to the #natsOptions object. * @param jwtAndSeedContent string containing user JWT and user NKey seed. */ NATS_EXTERN natsStatus natsOptions_SetUserCredentialsFromMemory(natsOptions *opts, const char *jwtAndSeedContent); /** \brief Sets the NKey public key and signature callback. * * Any time the library creates a TCP connection to the server, the server * in response sends an `INFO` protocol. That `INFO` protocol, for NATS Server * at v2.0.0+, may include a `nonce` for the client to sign. * * If this option is set, the library will add the NKey public key `pubKey` * to the `CONNECT` protocol along with the server's nonce signature resulting * from the invocation of the signature handler `sigCB`. * * \note natsOptions_SetNKey() and natsOptions_SetUserCredentialsCallbacks() * or natsOptions_SetUserCredentialsFromFiles() are mutually exclusive. * Calling this function will remove the user JWT callback and replace the * signature handler, that was set with one of the user credentials options, * with this one. * * @see natsSignatureHandler * * @param opts the pointer to the #natsOptions object. * @param pubKey the user NKey public key. * @param sigCB the callback to invoke to sign the server nonce. * @param sigClosure the closure that will be passed to the `sigCB` callback. */ NATS_EXTERN natsStatus natsOptions_SetNKey(natsOptions *opts, const char *pubKey, natsSignatureHandler sigCB, void *sigClosure); /** \brief Sets the NKey public key and its seed file. * * Any time the library creates a TCP connection to the server, the server * in response sends an `INFO` protocol. That `INFO` protocol, for NATS Server * at v2.0.0+, may include a `nonce` for the client to sign. * * If this option is set, the library will add the NKey public key `pubKey` * to the `CONNECT` protocol along with the server's nonce signature signed * using the private key from the provided seed file. The library takes care * of clearing the memory holding the private key read from the file as soon * as it is no longer needed. * * \note natsOptions_SetNKeyFromSeed() and natsOptions_SetUserCredentialsCallbacks() * or natsOptions_SetUserCredentialsFromFiles() are mutually exclusive. * Calling this function will remove the user JWT callback and replace the * signature handler, that was set with one of the user credentials options, * with this one. * * @see natsSignatureHandler * * @param opts the pointer to the #natsOptions object. * @param pubKey the user NKey public key. * @param seedFile the name of the file containing the user NKey seed. */ NATS_EXTERN natsStatus natsOptions_SetNKeyFromSeed(natsOptions *opts, const char *pubKey, const char *seedFile); /** \brief Sets the write deadline. * * If this is set, the socket is set to non-blocking mode and * write will have a deadline set. If the deadline is reached, * the write call will return an error which will translate * to publish calls, or any library call trying to send data * to the server, to possibly fail. * * @param opts the pointer to the #natsOptions object. * @param deadline the write deadline expressed in milliseconds. * If set to 0, it means that there is no deadline and socket * is in blocking mode. */ NATS_EXTERN natsStatus natsOptions_SetWriteDeadline(natsOptions *opts, int64_t deadline); /** \brief Enable/Disable the "no responders" feature. * * By default, when a connection to a NATS Server v2.2.0+ is made, * the library signals to the server that it supports the "no responders" * feature, which means that if a request is made, and there are * no subscriptions on the request subject (no responders), then * the server sends back an empty message with the header "Status" * and value "503". The request APIs capture this message and * instead return a #NATS_NO_RESPONDERS status, instead of waiting * for the timeout to occur and return #NATS_TIMEOUT. * * In case where users set up their own asynchronous subscription * on the reply subject and publish the request with #natsConnection_PublishRequest * and the like, then the message callback may be invoked with this * "no responders" message, which can be checked with #natsMsg_IsNoResponders. * * However, if users don't want to have to deal with that, it is * possible to instruct the server to disable this feature for * a given connection. If that is the case, requests will behave * as with pre-v2.2.0 servers, in that the request will timeout * when there are no responders. * * \note This function is to disable the feature that is normally * enabled by default. Passing `false` means that it would enable * it again if you had previously disable the option. However, the * feature may still be disabled when connecting to a server that * does not support it. * * @see natsMsg_IsNoResponders() * * @param opts the pointer to the #natsOptions object. * @param disabled the boolean to indicate if the feature should be * disabled or not. */ NATS_EXTERN natsStatus natsOptions_DisableNoResponders(natsOptions *opts, bool disabled); /** \brief Sets a custom inbox prefix * * The default inbox prefix is "_INBOX", but you can change it * using this option. This can be useful when setting permissions * and/or with import/exports across different accounts. * * The prefix must be a valid subject and not contain any of the * wildcards tokens `*` nor `>`. * * To clear the custom inbox prefix, call this function with `NULL` * or the empty string. * * @param opts the pointer to the #natsOptions object. * @param inboxPrefix the desired inbox prefix. */ NATS_EXTERN natsStatus natsOptions_SetCustomInboxPrefix(natsOptions *opts, const char *inboxPrefix); /** \brief Sets a custom padding when allocating buffer for incoming messages * * By default library allocates natsMsg with payload buffer size * equal to payload size. Sometimes it can be useful to add some * padding to the end of the buffer which can be tweaked using * this option. * * To clear the custom message buffer padding, call this function with 0. * Changing this option has no effect on existing NATS connections. * * @param opts the pointer to the #natsOptions object. * @param paddingSize the desired inbox prefix. */ NATS_EXTERN natsStatus natsOptions_SetMessageBufferPadding(natsOptions *opts, int paddingSize); /** \brief Destroys a #natsOptions object. * * Destroys the natsOptions object, freeing used memory. See the note in * the natsOptions_Create() call. * * @param opts the pointer to the #natsOptions object to destroy. */ NATS_EXTERN void natsOptions_Destroy(natsOptions *opts); /** @} */ // end of optsGroup #if defined(NATS_HAS_STREAMING) /** \defgroup stanConnOptsGroup Streaming Connection Options * * NATS Streaming Connection Options. * @{ */ /** \brief Creates a #stanConnOptions object. * * Creates a #stanConnOptions object. This object is used when one wants to set * specific options prior to connecting to the `NATS Streaning Server`. * * After making the appropriate `stanConnOptions_SetXXX()` calls, this object is passed * to the #stanConnection_Connect() call, which will clone this object. After * #stanConnection_Connect() returns, modifications to the options object * will not affect the connection. * * The default options set in this call are: * url: `nats://localhost:4222` * connection wait: 2 seconds * publish ack wait: 30 seconds * discovery prefix: `_STAN.discovery` * maximum publish acks inflight and percentage: 16384, 50% * ping interval: 5 seconds * max ping out without response: 3 * * \note The object needs to be destroyed when no longer needed. * * @see stanConnection_Connect() * @see stanConnOptions_Destroy() * * @param newOpts the location where store the pointer to the newly created * #stanConnOptions object. */ NATS_EXTERN natsStatus stanConnOptions_Create(stanConnOptions **newOpts); /** \brief Sets the URL to connect to. * * Sets the URL of the `NATS Streaming Server` the client should try to connect to. * The URL can contain optional user name and password. You can provide a comma * separated list of URLs too. * * Some valid URLS: * * - nats://localhost:4222 * - nats://user\@localhost:4222 * - nats://user:password\@localhost:4222 * - nats://host1:4222,nats://host2:4222,nats://host3:4222 * * \note This option takes precedence over #natsOptions_SetURL when NATS options * are passed with #stanConnOptions_SetNATSOptions. * * @param opts the pointer to the #stanConnOptions object. * @param url the string representing the URL the connection should use * to connect to the server. * */ NATS_EXTERN natsStatus stanConnOptions_SetURL(stanConnOptions *opts, const char *url); /** \brief Sets the NATS Options to use to create the connection. * * The Streaming client connects to the NATS Streaming Server through * a regular NATS Connection (#natsConnection). To configure this connection * create a #natsOptions and configure it as needed, then call this function. * * This function clones the passed options, so after this call, any * changes to the given #natsOptions will not affect the #stanConnOptions. * * \note If both #natsOptions_SetURL and #stanConnOptions_SetURL are used * the URL(s) set in the later take precedence. * * @param opts the pointer to the #stanConnOptions object. * @param nOpts the pointer to the #natsOptions object to use to create * the connection to the server. */ NATS_EXTERN natsStatus stanConnOptions_SetNATSOptions(stanConnOptions *opts, natsOptions *nOpts); /** \brief Sets the timeout for establishing a connection. * * Value expressed in milliseconds. * * Default is 2000 milliseconds (2 seconds). * * @param opts the pointer to the #stanConnOptions object. * @param wait how long to wait for a response from the streaming server. */ NATS_EXTERN natsStatus stanConnOptions_SetConnectionWait(stanConnOptions *opts, int64_t wait); /** \brief Sets the timeout for waiting for an ACK for a published message. * * Value expressed in milliseconds. * * Default is 30000 milliseconds (30 seconds). * * @param opts the pointer to the #stanConnOptions object. * @param wait how long to wait for a response from the streaming server. */ NATS_EXTERN natsStatus stanConnOptions_SetPubAckWait(stanConnOptions *opts, int64_t wait); /** \brief Sets the subject prefix the library sends the connect request to. * * Default is `_STAN.discovery` * * @param opts the pointer to the #stanConnOptions object. * @param prefix the subject prefix the library sends the connect request to. */ NATS_EXTERN natsStatus stanConnOptions_SetDiscoveryPrefix(stanConnOptions *opts, const char *prefix); /** \brief Sets the maximum number of published messages without outstanding ACKs from the server. * * A connection will block #stanConnection_Publish() or #stanConnection_PublishAsync calls * if the number of outstanding published messages has reached this number. * * When the connection receives ACKs, the number of outstanding messages will decrease. * If the number falls between `maxPubAcksInflight * percentage`, then the blocked publish * calls will be released. * * @param opts the pointer to the #stanConnOptions object. * @param maxPubAcksInflight the maximum number of published messages without ACKs from the server. * @param percentage the percentage (expressed as a float between ]0.0 and 1.0]) of the maxPubAcksInflight * number below which a blocked publish call is released. */ NATS_EXTERN natsStatus stanConnOptions_SetMaxPubAcksInflight(stanConnOptions *opts, int maxPubAcksInflight, float percentage); /** \brief Sets the ping interval and max out values. * * Value expressed in number of seconds. * * Default is 5 seconds and 3 missed PONGs. * * The interval needs to be at least 1 and represents the number of seconds. * The maxOut needs to be at least 2, since the count of sent PINGs increase * whenever a PING is sent and reset to 0 when a response is received. * Setting to 1 would cause the library to close the connection right away. * * @param opts the pointer to the #stanConnOptions object. * @param interval the number of seconds between each PING. * @param maxOut the maximum number of PINGs without receiving a PONG back. */ NATS_EXTERN natsStatus stanConnOptions_SetPings(stanConnOptions *opts, int interval, int maxOut); /** \brief Sets the connection lost handler. * * This callback will be invoked should the client permanently lose * contact with the server (or another client replaces it while being * disconnected). The callback will not be invoked on normal #stanConnection_Close(). * * @param opts the pointer to the #stanConnOptions object. * @param handler the handler to be invoked when the connection to the streaming server is lost. * @param closure the closure the library will pass to the callback. */ NATS_EXTERN natsStatus stanConnOptions_SetConnectionLostHandler(stanConnOptions *opts, stanConnectionLostHandler handler, void *closure); /** \brief Destroys a #stanConnOptions object. * * Destroys the #stanConnOptions object, freeing used memory. See the note in * the #stanConnOptions_Create() call. * * @param opts the pointer to the #stanConnOptions object to destroy. */ NATS_EXTERN void stanConnOptions_Destroy(stanConnOptions *opts); /** @} */ // end of stanConnOptsGroup /** \defgroup stanSubOptsGroup Streaming Subscription Options * * NATS Streaming Subscription Options. * @{ */ /** \brief Creates a #stanSubOptions object. * * Creates a #stanSubOptions object. This object is used when one wants to set * specific options prior to create a subscription. * * After making the appropriate `stanSubOptions_SetXXX()` calls, this object is passed * to the #stanConnection_Subscribe() or #stanConnection_QueueSubscribe() call, which * will clone this object. It means that modifications to the options object will not * affect the created subscription. * * The default options set in this call are: * ackWait: 30000 milliseconds (30 seconds) * maxIinflight: 1024 * start position: new only * * \note The object needs to be destroyed when no longer needed. * * @see stanConnection_Subscribe() * @see stanConnection_QueueSubscribe() * @see stanSubOptions_Destroy() * * @param newOpts the location where store the pointer to the newly created * #stanSubOptions object. */ NATS_EXTERN natsStatus stanSubOptions_Create(stanSubOptions **newOpts); /** \brief Sets the Durable Name for this subscription. * * If a durable name is set, this subscription will be durable. It means that * if the application stops and re-create the same subscription with the * same connection client ID and durable name (or simply durable name for * queue subscriptions), then the server will resume (re)delivery of messages * from the last known position in the steam for that durable. * * It means that the start position, if provided, is used only when the durable * subscription is first created, then is ignored by the server for the rest * of the durable subscription lifetime. * * \note Durable names should be alphanumeric and not contain the character `:`. * * @param opts the pointer to the #stanSubOptions object. * @param durableName the string representing the name of the durable subscription. * */ NATS_EXTERN natsStatus stanSubOptions_SetDurableName(stanSubOptions *opts, const char *durableName); /** \brief Sets the timeout for waiting for an ACK from the cluster's point of view for delivered messages. * * Value expressed in milliseconds. * * Default is 30000 milliseconds (30 seconds). * * If the server does not receive an acknowledgment from the subscription for * a delivered message after this amount of time, the server will re-deliver * the unacknowledged message. * * @param opts the pointer to the #stanSubOptions object. * @param wait how long the server will wait for an acknowledgment from the subscription. */ NATS_EXTERN natsStatus stanSubOptions_SetAckWait(stanSubOptions *opts, int64_t wait); /** \brief Sets the the maximum number of messages the cluster will send without an ACK. * * Default is 1024. * * If a subscription receives messages but does not acknowledge them, the server will * stop sending new messages when it reaches this number. Unacknowledged messages are * re-delivered regardless of that setting. * * @param opts the pointer to the #stanSubOptions object. * @param maxInflight the maximum number of messages the subscription will receive without sending back ACKs. */ NATS_EXTERN natsStatus stanSubOptions_SetMaxInflight(stanSubOptions *opts, int maxInflight); /** \brief Sets the desired start position based on the given sequence number. * * This allows the subscription to start at a specific sequence number in * the channel's message log. * * If the sequence is smaller than the first available message in the * message log (old messages dropped due to channel limits), * the subscription will be created with the first available sequence. * * Conversely, if the given sequence is higher than the currently * last sequence number, the subscription will receive only new published messages. * * @param opts the pointer to the #stanSubOptions object. * @param seq the starting sequence. */ NATS_EXTERN natsStatus stanSubOptions_StartAtSequence(stanSubOptions *opts, uint64_t seq); /** \brief Sets the desired start position based on the given time. * * When the subscription is created, the server will send messages starting * with the message which timestamp is at least the given time. The time * is expressed in number of milliseconds since the EPOCH, as given by * nats_Now() for instance. * * If the time is in the past and the most recent message's timestamp is older * than the given time, or if the time is in the future, the subscription * will receive only new messages. * * @param opts the pointer to the #stanSubOptions object. * @param time the start time, expressed in milliseconds since the EPOCH. */ NATS_EXTERN natsStatus stanSubOptions_StartAtTime(stanSubOptions *opts, int64_t time); /** \brief Sets the desired start position based on the given delta. * * When the subscription is created, the server will send messages starting * with the message which timestamp is at least now minus `delta`. In other words, * this means start receiving messages that were sent n milliseconds ago. * * The delta is expressed in milliseconds. * * @param opts the pointer to the #stanSubOptions object. * @param delta he historical time delta (from now) from which to start receiving messages. */ NATS_EXTERN natsStatus stanSubOptions_StartAtTimeDelta(stanSubOptions *opts, int64_t delta); /** \brief The subscription should start with the last message in the channel. * * When the subscription is created, the server will start sending messages * starting with the last message currently in the channel message's log. * The subscription will then receive any new published message. * * @param opts the pointer to the #stanSubOptions object. */ NATS_EXTERN natsStatus stanSubOptions_StartWithLastReceived(stanSubOptions *opts); /** \brief The subscription should start with the first message in the channel. * * When the subscription is created, the server will start sending messages * starting with the first message currently in the channel message's log. * * @param opts the pointer to the #stanSubOptions object. */ NATS_EXTERN natsStatus stanSubOptions_DeliverAllAvailable(stanSubOptions *opts); /** \brief Sets the subscription's acknowledgment mode. * * By default, a subscription will automatically send a message acknowledgment * after the #stanMsgHandler callback returns. * * In order to control when the acknowledgment is sent, set the acknowledgment * mode to `manual` and call #stanSubscription_AckMsg(). * * @see #stanSubscription_AckMsg() * * @param opts the pointer to the #stanSubOptions object. * @param manual a boolean indicating if the subscription should auto-acknowledge * or if the user will. */ NATS_EXTERN natsStatus stanSubOptions_SetManualAckMode(stanSubOptions *opts, bool manual); /** \brief Destroys a #stanSubOptions object. * * Destroys the #stanSubOptions object, freeing used memory. See the note in * the #stanSubOptions_Create() call. * * @param opts the pointer to the #stanSubOptions object to destroy. */ NATS_EXTERN void stanSubOptions_Destroy(stanSubOptions *opts); /** @} */ // end of stanSubOptsGroup #endif /** \defgroup inboxGroup Inboxes * * NATS Inboxes. * @{ */ /** \brief Creates an inbox. * * Returns an inbox string which can be used for directed replies from * subscribers. These are guaranteed to be unique, but can be shared * and subscribed to by others. * * \note The inbox needs to be destroyed when no longer needed. * * @see #natsInbox_Destroy() * * @param newInbox the location where to store a pointer to the newly * created #natsInbox. */ NATS_EXTERN natsStatus natsInbox_Create(natsInbox **newInbox); /** \brief Destroys the inbox. * * Destroys the inbox. * * @param inbox the pointer to the #natsInbox object to destroy. */ NATS_EXTERN void natsInbox_Destroy(natsInbox *inbox); /** @} */ // end of inboxGroup /** \defgroup msgGroup Message * * NATS Message. * @{ */ /** \brief Destroys this list of messages. * * This function iterates through the list of all messages and call #natsMsg_Destroy * for each valid (not set to `NULL`) message. It then frees the array that was * allocated to hold pointers to those messages. * * \note The #natsMsgList object itself is not freed since it is expected that * users will pass a pointer to a stack object. Should the user create its own * object, it will be the user responsibility to free this object. * * @param list the #natsMsgList list of #natsMsg objects to destroy. */ NATS_EXTERN void natsMsgList_Destroy(natsMsgList *list); /** \brief Creates a #natsMsg object. * * Creates a #natsMsg object. This is used by the subscription related calls * and by #natsConnection_PublishMsg(). * * \note Messages need to be destroyed with #natsMsg_Destroy() when no * longer needed. * * @see natsMsg_Destroy() * * @param newMsg the location where to store the pointer to the newly created * #natsMsg object. * @param subj the subject this message will be sent to. Cannot be `NULL`. * @param reply the optional reply for this message. * @param data the optional message payload. * @param dataLen the size of the payload. */ NATS_EXTERN natsStatus natsMsg_Create(natsMsg **newMsg, const char *subj, const char *reply, const char *data, int dataLen); /** \brief Returns the subject set in this message. * * Returns the subject set on that message. * * \warning The string belongs to the message and must not be freed. * Copy it if needed. * @param msg the pointer to the #natsMsg object. */ NATS_EXTERN const char* natsMsg_GetSubject(const natsMsg *msg); /** \brief Returns the reply set in this message. * * Returns the reply, possibly `NULL`. * * \warning The string belongs to the message and must not be freed. * Copy it if needed. * * @param msg the pointer to the #natsMsg object. */ NATS_EXTERN const char* natsMsg_GetReply(const natsMsg *msg); /** \brief Returns the message payload. * * Returns the message payload, possibly `NULL`. * * Note that although the data sent and received from the server is not `NULL` * terminated, the NATS C Client does add a `NULL` byte to the received payload. * If you expect the received data to be a "string", then this conveniently * allows you to call #natsMsg_GetData() without having to copy the returned * data to a buffer to add the `NULL` byte at the end. * * \warning The string belongs to the message and must not be freed. * Copy it if needed. * * @param msg the pointer to the #natsMsg object. */ NATS_EXTERN const char* natsMsg_GetData(const natsMsg *msg); /** \brief Returns the message length. * * Returns the message's payload length, possibly 0. * * @param msg the pointer to the #natsMsg object. */ NATS_EXTERN int natsMsg_GetDataLength(const natsMsg *msg); /** \brief Set the header entries associated with `key` to the single element `value`. * * It will replace any existing value associated with `key`. * * \warning Prior to v3.0.0, the `key` was stored in its canonical form, this is no * longer the case. Header keys are now case sensitive. * * \warning Headers are not thread-safe, that is, you must not set/add/get values or * delete keys for the same message from different threads. The internal structure * of `natsMsg` may possible be altered during this call. * * @param msg the pointer to the #natsMsg object. * @param key the key under which the `value` will be stored. It can't ne `NULL` or empty. * @param value the string to store under the given `key`. The value can be `NULL` or empty string. */ NATS_EXTERN natsStatus natsMsgHeader_Set(natsMsg *msg, const char *key, const char *value); /** \brief Add `value` to the header associated with `key`. * * It will append to any existing values associated with `key`. * * \warning Prior to v3.0.0, the `key` was stored in its canonical form, this is no * longer the case. Header keys are now case sensitive. * * \warning Headers are not thread-safe, that is, you must not set/add/get values or * delete keys for the same message from different threads. The internal structure * of `natsMsg` may possible be altered during this call. * * @param msg the pointer to the #natsMsg object. * @param key the key under which the `value` will be stored. It can't ne `NULL` or empty. * @param value the string to add to the values associated with the given `key`. The value can be `NULL` or empty string. */ NATS_EXTERN natsStatus natsMsgHeader_Add(natsMsg *msg, const char *key, const char *value); /** \brief Get the header entry associated with `key`. * * If more than one entry for the `key` is available, the first is returned. * The returned value is owned by the library and MUST not be freed or altered. * * \warning Prior to v3.0.0, the `key` was stored in its canonical form, this is no * longer the case. Header keys are now case sensitive. * * \warning Headers are not thread-safe, that is, you must not set/add/get values or * delete keys for the same message from different threads. The internal structure * of `natsMsg` may possible be altered during this call. * * @param msg the pointer to the #natsMsg object. * @param key the key for which the value is requested. * @param value the memory location where the library will store the pointer to the first * value (if more than one is found) associated with the `key`. * @return NATS_NOT_FOUND if `key` is not present in the headers. */ NATS_EXTERN natsStatus natsMsgHeader_Get(natsMsg *msg, const char *key, const char **value); /** \brief Get all header values associated with `key`. * * The returned strings are own by the library and MUST not be freed or altered. * However, the returned array `values` MUST be freed by the user. * * \code{.c} * const char* *values = NULL; * int count = 0; * * s = natsMsgHeader_Values(msg, "My-Key", &values, &count); * if (s == NATS_OK) * { * // do something with the values * * // then free the array of pointers. * free((void*) values); * } * \endcode * * \warning Prior to v3.0.0, the `key` was stored in its canonical form, this is no * longer the case. Header keys are now case sensitive. * * \warning Headers are not thread-safe, that is, you must not set/add/get values or * delete keys for the same message from different threads. The internal structure * of `natsMsg` may possible be altered during this call. * * @param msg the pointer to the #natsMsg object. * @param key the key for which the values are requested. * @param values the memory location where the library will store the pointer to the array * of values. * @param count the memory location where the library will store the number of values returned. * @return NATS_NOT_FOUND if `key` is not present in the headers. */ NATS_EXTERN natsStatus natsMsgHeader_Values(natsMsg *msg, const char *key, const char* **values, int *count); /** \brief Get all header keys. * * The returned strings are own by the library and MUST not be freed or altered. * However, the returned array `keys` MUST be freed by the user. * * \code{.c} * const char* *keys = NULL; * int count = 0; * * s = natsMsgHeader_Keys(msg, &keys, &count); * if (s == NATS_OK) * { * // do something with the keys * * // then free the array of pointers. * free((void*) keys); * } * \endcode * * \warning Headers are not thread-safe, that is, you must not set/add/get values or * delete keys for the same message from different threads. The internal structure * of `natsMsg` may possible be altered during this call. * * @param msg the pointer to the #natsMsg object. * @param keys the memory location where the library will store the pointer to the array * of keys. * @param count the memory location where the library will store the number of keys returned. * @return NATS_NOT_FOUND if no key is present. */ NATS_EXTERN natsStatus natsMsgHeader_Keys(natsMsg *msg, const char* **keys, int *count); /** \brief Delete the value(s) associated with `key`. * * \warning Prior to v3.0.0, the `key` was stored in its canonical form, this is no * longer the case. Header keys are now case sensitive. * * \warning Headers are not thread-safe, that is, you must not set/add/get values or * delete keys for the same message from different threads. The internal structure * of `natsMsg` may possible be altered during this call. * * @param msg the pointer to the #natsMsg object. * @param key the key to delete from the headers map. * @return NATS_NOT_FOUND if `key` is not present in the headers. */ NATS_EXTERN natsStatus natsMsgHeader_Delete(natsMsg *msg, const char *key); /** \brief Indicates if this message is a "no responders" message from the server. * * Starting with the NATS Server v2.2.0+ and the C client v2.2.0+ releases, which * introduced support for message headers and the "no responders" feature, if a * request is received by the server and there are no subscriptions on the * request's subject, the server sends a message with no payload but with a header * "Status" with value "503". * * The call #natsConnection_Request() and its variants intercept this special * message and instead of returning it to the user, they return #NATS_NO_RESPONDERS. * * If a synchronous subscription is created on a subject used as a reply subject * to a #natsConnection_PublishRequest call (and its variants), #natsSubscription_NextMsg * also detects this message and returns #NATS_NO_RESPONDERS (but it was not from * release v2.2.0 to v2.4.1). * * For asynchronous subscriptions, the user may want to know that the request * failed because there are no responders. For that reason, the message is passed * to the message callback, and this function can be used to detect that this * is a "no responders" message from the server and act accordingly. * * @param msg the pointer to the #natsMsg object. * @return `true` if this message is a "no responders" message from the server, * that is, has no payload and the "Status" header with "503" as the value. */ NATS_EXTERN bool natsMsg_IsNoResponders(natsMsg *msg); /** \brief Destroys the message object. * * Destroys the message, freeing memory. * * @param msg the pointer to the #natsMsg object to destroy. */ NATS_EXTERN void natsMsg_Destroy(natsMsg *msg); /** @} */ // end of msgGroup #if defined(NATS_HAS_STREAMING) /** \defgroup stanMsgGroup Streaming Message * * NATS Streaming Message. * @{ */ /** \brief Returns the message's sequence number. * * Returns the message's sequence number (as assigned by the cluster). * * @param msg the pointer to the #stanMsg object. */ NATS_EXTERN uint64_t stanMsg_GetSequence(const stanMsg *msg); /** \brief Returns the message's timestamp. * * Returns the message's timestamp (as assigned by the cluster). * * @param msg the pointer to the #stanMsg object. */ NATS_EXTERN int64_t stanMsg_GetTimestamp(const stanMsg *msg); /** \brief Returns the message's redelivered flag. * * Returns the message's redelivered flag. This can help detect if this * message is a possible duplicate (due to redelivery and at-least-once * semantic). * * @param msg the pointer to the #stanMsg object. */ NATS_EXTERN bool stanMsg_IsRedelivered(const stanMsg *msg); /** \brief Returns the message payload. * * Returns the message payload, possibly `NULL`. * * Note that although the data sent and received from the server is not `NULL` * terminated, the NATS C Client does add a `NULL` byte to the received payload. * If you expect the received data to be a "string", then this conveniently * allows you to call #stanMsg_GetData() without having to copy the returned * data to a buffer to add the `NULL` byte at the end. * * \warning The string belongs to the message and must not be freed. * Copy it if needed. * * @param msg the pointer to the #stanMsg object. */ NATS_EXTERN const char* stanMsg_GetData(const stanMsg *msg); /** \brief Returns the message length. * * Returns the message's payload length, possibly 0. * * @param msg the pointer to the #stanMsg object. */ NATS_EXTERN int stanMsg_GetDataLength(const stanMsg *msg); /** \brief Destroys the message object. * * Destroys the message, freeing memory. * * @param msg the pointer to the #stanMsg object to destroy. */ NATS_EXTERN void stanMsg_Destroy(stanMsg *msg); /** @} */ // end of stanMsgGroup #endif /** \defgroup connGroup Connection * * NATS Connection * @{ */ /** \defgroup connMgtGroup Management * * Functions related to connection management. * @{ */ /** \brief Connects to a `NATS Server` using the provided options. * * Attempts to connect to a `NATS Server` with multiple options. * * This call is cloning the #natsOptions object. Once this call returns, * changes made to the `options` will not have an effect to this * connection. The `options` can however be changed prior to be * passed to another #natsConnection_Connect() call if desired. * * @see #natsOptions * @see #natsConnection_Destroy() * * @param nc the location where to store the pointer to the newly created * #natsConnection object. * @param options the options to use for this connection. If `NULL` * this call is equivalent to #natsConnection_ConnectTo() with #NATS_DEFAULT_URL. * */ NATS_EXTERN natsStatus natsConnection_Connect(natsConnection **nc, natsOptions *options); /** \brief Process a read event when using external event loop. * * When using an external event loop, and the callback indicating that * the socket is ready for reading, this call will read data from the * socket and process it. * * @param nc the pointer to the #natsConnection object. * * \warning This API is reserved for external event loop adapters. */ NATS_EXTERN void natsConnection_ProcessReadEvent(natsConnection *nc); /** \brief Process a write event when using external event loop. * * When using an external event loop, and the callback indicating that * the socket is ready for writing, this call will write data to the * socket. * * @param nc the pointer to the #natsConnection object. * * \warning This API is reserved for external event loop adapters. */ NATS_EXTERN void natsConnection_ProcessWriteEvent(natsConnection *nc); /** \brief Connects to a `NATS Server` using any of the URL from the given list. * * Attempts to connect to a `NATS Server`. * * This call supports multiple comma separated URLs. If more than one is * specified, it behaves as if you were using a #natsOptions object and * called #natsOptions_SetServers() with the equivalent array of URLs. * The list is randomized before the connect sequence starts. * * @see #natsConnection_Destroy() * @see #natsOptions_SetServers() * * @param nc the location where to store the pointer to the newly created * #natsConnection object. * @param urls the URL to connect to, or the list of URLs to chose from. * If `NULL` this call is equivalent to #natsConnection_ConnectTo() * with #NATS_DEFAULT_URL */ NATS_EXTERN natsStatus natsConnection_ConnectTo(natsConnection **nc, const char *urls); /** \brief Test if connection has been closed. * * Tests if connection has been closed. * * @param nc the pointer to the #natsConnection object. */ NATS_EXTERN bool natsConnection_IsClosed(natsConnection *nc); /** \brief Test if connection is reconnecting. * * Tests if connection is reconnecting. * * @param nc the pointer to the #natsConnection object. */ NATS_EXTERN bool natsConnection_IsReconnecting(natsConnection *nc); /** \brief Test if connection is draining. * * Tests if connection is draining. * * @param nc the pointer to the #natsConnection object. */ bool natsConnection_IsDraining(natsConnection *nc); /** \brief Returns the current state of the connection. * * Returns the current state of the connection. * * @see #natsConnStatus * * @param nc the pointer to the #natsConnection object. */ NATS_EXTERN natsConnStatus natsConnection_Status(natsConnection *nc); /** \brief Returns the number of bytes to be sent to the server. * * When calling any of the publish functions, data is not necessarily * immediately sent to the server. Some buffering occurs, allowing * for better performance. This function indicates if there is any * data not yet transmitted to the server. * * @param nc the pointer to the #natsConnection object. * @return the number of bytes to be sent to the server, or -1 if the * connection is closed. */ NATS_EXTERN int natsConnection_Buffered(natsConnection *nc); /** \brief Flushes the connection. * * Performs a round trip to the server and return when it receives the * internal reply. * * Note that if this call occurs when the connection to the server is * lost, the `PING` will not be echoed even if the library can connect * to a new (or the same) server. Therefore, in such situation, this * call will fail with the status #NATS_CONNECTION_DISCONNECTED. * * If the connection is closed while this call is in progress, then the * status #NATS_CONN_STATUS_CLOSED would be returned instead. * * @param nc the pointer to the #natsConnection object. */ NATS_EXTERN natsStatus natsConnection_Flush(natsConnection *nc); /** \brief Flushes the connection with a given timeout. * * Performs a round trip to the server and return when it receives the * internal reply, or if the call times-out (timeout is expressed in * milliseconds). * * See possible failure case described in #natsConnection_Flush(). * * @param nc the pointer to the #natsConnection object. * @param timeout in milliseconds, is the time allowed for the flush * to complete before #NATS_TIMEOUT error is returned. */ NATS_EXTERN natsStatus natsConnection_FlushTimeout(natsConnection *nc, int64_t timeout); /** \brief Returns the maximum message payload. * * Returns the maximum message payload accepted by the server. The * information is gathered from the `NATS Server` when the connection is * first established. * * @param nc the pointer to the #natsConnection object. * @return the maximum message payload. */ NATS_EXTERN int64_t natsConnection_GetMaxPayload(natsConnection *nc); /** \brief Gets the connection statistics. * * Copies in the provided statistics structure, a snapshot of the statistics for * this connection. * * @param nc the pointer to the #natsConnection object. * @param stats the pointer to a #natsStatistics object in which statistics * will be copied. */ NATS_EXTERN natsStatus natsConnection_GetStats(natsConnection *nc, natsStatistics *stats); /** \brief Gets the URL of the currently connected server. * * Copies in the given buffer, the connected server's Url. If the buffer is * too small, an error is returned. * * @param nc the pointer to the #natsConnection object. * @param buffer the buffer in which the URL is copied. * @param bufferSize the size of the buffer. */ NATS_EXTERN natsStatus natsConnection_GetConnectedUrl(natsConnection *nc, char *buffer, size_t bufferSize); /** \brief Gets the server Id. * * Copies in the given buffer, the connected server's Id. If the buffer is * too small, an error is returned. * * @param nc the pointer to the #natsConnection object. * @param buffer the buffer in which the server id is copied. * @param bufferSize the size of the buffer. */ NATS_EXTERN natsStatus natsConnection_GetConnectedServerId(natsConnection *nc, char *buffer, size_t bufferSize); /** \brief Returns the list of server URLs known to this connection. * * Returns the list of known servers, including additional servers * discovered after a connection has been established (with servers * version 0.9.2 and above). * * No credential information is included in any of the server URLs * returned by this call.
* If you want to use any of these URLs to connect to a server that * requires authentication, you will need to use #natsOptions_SetUserInfo * or #natsOptions_SetToken. * * \note The user is responsible for freeing the memory of the returned array. * * @param nc the pointer to the #natsConnection object. * @param servers the location where to store the pointer to the array * of server URLs. * @param count the location where to store the number of elements of the * returned array. */ NATS_EXTERN natsStatus natsConnection_GetServers(natsConnection *nc, char ***servers, int *count); /** \brief Returns the list of discovered server URLs. * * Unlike #natsConnection_GetServers, this function only returns * the list of servers that have been discovered after the a connection * has been established (with servers version 0.9.2 and above). * * No credential information is included in any of the server URLs * returned by this call.
* If you want to use any of these URLs to connect to a server that * requires authentication, you will need to use #natsOptions_SetUserInfo * or #natsOptions_SetToken. * * \note The user is responsible for freeing the memory of the returned array. * * @param nc the pointer to the #natsConnection object. * @param servers the location where to store the pointer to the array * of server URLs. * @param count the location where to store the number of elements of the * returned array. */ NATS_EXTERN natsStatus natsConnection_GetDiscoveredServers(natsConnection *nc, char ***servers, int *count); /** \brief Gets the last connection error. * * Returns the last known error as a 'natsStatus' and the location to the * null-terminated error string. * * \warning The returned string is owned by the connection object and * must not be freed. * * @param nc the pointer to the #natsConnection object. * @param lastError the location where the pointer to the connection's last * error string is copied. */ NATS_EXTERN natsStatus natsConnection_GetLastError(natsConnection *nc, const char **lastError); /** \brief Gets the current client ID assigned by the server. * * Returns the client ID assigned by the server to which the client is * currently connected to. * * \note The value may change if the client reconnects. * * This function returns #NATS_NO_SERVER_SUPPORT if the server's version * is less than 1.2.0. * * @param nc the pointer to the #natsConnection object. * @param cid the location where to store the client ID. */ NATS_EXTERN natsStatus natsConnection_GetClientID(natsConnection *nc, uint64_t *cid); /** \brief Drains the connection with default timeout. * * Drain will put a connection into a drain state. All subscriptions will * immediately be put into a drain state. Upon completion, the publishers * will be drained and can not publish any additional messages. Upon draining * of the publishers, the connection will be closed. Use the #natsOptions_SetClosedCB() * option to know when the connection has moved from draining to closed. * * This call uses a default drain timeout of 30 seconds. * * \warning This function does not block waiting for the draining operation * to complete. * * @see natsOptions_SetClosedCB * @see natsConnection_DrainTimeout * * @param nc the pointer to the #natsConnection object. */ NATS_EXTERN natsStatus natsConnection_Drain(natsConnection *nc); /** \brief Drains the connection with given timeout. * * Identical to #natsConnection_Drain but the timeout can be specified here. * * The value is expressed in milliseconds. Zero or negative value means * that the operation will not timeout. * * \warning This function does not block waiting for the draining operation * to complete. * * @see natsOptions_SetClosedCB * @see natsConnection_Drain * * @param nc the pointer to the #natsConnection object. * @param timeout the allowed time for a drain operation to complete, expressed * in milliseconds. */ NATS_EXTERN natsStatus natsConnection_DrainTimeout(natsConnection *nc, int64_t timeout); /** \brief Signs any 'message' using the connection's user credentials. * * The connection must have been created with the #natsOptions_SetUserCredentialsFromFiles. * * This call will sign the given message with the private key extracted through * the user credentials file(s). * * @param nc the pointer to the #natsConnection object. * @param message the byte array to sign. * @param messageLen the length of the given byte array. * @param sig an array of 64 bytes in which the signature will be copied. */ NATS_EXTERN natsStatus natsConnection_Sign(natsConnection *nc, const unsigned char *message, int messageLen, unsigned char sig[64]); /** \brief Returns the client's IP address as reported by the server. * * When a connection is created to the server, the server identifies * the connection's remote IP address and return it back to the client. * * \note The user is responsible to free memory allocated to store * the client IP address. * * \note This is supported on servers >= version 2.1.6. Calling * #natsConnection_GetClientIP() with server below this version will * return the #NATS_NO_SERVER_SUPPORT error. * * @see natsConnection_GetLocalIPAndPort to get the local IP and port instead. * * @param nc the pointer to the #natsConnection object. * @param ip the memory location where to store the client's IP string. * The user is responsible from freeing this memory. */ NATS_EXTERN natsStatus natsConnection_GetClientIP(natsConnection *nc, char **ip); /** \brief Returns the round trip time between this client and the server. * * The value returned is in nanoseconds. * * \note If the library is currently trying to reconnect, this call will * return #NATS_CONNECTION_DISCONNECTED. * * @param nc the pointer to the #natsConnection object. * @param rtt the memory location where to store the rtt. */ NATS_EXTERN natsStatus natsConnection_GetRTT(natsConnection *nc, int64_t *rtt); /** \brief Returns if the connection to current server supports headers. * * Returns NATS_OK if the server this client is currently connected to * supports headers, NATS_NO_SERVER_SUPPORT otherwise. * * @param nc the pointer to the #natsConnection object. */ NATS_EXTERN natsStatus natsConnection_HasHeaderSupport(natsConnection *nc); /** \brief Returns the connection local IP and port. * * Unlike #natsConnection_GetClientIP, this function returns the * connection's local IP and port. * * \note The user is responsible for freeing the memory allocated * for the returned IP string. * * @param nc the pointer of the #natsConnection object. * @param ip the memory location where to store the local IP string. * The user is responsible from freeing this memory. * @param port the memory location where to store the local port. * * @return #NATS_OK on success. * @return #NATS_CONNECTION_DISCONNECTED if disconnected. * @return #NATS_CONNECTION_CLOSED is connection is closed. * @return #NATS_SYS_ERROR if a system error getting the IP and port occurred. * @return #NATS_NO_MEMORY if the library was unable to allocate memory for the returned IP string. */ natsStatus natsConnection_GetLocalIPAndPort(natsConnection *nc, char **ip, int *port); /** \brief Closes the connection. * * Closes the connection to the server. This call will release all blocking * calls, such as #natsConnection_Flush() and #natsSubscription_NextMsg(). * The connection object is still usable until the call to * #natsConnection_Destroy(). * * @param nc the pointer to the #natsConnection object. */ NATS_EXTERN void natsConnection_Close(natsConnection *nc); /** \brief Destroys the connection object. * * Destroys the connection object, freeing up memory. * If not already done, this call first closes the connection to the server. * * @param nc the pointer to the #natsConnection object. */ NATS_EXTERN void natsConnection_Destroy(natsConnection *nc); /** @} */ // end of connMgtGroup /** \defgroup connPubGroup Publishing * * Publishing functions * @{ */ /** \brief Publishes data on a subject. * * Publishes the data argument to the given subject. The data argument is left * untouched and needs to be correctly interpreted on the receiver. * * @param nc the pointer to the #natsConnection object. * @param subj the subject the data is sent to. * @param data the data to be sent, can be `NULL`. * @param dataLen the length of the data to be sent. */ NATS_EXTERN natsStatus natsConnection_Publish(natsConnection *nc, const char *subj, const void *data, int dataLen); /** \brief Publishes a string on a subject. * * Convenient function to publish a string. This call is equivalent to: * * \code{.c} * const char* myString = "hello"; * * natsConnection_Publish(nc, subj, (const void*) myString, (int) strlen(myString)); * \endcode * * @param nc the pointer to the #natsConnection object. * @param subj the subject the data is sent to. * @param str the string to be sent. */ NATS_EXTERN natsStatus natsConnection_PublishString(natsConnection *nc, const char *subj, const char *str); /** \brief Publishes a message on a subject. * * Publishes the #natsMsg, which includes the subject, an optional reply and * optional data. * * @see #natsMsg_Create() * * @param nc the pointer to the #natsConnection object. * @param msg the pointer to the #natsMsg object to send. */ NATS_EXTERN natsStatus natsConnection_PublishMsg(natsConnection *nc, natsMsg *msg); /** \brief Publishes data on a subject expecting replies on the given reply. * * Publishes the data argument to the given subject expecting a response on * the reply subject. Use #natsConnection_Request() for automatically waiting * for a response inline. * * @param nc the pointer to the #natsConnection object. * @param subj the subject the request is sent to. * @param reply the reply on which resonses are expected. * @param data the data to be sent, can be `NULL`. * @param dataLen the length of the data to be sent. */ NATS_EXTERN natsStatus natsConnection_PublishRequest(natsConnection *nc, const char *subj, const char *reply, const void *data, int dataLen); /** \brief Publishes a string on a subject expecting replies on the given reply. * * Convenient function to publish a request as a string. This call is * equivalent to: * * \code{.c} * const char* myString = "hello"; * * natsPublishRequest(nc, subj, reply, (const void*) myString, (int) strlen(myString)); * \endcode * * @param nc the pointer to the #natsConnection object. * @param subj the subject the request is sent to. * @param reply the reply on which resonses are expected. * @param str the string to send. */ NATS_EXTERN natsStatus natsConnection_PublishRequestString(natsConnection *nc, const char *subj, const char *reply, const char *str); /** \brief Sends a request and waits for a reply. * * Sends a request payload and delivers the first response message, * or an error, including a timeout if no message was received properly. * * \warning If connected to a NATS Server v2.2.0+ with no responder running * when the request is received, this call will return a #NATS_NO_RESPONDERS error. * * @param replyMsg the location where to store the pointer to the received * #natsMsg reply. * @param nc the pointer to the #natsConnection object. * @param subj the subject the request is sent to. * @param data the data of the request, can be `NULL`. * @param dataLen the length of the data to send. * @param timeout in milliseconds, before this call returns #NATS_TIMEOUT * if no response is received in this alloted time. */ NATS_EXTERN natsStatus natsConnection_Request(natsMsg **replyMsg, natsConnection *nc, const char *subj, const void *data, int dataLen, int64_t timeout); /** \brief Sends a request (as a string) and waits for a reply. * * Convenient function to send a request as a string. This call is * equivalent to: * * \code{.c} * const char* myString = "hello"; * * natsConnection_Request(replyMsg, nc, subj, (const void*) myString, (int) strlen(myString)); * \endcode * * \warning See warning about no responders in #natsConnection_Request(). * * @param replyMsg the location where to store the pointer to the received * #natsMsg reply. * @param nc the pointer to the #natsConnection object. * @param subj the subject the request is sent to. * @param str the string to send. * @param timeout in milliseconds, before this call returns #NATS_TIMEOUT * if no response is received in this alloted time. */ NATS_EXTERN natsStatus natsConnection_RequestString(natsMsg **replyMsg, natsConnection *nc, const char *subj, const char *str, int64_t timeout); /** \brief Sends a request based on the given `requestMsg` and waits for a reply. * * Similar to #natsConnection_Request but uses `requestMsg` to extract subject, * and payload to send. * * \warning See warning about no responders in #natsConnection_Request(). * * @param replyMsg the location where to store the pointer to the received * #natsMsg reply. * @param nc the pointer to the #natsConnection object. * @param requestMsg the message used for the request. * @param timeout in milliseconds, before this call returns #NATS_TIMEOUT * if no response is received in this alloted time. */ NATS_EXTERN natsStatus natsConnection_RequestMsg(natsMsg **replyMsg, natsConnection *nc, natsMsg *requestMsg, int64_t timeout); /** @} */ // end of connPubGroup /** \defgroup connSubGroup Subscribing * * Subscribing functions. * @{ */ /** \brief Creates an asynchronous subscription. * * Expresses interest in the given subject. The subject can have wildcards * (see \ref wildcardsGroup). Messages will be delivered to the associated * #natsMsgHandler. * * @param sub the location where to store the pointer to the newly created * #natsSubscription object. * @param nc the pointer to the #natsConnection object. * @param subject the subject this subscription is created for. * @param cb the #natsMsgHandler callback. * @param cbClosure a pointer to an user defined object (can be `NULL`). See * the #natsMsgHandler prototype. */ NATS_EXTERN natsStatus natsConnection_Subscribe(natsSubscription **sub, natsConnection *nc, const char *subject, natsMsgHandler cb, void *cbClosure); /** \brief Creates an asynchronous subscription with a timeout. * * Expresses interest in the given subject. The subject can have wildcards * (see \ref wildcardsGroup). Messages will be delivered to the associated * #natsMsgHandler. * * If no message is received by the given timeout (in milliseconds), the * message handler is invoked with a `NULL` message.
* You can then destroy the subscription in the callback, or simply * return, in which case, the message handler will fire again when a * message is received or the subscription times-out again. * * \note Receiving a message reset the timeout. Until all pending messages * are processed, no timeout will occur. The timeout starts when the * message handler for the last pending message returns. * * \warning If you re-use message handler code between subscriptions with * and without timeouts, keep in mind that the message passed in the * message handler may be `NULL`. * * @param sub the location where to store the pointer to the newly created * #natsSubscription object. * @param nc the pointer to the #natsConnection object. * @param subject the subject this subscription is created for. * @param timeout the interval (in milliseconds) after which, if no message * is received, the message handler is invoked with a `NULL` message. * @param cb the #natsMsgHandler callback. * @param cbClosure a pointer to an user defined object (can be `NULL`). See * the #natsMsgHandler prototype. */ NATS_EXTERN natsStatus natsConnection_SubscribeTimeout(natsSubscription **sub, natsConnection *nc, const char *subject, int64_t timeout, natsMsgHandler cb, void *cbClosure); /** \brief Creates a synchronous subcription. * * Similar to #natsConnection_Subscribe, but creates a synchronous subscription * that can be polled via #natsSubscription_NextMsg(). * * @param sub the location where to store the pointer to the newly created * #natsSubscription object. * @param nc the pointer to the #natsConnection object. * @param subject the subject this subscription is created for. */ NATS_EXTERN natsStatus natsConnection_SubscribeSync(natsSubscription **sub, natsConnection *nc, const char *subject); /** \brief Creates an asynchronous queue subscriber. * * Creates an asynchronous queue subscriber on the given subject. * All subscribers with the same queue name will form the queue group and * only one member of the group will be selected to receive any given * message asynchronously. * * @param sub the location where to store the pointer to the newly created * #natsSubscription object. * @param nc the pointer to the #natsConnection object. * @param subject the subject this subscription is created for. * @param queueGroup the name of the group. * @param cb the #natsMsgHandler callback. * @param cbClosure a pointer to an user defined object (can be `NULL`). See * the #natsMsgHandler prototype. * */ NATS_EXTERN natsStatus natsConnection_QueueSubscribe(natsSubscription **sub, natsConnection *nc, const char *subject, const char *queueGroup, natsMsgHandler cb, void *cbClosure); /** \brief Creates an asynchronous queue subscriber with a timeout. * * Creates an asynchronous queue subscriber on the given subject. * All subscribers with the same queue name will form the queue group and * only one member of the group will be selected to receive any given * message asynchronously. * * If no message is received by the given timeout (in milliseconds), the * message handler is invoked with a `NULL` message.
* You can then destroy the subscription in the callback, or simply * return, in which case, the message handler will fire again when a * message is received or the subscription times-out again. * * \note Receiving a message reset the timeout. Until all pending messages * are processed, no timeout will occur. The timeout starts when the * message handler for the last pending message returns. * * \warning If you re-use message handler code between subscriptions with * and without timeouts, keep in mind that the message passed in the * message handler may be `NULL`. * * @param sub the location where to store the pointer to the newly created * #natsSubscription object. * @param nc the pointer to the #natsConnection object. * @param subject the subject this subscription is created for. * @param queueGroup the name of the group. * @param timeout the interval (in milliseconds) after which, if no message * is received, the message handler is invoked with a `NULL` message. * @param cb the #natsMsgHandler callback. * @param cbClosure a pointer to an user defined object (can be `NULL`). See * the #natsMsgHandler prototype. */ NATS_EXTERN natsStatus natsConnection_QueueSubscribeTimeout(natsSubscription **sub, natsConnection *nc, const char *subject, const char *queueGroup, int64_t timeout, natsMsgHandler cb, void *cbClosure); /** \brief Creates a synchronous queue subscriber. * * Similar to #natsConnection_QueueSubscribe, but creates a synchronous * subscription that can be polled via #natsSubscription_NextMsg(). * * @param sub the location where to store the pointer to the newly created * #natsSubscription object. * @param nc the pointer to the #natsConnection object. * @param subject the subject this subscription is created for. * @param queueGroup the name of the group. */ NATS_EXTERN natsStatus natsConnection_QueueSubscribeSync(natsSubscription **sub, natsConnection *nc, const char *subject, const char *queueGroup); /** @} */ // end of connSubGroup /** @} */ // end of connGroup /** \defgroup subGroup Subscription * * NATS Subscriptions. * @{ */ /** \brief Enables the No Delivery Delay mode. * * By default, messages that arrive are not immediately delivered. This * generally improves performance. However, in case of request-reply, * this delay has a negative impact. In such case, call this function * to have the subscriber be notified immediately each time a message * arrives. * * @param sub the pointer to the #natsSubscription object. * * \deprecated No longer needed. Will be removed in the future. */ NATS_EXTERN natsStatus natsSubscription_NoDeliveryDelay(natsSubscription *sub); /** \brief Returns the next available message. * * Return the next message available to a synchronous subscriber or block until * one is available. * A timeout (expressed in milliseconds) can be used to return when no message * has been delivered. If the value is zero, then this call will not wait and * return the next message that was pending in the client, and #NATS_TIMEOUT * otherwise. * * \note If you create a subscription for a subject used as the reply subject * of a #natsConnection_PublishRequest call (or any of its variant), and there * are no responders for the request subject, NATS Servers v2.2.0+ will return * an empty message with a header "Status" and value "503". The library v2.2.0 * until v2.4.1 would return this message to the user, which was wrong.
* The library now returns no message and #NATS_NO_RESPONDERS status. * * @param nextMsg the location where to store the pointer to the next available * message. * @param sub the pointer to the #natsSubscription object. * @param timeout time, in milliseconds, after which this call will return * #NATS_TIMEOUT if no message is available. */ NATS_EXTERN natsStatus natsSubscription_NextMsg(natsMsg **nextMsg, natsSubscription *sub, int64_t timeout); /** \brief Unsubscribes. * * Removes interest on the subject. Asynchronous subscription may still have * a callback in progress, in that case, the subscription will still be valid * until the callback returns. * * @param sub the pointer to the #natsSubscription object. */ NATS_EXTERN natsStatus natsSubscription_Unsubscribe(natsSubscription *sub); /** \brief Auto-Unsubscribes. * * This call issues an automatic #natsSubscription_Unsubscribe that is * processed by the server when 'max' messages have been received. * This can be useful when sending a request to an unknown number * of subscribers. * * @param sub the pointer to the #natsSubscription object. * @param max the maximum number of message you want this subscription * to receive. */ NATS_EXTERN natsStatus natsSubscription_AutoUnsubscribe(natsSubscription *sub, int max); /** \brief Gets the number of pending messages. * * Returns the number of queued messages in the client for this subscription. * * \deprecated Use #natsSubscription_GetPending instead. * * @param sub the pointer to the #natsSubscription object. * @param queuedMsgs the location where to store the number of queued messages. */ NATS_EXTERN natsStatus natsSubscription_QueuedMsgs(natsSubscription *sub, uint64_t *queuedMsgs); /** \brief Gets the subscription id. * * Returns the id of the given subscription. * * \note Invalid or closed subscriptions will cause a value of 0 to be returned. * * @param sub the pointer to the #natsSubscription object. */ NATS_EXTERN int64_t natsSubscription_GetID(natsSubscription* sub); /** \brief Gets the subject name. * * Returns the subject of the given subscription. * * \note Invalid or closed subscriptions will cause a value of NULL to be returned. * * \warning The string belongs to the subscription and must not be freed. Copy it if needed. * * @param sub the pointer to the #natsSubscription object. */ NATS_EXTERN const char* natsSubscription_GetSubject(natsSubscription* sub); /** \brief Sets the limit for pending messages and bytes. * * Specifies the maximum number and size of incoming messages that can be * buffered in the library for this subscription, before new incoming messages are * dropped and #NATS_SLOW_CONSUMER status is reported to the #natsErrHandler * callback (if one has been set). * * If no limit is set at the subscription level, the limit set by #natsOptions_SetMaxPendingMsgs * before creating the connection will be used. * * \note If no option is set, there is still a default of `65536` messages and * `65536 * 1024` bytes. * * @see natsOptions_SetMaxPendingMsgs * @see natsSubscription_GetPendingLimits * * @param sub he pointer to the #natsSubscription object. * @param msgLimit the limit in number of messages that the subscription can hold. * @param bytesLimit the limit in bytes that the subscription can hold. */ NATS_EXTERN natsStatus natsSubscription_SetPendingLimits(natsSubscription *sub, int msgLimit, int bytesLimit); /** \brief Returns the current limit for pending messages and bytes. * * Regardless if limits have been explicitly set with #natsSubscription_SetPendingLimits, * this call will store in the provided memory locations, the limits set for * this subscription. * * \note It is possible for `msgLimit` and/or `bytesLimits` to be `NULL`, in which * case the corresponding value is obviously not stored, but the function will * not return an error. * * @see natsOptions_SetMaxPendingMsgs * @see natsSubscription_SetPendingLimits * * @param sub the pointer to the #natsSubscription object. * @param msgLimit if not `NULL`, the memory location where to store the maximum * number of pending messages for this subscription. * @param bytesLimit if not `NULL`, the memory location where to store the maximum * size of pending messages for this subscription. */ NATS_EXTERN natsStatus natsSubscription_GetPendingLimits(natsSubscription *sub, int *msgLimit, int *bytesLimit); /** \brief Returns the number of pending messages and bytes. * * Returns the total number and size of pending messages on this subscription. * * \note It is possible for `msgs` and `bytes` to be NULL, in which case the * corresponding values are obviously not stored, but the function will not return * an error. * * @param sub the pointer to the #natsSubscription object. * @param msgs if not `NULL`, the memory location where to store the number of * pending messages. * @param bytes if not `NULL`, the memory location where to store the total size of * pending messages. */ NATS_EXTERN natsStatus natsSubscription_GetPending(natsSubscription *sub, int *msgs, int *bytes); /** \brief Returns the number of delivered messages. * * Returns the number of delivered messages for this subscription. * * @param sub the pointer to the #natsSubscription object. * @param msgs the memory location where to store the number of * delivered messages. */ NATS_EXTERN natsStatus natsSubscription_GetDelivered(natsSubscription *sub, int64_t *msgs); /** \brief Returns the number of dropped messages. * * Returns the number of known dropped messages for this subscription. This happens * when a consumer is not keeping up and the library starts to drop messages * when the maximum number (and/or size) of pending messages has been reached. * * \note If the server declares the connection a slow consumer, this number may * not be valid. * * @see natsOptions_SetMaxPendingMsgs * @see natsSubscription_SetPendingLimits * * @param sub the pointer to the #natsSubscription object. * @param msgs the memory location where to store the number of dropped messages. */ NATS_EXTERN natsStatus natsSubscription_GetDropped(natsSubscription *sub, int64_t *msgs); /** \brief Returns the maximum number of pending messages and bytes. * * Returns the maximum of pending messages and bytes seen so far. * * \note `msgs` and/or `bytes` can be NULL. * * @param sub the pointer to the #natsSubscription object. * @param msgs if not `NULL`, the memory location where to store the maximum * number of pending messages seen so far. * @param bytes if not `NULL`, the memory location where to store the maximum * number of bytes pending seen so far. */ NATS_EXTERN natsStatus natsSubscription_GetMaxPending(natsSubscription *sub, int *msgs, int *bytes); /** \brief Clears the statistics regarding the maximum pending values. * * Clears the statistics regarding the maximum pending values. * * @param sub the pointer to the #natsSubscription object. */ NATS_EXTERN natsStatus natsSubscription_ClearMaxPending(natsSubscription *sub); /** \brief Get various statistics from this subscription. * * This is a convenient function to get several subscription's statistics * in one call. * * \note Any or all of the statistics pointers can be `NULL`. * * @see natsSubscription_GetPending * @see natsSubscription_GetMaxPending * @see natsSubscription_GetDelivered * @see natsSubscription_GetDropped * * @param sub the pointer to the #natsSubscription object. * @param pendingMsgs if not `NULL`, memory location where to store the * number of pending messages. * @param pendingBytes if not `NULL`, memory location where to store the * total size of pending messages. * @param maxPendingMsgs if not `NULL`, memory location where to store the * maximum number of pending messages seen so far. * @param maxPendingBytes if not `NULL`, memory location where to store the * maximum total size of pending messages seen so far. * @param deliveredMsgs if not `NULL`, memory location where to store the * number of delivered messages. * @param droppedMsgs if not `NULL`, memory location where to store the * number of dropped messages. */ NATS_EXTERN natsStatus natsSubscription_GetStats(natsSubscription *sub, int *pendingMsgs, int *pendingBytes, int *maxPendingMsgs, int *maxPendingBytes, int64_t *deliveredMsgs, int64_t *droppedMsgs); /** \brief Checks the validity of the subscription. * * Returns a boolean indicating whether the subscription is still active. * This will return false if the subscription has already been closed, * or auto unsubscribed. * * @param sub the pointer to the #natsSubscription object. */ NATS_EXTERN bool natsSubscription_IsValid(natsSubscription *sub); /** \brief Drains the subscription with a default timeout. * * Drain will remove interest but continue to invoke callbacks until all messages * have been processed. * * This call uses a default drain timeout of 30 seconds. See #natsSubscription_DrainTimeout * for details on behavior when timeout elapses. * * \warning This function does not block waiting for the operation * to complete. To synchronously wait, see #natsSubscription_WaitForDrainCompletion * * @see natsSubscription_DrainTimeout * @see natsSubscription_WaitForDrainCompletion * @see natsSubscription_DrainCompletionStatus * * @param sub the pointer to the #natsSubscription object. */ NATS_EXTERN natsStatus natsSubscription_Drain(natsSubscription *sub); /** \brief Drains the subscription with the specified timeout. * * Drain will remove interest but continue to invoke callbacks until all messages * have been processed, or the specified timeout has elapsed. In that case, the * subscription will be forcibly closed and remaining pending messages (if any) * will not be processed. * * The timeout is expressed in milliseconds. Zero or negative value means that * the call will not timeout, but see below for more details. * * When this call returns, the UNSUBSCRIBE protocol for this subscription has * been enqueued to the outgoing connection buffer, but not sent to the server, * ensuring that this call does not block. * * The library then asynchronously ensures that this protocol is sent and waits * for a confirmation from the server. After that, it is guaranteed that no * new message for this subscription will be received and the library can proceed * with the rest of the draining. * * However, should the "flush" of the protocol fail, the library will ensure that * no new message is added to the subscription (in the event the server did not * receive the UNSUBSCRIBE protocol and still attempts to deliver messages), and * will proceed with the draining of the pending messages. Users can check the * status of the draining after it has completed by calling #natsSubscription_DrainCompletionStatus. * * If no timeout is specified (that is, value is zero or negative), a timeout * will be used for the "flush" of the protocol. Again, even in case of failure, * the draining will proceed. * * If a timeout is specified, the complete process: "flush" of the protocol * and draining of messages, must happen before the timeout elapses otherwise the * subscription will be forcibly closed, and not all message callbacks may be invoked. * * Regardless of the presence of a timeout or not, should the subscription or connection * be closed while draining occurs, the draining process will stop. The * #natsSubscription_WaitForDrainCompletion call will not report an error. To * know if an error occurred, the user can call #natsSubscription_DrainCompletionStatus * after ensuring that the drain has completed. * * \warning This function does not block waiting for the operation * to complete. To synchronously wait, see #natsSubscription_WaitForDrainCompletion * * @see natsSubscription_Drain * @see natsSubscription_WaitForDrainCompletion * @see natsSubscription_DrainCompletionStatus * * @param sub the pointer to the #natsSubscription object. * @param timeout how long to wait for the operation to complete, expressed in * milliseconds. If the timeout elapses the subscription will be closed. */ NATS_EXTERN natsStatus natsSubscription_DrainTimeout(natsSubscription *sub, int64_t timeout); /** \brief Blocks until the drain operation completes. * * This function blocks until the subscription is fully drained. * Returns no error if the subscription is drained or closed, otherwise * returns the error if the subscription was not in drained mode (#NATS_ILLEGAL_STATE) * or if this subscription was not drained or closed prior to the specified * timeout (#NATS_TIMEOUT). * * The timeout is expressed in milliseconds. Zero or negative value * means that the call will not timeout. * * Note that if this call times-out, it does not mean that the drain stops. * The drain will continue until its own timeout elapses. * * @see natsSubscription_Drain * @see natsSubscription_DrainTimeout * @see natsSubscription_DrainCompletionStatus * * @param sub the pointer to the #natsSubscription object. * @param timeout how long to wait for the operation to complete, expressed in * milliseconds. */ NATS_EXTERN natsStatus natsSubscription_WaitForDrainCompletion(natsSubscription *sub, int64_t timeout); /** \brief Returns the status of the drain after completion. * * Once the drain has completed, users can use this function to know if the * drain completed successfully or not. * * Possible return values (the list is not exhaustive): * * NATS_OK the library sent the UNSUBSCRIBE protocol and finished processing * all messages that were pending.
* NATS_ILLEGAL_STATE this call was made for a subscription that had not * started draining or the draining is still in progress.
* NATS_INVALID_SUBSCRIPTION the subscription was closed while draining, * which means that some messages may not have been processed.
* NATS_CONNECTION_CLOSED the connection was closed while draining, which * means that some messages may not have been processed. * * \note This call does not wait for the drain completion (see #natsSubscription_WaitForDrainCompletion * for that). * * @see natsSubscription_Drain * @see natsSubscription_DrainTimeout * @see natsSubscription_WaitForDrainCompletion * * @param sub the pointer to the #natsSubscription object. */ NATS_EXTERN natsStatus natsSubscription_DrainCompletionStatus(natsSubscription *sub); /** \brief Sets a completion callback. * * In order to make sure that an asynchronous subscription's message handler is no longer invoked once the * subscription is closed (#natsSubscription_Unsubscribe), the subscription should be closed from the * message handler itslef. * * If the application closes the subscription from a different thread and immediately frees resources * needed in the message handler, there is a risk of a crash since the subscription's message handler * may still be invoked one last time or already in the process of executing. * * To address this, the user can set a callback that will be invoked after the subscription is closed and the * message handler has returned. This applies to asynchronous subscriptions using their own dispatcher or using * the library's delivery thread pool. * * \note You don't need to call this function if you are not freeing resources needed in the message handler or if * you always close the subscription from the message handler itself. * * \note If you plan on calling this function, you should do so before calling #natsSubscription_AutoUnsubscribe, since * there is a risk that the subscription be removed as soon as #natsSubscription_AutoUnsubscribe returns. * * Calling this function on a synchronous or closed subscription will return #NATS_INVALID_SUBSCRIPTION. * * @see natsOnCompleteCB * * @param sub the pointer to the #natsSubscription object * @param cb the callback to invoke when the last message of a closed subscription has been dispatched * @param closure the pointer to a user defined object (possibly `NULL`) that will be passed to the callback */ NATS_EXTERN natsStatus natsSubscription_SetOnCompleteCB(natsSubscription *sub, natsOnCompleteCB cb, void *closure); /** \brief Destroys the subscription. * * Destroys the subscription object, freeing up memory. * If not already done, this call will removes interest on the subject. * * @param sub the pointer to the #natsSubscription object to destroy. */ NATS_EXTERN void natsSubscription_Destroy(natsSubscription *sub); /** @} */ // end of subGroup #if defined(NATS_HAS_STREAMING) /** \defgroup stanConnGroup Streaming Connection * * NATS Streaming Connection * @{ */ /** \defgroup stanConnMgtGroup Management * * Functions related to connection management. * @{ */ /** \brief Connects to a `NATS Streaming Server` using the provided options. * * Attempts to connect to a `NATS Streaming Server`. * * This call is cloning the #stanConnOptions object, if given. Once this call returns, * changes made to the `options` will not have an effect to this connection. * The `options` can however be changed prior to be passed to another * #stanConnection_Connect() call if desired. * * \note The Streaming connection does not honor the NATS Connection option * #natsOptions_SetRetryOnFailedConnect(). If you pass NATS Options with * this option enabled, no error is returned, but if the connection cannot * be established "right away", the connect call will return an error. * * \warning If connecting to a NATS Server v2.2.0+ and there is no Streaming server * listening on the connect request subject, this call will return #NATS_NO_RESPONDERS, * not #NATS_TIMEOUT. * * @see #stanConnOptions * @see #stanConnection_Destroy() * * @param sc the location where to store the pointer to the newly created * #natsConnection object. * @param clusterID the name of the cluster this connection is for. * @param clientID the client ID for this connection. Only one connection * with this ID will be accepted by the server. Use only a-zA-Z0-9_- characters. * @param options the options to use for this connection (can be `NULL`). */ NATS_EXTERN natsStatus stanConnection_Connect(stanConnection **sc, const char *clusterID, const char *clientID, stanConnOptions *options); /** \brief Returns the underlying NATS Connection. * * This can be used if the application needs to do non streaming messaging * but does not want to create a separate NATS Connection. * * Obtain a NATS connection from a NATS streaming connection. The NATS * connection can be used to perform regular NATS operations, but it is owned * and managed by the NATS streaming connection. It cannot be closed, * which will happen when the NATS streaming connection is closed. * * \note For each call to this function, the user must call * #stanConnection_ReleaseNATSConnection() when access to the NATS Connection * is no longer needed. * * \warning The returned connection cannot be closed, drained nor destroyed. * Calling corresponding functions will have no effect or return #NATS_ILLEGAL_STATE. * * @see stanConnection_ReleaseNATSConnection() * * @param sc the pointer to the #stanConnection object. * @param nc the location where to store the pointer of the #natsConnection object. */ NATS_EXTERN natsStatus stanConnection_GetNATSConnection(stanConnection *sc, natsConnection **nc); /** \brief Releases the NATS Connection. * * This should be paired with the #stanConnection_GetNATSConnection() call. * That is, after getting a reference to the underlying NATS Connection and * once that connection is no longer needed, calling this function will * allow resources to be properly released when the streaming connection is destroyed. * * You would normally call #stanConnection_GetNATSConnection() and this function * only once. * * After the last #stanConnection_ReleaseNATSConnection() call is made, you * must no longer use the NATS Connection because if #stanConnection_Destroy() * is called, that could make the pointer to the NATS Connection invalid. * * \note If the streaming connection is closed/destroyed before the last * call to #stanConnection_ReleaseNATSConnection, the pointer to the NATS * connection will still be valid, although all calls will fail since the * connection is now closed. Calling this function will release the streaming * object allowing memory to be freed. * * @see stanConnection_GetNATSConnection * * @param sc the pointer to the #stanConnection object. */ NATS_EXTERN void stanConnection_ReleaseNATSConnection(stanConnection *sc); /** \brief Closes the connection. * * Closes the connection to the server. This call will release all blocking * calls. The connection object is still usable until the call to * #stanConnection_Destroy(). * * \warning See warning about connecting to a NATS Server v2.2.0+ in #stanConnection_Connect(). * * @param sc the pointer to the #stanConnection object. */ NATS_EXTERN natsStatus stanConnection_Close(stanConnection *sc); /** \brief Destroys the connection object. * * Destroys the connection object, freeing up memory. * If not already done, this call first closes the connection to the server. * * @param sc the pointer to the #stanConnection object. */ NATS_EXTERN natsStatus stanConnection_Destroy(stanConnection *sc); /** @} */ // end of stanConnMgtGroup /** \defgroup stanConnPubGroup Publishing * * Publishing functions * @{ */ /** \brief Publishes data on a channel. * * Publishes the data argument to the given channel. The data argument is left * untouched and needs to be correctly interpreted on the receiver. * * @param sc the pointer to the #stanConnection object. * @param channel the channel name the data is sent to. * @param data the data to be sent, can be `NULL`. * @param dataLen the length of the data to be sent. */ NATS_EXTERN natsStatus stanConnection_Publish(stanConnection *sc, const char *channel, const void *data, int dataLen); /** \brief Asynchronously publishes data on a channel. * * Publishes the data argument to the given channel. The data argument is left * untouched and needs to be correctly interpreted on the receiver. * * This function does not wait for an acknowledgment back from the server. * Instead, the library will invoke the provided callback when that acknowledgment * comes. * * In order to correlate the acknowledgment with the published message, you * can use the `ahClosure` since this will be passed to the #stanPubAckHandler * on every invocation. In other words, you should use a unique closure for * each published message. * * @param sc the pointer to the #natsConnection object. * @param channel the channel name the data is sent to. * @param data the data to be sent, can be `NULL`. * @param dataLen the length of the data to be sent. * @param ah the publish acknowledgment callback. If `NULL` the user will not * be notified of the publish result. * @param ahClosure the closure the library will pass to the `ah` callback if * one has been set. */ NATS_EXTERN natsStatus stanConnection_PublishAsync(stanConnection *sc, const char *channel, const void *data, int dataLen, stanPubAckHandler ah, void *ahClosure); /** @} */ // end of stanConnPubGroup /** \defgroup stanConnSubGroup Subscribing * * Subscribing functions. * @{ */ /** \brief Creates a subscription. * * Expresses interest in the given subject. The subject can NOT have wildcards. * Messages will be delivered to the associated #stanMsgHandler. * * \warning See warning about connecting to a NATS Server v2.2.0+ in #stanConnection_Connect(). * * @param sub the location where to store the pointer to the newly created * #natsSubscription object. * @param sc the pointer to the #natsConnection object. * @param channel the channel this subscription is created for. * @param cb the #stanMsgHandler callback. * @param cbClosure a pointer to an user defined object (can be `NULL`). See * the #stanMsgHandler prototype. * @param options the optional to further configure the subscription. */ NATS_EXTERN natsStatus stanConnection_Subscribe(stanSubscription **sub, stanConnection *sc, const char *channel, stanMsgHandler cb, void *cbClosure, stanSubOptions *options); /** \brief Creates a queue subscription. * * Creates a queue subscriber on the given channel. * All subscribers with the same queue name will form the queue group and * only one member of the group will be selected to receive any given * message asynchronously. * * \warning See warning about connecting to a NATS Server v2.2.0+ in #stanConnection_Connect(). * * @param sub the location where to store the pointer to the newly created * #natsSubscription object. * @param sc the pointer to the #natsConnection object. * @param channel the channel name this subscription is created for. * @param queueGroup the name of the group. * @param cb the #natsMsgHandler callback. * @param cbClosure a pointer to an user defined object (can be `NULL`). See * the #natsMsgHandler prototype. * @param options the optional options to further configure this queue subscription. */ NATS_EXTERN natsStatus stanConnection_QueueSubscribe(stanSubscription **sub, stanConnection *sc, const char *channel, const char *queueGroup, stanMsgHandler cb, void *cbClosure, stanSubOptions *options); /** @} */ // end of stanConnSubGroup /** @} */ // end of stanConnGroup /** \defgroup stanSubGroup Streaming Subscription * * NATS Streaming Subscriptions. * @{ */ /** \brief Sets a completion callback. * * In order to make sure that an asynchronous subscription's message handler is no longer invoked once the * subscription is closed (or unsubscribed) (#stanSubscription_Close, #stanSubscription_Unsubscribe), the * subscription should be closed from the message handler itslef. * * If the application closes the subscription from a different thread and immediately frees resources * needed in the message handler, there is a risk of a crash since the subscription's message handler * may still be invoked one last time or already in the process of executing. * * To address this, the user can set a callback that will be invoked after the subscription is closed and the * message handler has returned. * * \note You don't need to call this function if you are not freeing resources needed in the message handler or if * you always close the subscription from the message handler itself. * * @see natsOnCompleteCB * * @param sub the pointer to the #stanSubscription object * @param cb the callback to invoke when the last message of a closed subscription has been dispatched * @param closure the pointer to a user defined object (possibly `NULL`) that will be passed to the callback */ NATS_EXTERN natsStatus stanSubscription_SetOnCompleteCB(stanSubscription *sub, natsOnCompleteCB cb, void *closure); /** \brief Acknowledge a message. * * If the subscription is created with manual acknowledgment mode (see #stanSubOptions_SetManualAckMode) * then it is the user responsibility to acknowledge received messages when * appropriate. * * @param sub the pointer to the #stanSubscription object. * @param msg the message to acknowledge. */ NATS_EXTERN natsStatus stanSubscription_AckMsg(stanSubscription *sub, stanMsg *msg); /** \brief Permanently remove a subscription. * * Removes interest on the channel. The subscription may still have * a callback in progress, in that case, the subscription will still be valid * until the callback returns. * * For non-durable subscriptions, #stanSubscription_Unsubscribe and #stanSubscription_Close * have the same effect. * * For durable subscriptions, calling this function causes the server * to remove the durable subscription (instead of simply suspending it). * It means that once this call is made, calling #stanConnection_Subscribe() with * the same durable name creates a brand new durable subscription, instead * of simply resuming delivery. * * \warning See warning about connecting to a NATS Server v2.2.0+ in #stanConnection_Connect(). * * @param sub the pointer to the #stanSubscription object. */ NATS_EXTERN natsStatus stanSubscription_Unsubscribe(stanSubscription *sub); /** \brief Closes the subscription. * * Similar to #stanSubscription_Unsubscribe() except that durable interest * is not removed in the server. The durable subscription can therefore be * resumed. * * \warning See warning about connecting to a NATS Server v2.2.0+ in #stanConnection_Connect(). * * @param sub the pointer to the #stanSubscription object. */ NATS_EXTERN natsStatus stanSubscription_Close(stanSubscription *sub); /** \brief Destroys the subscription. * * Destroys the subscription object, freeing up memory. * If not already done, this call will removes interest on the subject. * * @param sub the pointer to the #stanSubscription object to destroy. */ NATS_EXTERN void stanSubscription_Destroy(stanSubscription *sub); /** @} */ // end of stanSubGroup #endif /** \defgroup jsGroup JetStream * * JetStream. * @{ */ /** \brief Initializes a streaming context options structure. * * Use this before setting specific stream context options and passing it * to JetStream APIs. * * @param opts the pointer to the #jsOptions to initialize. */ NATS_EXTERN natsStatus jsOptions_Init(jsOptions *opts); /** \brief Returns a new JetStream context. * * A JetStream context is used for messaging and assets management. * * Since the underlying NATS connection is used for communication, the NATS connection * should stay valid while using the JetStream context. That is, do not close/destroy * the NATS connection before destroying the JetStream context. * * \note When done, the context should be destroyed to release memory. * * @param js the location where to store the pointer to the newly created #jsCtx object. * @param nc the pointer to the #natsConnection object from which to get the JetStream context. * @param opts the pointer to the #jsOptions object, possibly `NULL`. */ NATS_EXTERN natsStatus natsConnection_JetStream(jsCtx **js, natsConnection *nc, jsOptions *opts); /** \brief Destroys the JetStream context. * * Releases memory used by the context object. * * @param js the pointer to the #jsCtx object to destroy. */ NATS_EXTERN void jsCtx_Destroy(jsCtx *js); /** \defgroup jsAssetsGroup JetStream Assets Management * * JetStream Assets Management * @{ */ /** \brief Initializes a streaming configuration structure. * * Use this before setting specific stream configuration options and passing this * configuration to some of the stream management APIs. * * @param cfg the pointer to the #jsStreamConfig to initialize. */ NATS_EXTERN natsStatus jsStreamConfig_Init(jsStreamConfig *cfg); /** \brief Initializes a placement configuration structure. * * Use this before setting specific stream placement options. * * @param placement the pointer to the #jsPlacement to initialize. */ NATS_EXTERN natsStatus jsPlacement_Init(jsPlacement *placement); /** \brief Initializes a stream source configuration structure. * * Use this before setting specific stream source options. * * @param source the pointer to the #jsStreamSource to initialize. */ NATS_EXTERN natsStatus jsStreamSource_Init(jsStreamSource *source); /** \brief Initializes an external stream configuration structure. * * Use this before setting specific external stream options. * * @param external the pointer to the #jsExternalStream to initialize. */ NATS_EXTERN natsStatus jsExternalStream_Init(jsExternalStream *external); /** \brief Initializes a republish structure. * * Use this to set the source, destination and/or headers only for a stream re-publish. * * @param rp the pointer to the #jsRePublish to initialize. */ NATS_EXTERN natsStatus jsRePublish_Init(jsRePublish *rp); /** \brief Creates a stream. * * Creates a stream based on the provided configuration (that cannot be `NULL`). * The name is mandatory and cannot contain . characters. * * \note If you do not need a #jsStreamInfo to be returned, you can pass `NULL`, * otherwise, on success you are responsible for freeing this object. * * @see jsStreamConfig_Init * @see jsStreamInfo_Destroy * * @param si the location where to store the pointer to the new #jsStreamInfo object in * response to the creation request, or `NULL` if the stream information is not needed. * @param js the pointer to the #jsCtx context. * @param cfg the pointer to the #jsStreamConfig. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_AddStream(jsStreamInfo **si, jsCtx *js, jsStreamConfig *cfg, jsOptions *opts, jsErrCode *errCode); /** \brief Updates a stream. * * Updates a stream based on the provided configuration (that cannot be `NULL`). * The name is mandatory and cannot contain . characters. * * \note If you do not need a #jsStreamInfo to be returned, you can pass `NULL`, * otherwise, on success you are responsible for freeing this object. * * @see jsStreamConfig_Init * @see jsStreamInfo_Destroy * * @param si the location where to store the pointer to the new #jsStreamInfo object in * response to the creation request, or `NULL` if the stream information is not needed. * @param js the pointer to the #jsCtx context. * @param cfg the pointer to the #jsStreamConfig. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_UpdateStream(jsStreamInfo **si, jsCtx *js, jsStreamConfig *cfg, jsOptions *opts, jsErrCode *errCode); /** \brief Purges a stream. * * Purges the stream named stream. * * For more advanced purge options, you can specify them through #jsOptions. * * \code{.unparsed} * jsOptions o; * * jsOptions_Init(&o); * o.Stream.Purge.Subject = "foo"; * o.Stream.Purge.Sequence = 4; * * js_PurgeStream(js, "MY_STREAM", &o, &jerr); * \endcode * * @param js the pointer to the #jsCtx context. * @param stream the name of the stream to purge. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_PurgeStream(jsCtx *js, const char *stream, jsOptions *opts, jsErrCode *errCode); /** \brief Deletes a stream. * * Deletes the stream named stream. * * @param js the pointer to the #jsCtx context. * @param stream the name of the stream to delete. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_DeleteStream(jsCtx *js, const char *stream, jsOptions *opts, jsErrCode *errCode); /** \brief Retrieves a JetStream message from the stream by sequence. * * Retrieves a raw stream message stored in JetStream by sequence number. * * \note The message needs to be destroyed by calling #natsMsg_Destroy. * * @see js_GetLastMsg * @see natsMsg_Destroy * * @param msg the memory location where the library will store the pointer to the #natsMsg. * @param js the pointer to the #jsCtx context. * @param stream the name of the stream. * @param seq the sequence in the stream of the message being retrieved. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_GetMsg(natsMsg **msg, jsCtx *js, const char *stream, uint64_t seq, jsOptions *opts, jsErrCode *errCode); /** \brief Retrieves the last JetStream message from the stream for a given subject. * * Retrieves the last JetStream message from the stream for a given subject. * * \note The message needs to be destroyed by calling #natsMsg_Destroy. * * @see js_GetMsg * @see natsMsg_Destroy * * @param msg the memory location where the library will store the pointer to the #natsMsg. * @param js the pointer to the #jsCtx context. * @param stream the name of the stream. * @param subject the subject for which the last message is being retrieved. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_GetLastMsg(natsMsg **msg, jsCtx *js, const char *stream, const char *subject, jsOptions *opts, jsErrCode *errCode); /** \brief Initializes a direct get message options structure. * * Use this before setting specific direct get message options and passing it * to #js_DirectGetMsg API. * * @param opts the pointer to the #jsDirectGetMsgOptions object. */ NATS_EXTERN natsStatus jsDirectGetMsgOptions_Init(jsDirectGetMsgOptions *opts); /** \brief Retrieves directly a JetStream message based on provided options. * * If a stream is created with `AllowDirect`, it is possible to retrieve a message * without going through the leader. * * To specify the options, call #jsDirectGetMsgOptions_Init first and the set * the appropriate options, then invoke this function. * * \note Some options are mutually exclusive but the library is not doing the * check and leave it to the server to do it and return the error returned by * the server. * * \note This API can only be used against servers that support the direct * get feature, which is `v2.9.0+`. If running against an older server the * call will likely timeout. * * @param msg the location where to store the pointer to the retrieved message. * @param js the pointer to the #jsCtx context. * @param stream the name of the stream. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param dgOpts the pointer to the #jsDirectGetMsgOptions object, cannot be `NULL`. */ NATS_EXTERN natsStatus js_DirectGetMsg(natsMsg **msg, jsCtx *js, const char *stream, jsOptions *opts, jsDirectGetMsgOptions *dgOpts); /** \brief Deletes a message from the stream. * * Deletes the message at sequence seq in the stream named stream. * * \note To completely erase the content of the deleted message when stored on disk, * use #js_EraseMsg instead. * * @see js_EraseMsg * * @param js the pointer to the #jsCtx context. * @param stream the name of the stream. * @param seq the sequence in the stream of the message to delete. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_DeleteMsg(jsCtx *js, const char *stream, uint64_t seq, jsOptions *opts, jsErrCode *errCode); /** \brief Erases a message from the stream. * * Similar to #js_DeleteMsg except that the content of the deleted message is * erased from stable storage. * * @see js_DeleteMsg * * @param js the pointer to the #jsCtx context. * @param stream the name of the stream. * @param seq the sequence in the stream of the message to erase. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_EraseMsg(jsCtx *js, const char *stream, uint64_t seq, jsOptions *opts, jsErrCode *errCode); /** \brief Retreives information from a stream. * * Returns information about the stream named stream. * * \note You need to free the returned object. * * To get some detailed information about deleted messages, set this option: * * \code{.unparsed} * jsOptions o; * * jsOptions_Init(&o); * o.Stream.Info.DeletedDetails = true; * js_GetStreamInfo(&si, js, "MY_STREAM", &o, &jerr); * \endcode * * @see jsStreamInfo_Destroy * * @param si the location where to store the pointer to the new #jsStreamInfo object in * response to the creation request. * @param js the pointer to the #jsCtx context. * @param stream the name of the stream which information is retrieved. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_GetStreamInfo(jsStreamInfo **si, jsCtx *js, const char *stream, jsOptions *opts, jsErrCode *errCode); /** \brief Destroys the stream information object. * * Releases memory allocated for this stream information object. * * @param si the pointer to the #jsStreamInfo object. */ NATS_EXTERN void jsStreamInfo_Destroy(jsStreamInfo *si); /** \brief Retrieves the list of all available streams. * * Retrieves the list of all #jsStreamInfo. It is possible to filter * which streams are to be retrieved based on a subject filter. * * \warning The list should be destroyed when no longer used by * calling #jsStreamInfoList_Destroy. * * @param list the location where to store the pointer to the new #jsStreamInfoList object. * @param js the pointer to the #jsCtx context. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_Streams(jsStreamInfoList **list, jsCtx *js, jsOptions *opts, jsErrCode *errCode); /** \brief Destroys the stream information list object. * * Releases memory allocated for this stream information list. * * \warning All #jsStreamInfo pointers contained in the list will * be destroyed by this call. * * @param list the pointer to the #jsStreamInfoList object. */ NATS_EXTERN void jsStreamInfoList_Destroy(jsStreamInfoList *list); /** \brief Retrieves the list of all available stream names. * * Retrieves the list of all stream names. It is possible to filter * which streams are to be retrieved based on a subject filter. * * \warning The list should be destroyed when no longer used by * calling #jsStreamNamesList_Destroy. * * @param list the location where to store the pointer to the new #jsStreamNamesList object. * @param js the pointer to the #jsCtx context. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_StreamNames(jsStreamNamesList **list, jsCtx *js, jsOptions *opts, jsErrCode *errCode); /** \brief Destroys the stream names list object. * * Releases memory allocated for this list of stream names. * * \warning All string pointers contained in the list will * be destroyed by this call. * * @param list the pointer to the #jsStreamNamesList object. */ NATS_EXTERN void jsStreamNamesList_Destroy(jsStreamNamesList *list); /** \brief Initializes a consumer configuration structure. * * Use this before adding a consumer. * * @see #jsConsumerConfig * * @param cc the pointer to the #jsConsumerConfig to initialize. */ NATS_EXTERN natsStatus jsConsumerConfig_Init(jsConsumerConfig *cc); /** \brief Adds a JetStream consumer. * * Adds a consumer based on the provided configuration (that cannot be `NULL`). * * \note If you do not need a #jsConsumerInfo to be returned, you can pass `NULL`, * otherwise, on success you are responsible for freeing this object. * * @see jsConsumerConfig_Init * @see jsConsumerInfo_Destroy * * @param ci the location where to store the pointer to the new #jsConsumerInfo object in * response to the creation request, or `NULL` if the consumer information is not needed. * @param js the pointer to the #jsCtx context. * @param stream the name of the stream. * @param cfg the pointer to the #jsConsumerConfig. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_AddConsumer(jsConsumerInfo **ci, jsCtx *js, const char *stream, jsConsumerConfig *cfg, jsOptions *opts, jsErrCode *errCode); /** \brief Updates a JetStream consumer. * * Updates a consumer based on the provided configuration (that cannot be `NULL`). * * \note If you do not need a #jsConsumerInfo to be returned, you can pass `NULL`, * otherwise, on success you are responsible for freeing this object. * * @see jsConsumerConfig_Init * @see jsConsumerInfo_Destroy * * @param ci the location where to store the pointer to the new #jsConsumerInfo object in * response to the creation request, or `NULL` if the consumer information is not needed. * @param js the pointer to the #jsCtx context. * @param stream the name of the stream. * @param cfg the pointer to the #jsConsumerConfig. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_UpdateConsumer(jsConsumerInfo **ci, jsCtx *js, const char *stream, jsConsumerConfig *cfg, jsOptions *opts, jsErrCode *errCode); /** \brief Retrieves information about a consumer. * * \note The returned object should be destroyed using #jsConsumerInfo_Destroy in order * to free allocated memory. * * @param ci the location where to store the pointer to the new #jsConsumerInfo object. * @param js the pointer to the #jsCtx context. * @param stream the name of the stream. * @param consumer the name of the consumer. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_GetConsumerInfo(jsConsumerInfo **ci, jsCtx *js, const char *stream, const char *consumer, jsOptions *opts, jsErrCode *errCode); /** \brief Deletes a consumer. * * Deletes the consumer named consumer from stream named stream. * * @param js the pointer to the #jsCtx context. * @param stream the name of the stream. * @param consumer the name of the consumer. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_DeleteConsumer(jsCtx *js, const char *stream, const char *consumer, jsOptions *opts, jsErrCode *errCode); /** \brief Destroys the consumer information object. * * Releases memory allocated for this consumer information object. * * @param ci the pointer to the #jsConsumerInfo object. */ NATS_EXTERN void jsConsumerInfo_Destroy(jsConsumerInfo *ci); /** \brief Retrieves the list of all available consumers for a stream. * * Retrieves the list of all #jsConsumerInfo for a given stream. * * \warning The list should be destroyed when no longer used by * calling #jsConsumerInfoList_Destroy. * * @param list the location where to store the pointer to the new #jsConsumerInfoList object. * @param js the pointer to the #jsCtx context. * @param stream the stream name whose consumer list is requested. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_Consumers(jsConsumerInfoList **list, jsCtx *js, const char *stream, jsOptions *opts, jsErrCode *errCode); /** \brief Destroys the consumer information list object. * * Releases memory allocated for this consumer information list. * * \warning All #jsConsumerInfo pointers contained in the list will * be destroyed by this call. * * @param list the pointer to the #jsConsumerInfoList object. */ NATS_EXTERN void jsConsumerInfoList_Destroy(jsConsumerInfoList *list); /** \brief Retrieves the list of all available consumer names for a stream. * * Retrieves the list of all consumer names for a given stream. * * \warning The list should be destroyed when no longer used by * calling #jsConsumerNamesList_Destroy. * * @param list the location where to store the pointer to the new #jsConsumerNamesList object. * @param js the pointer to the #jsCtx context. * @param stream the stream name whose consumer list is requested. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_ConsumerNames(jsConsumerNamesList **list, jsCtx *js, const char *stream, jsOptions *opts, jsErrCode *errCode); /** \brief Destroys the consumer names list object. * * Releases memory allocated for this list of consumer names. * * \warning All string pointers contained in the list will * be destroyed by this call. * * @param list the pointer to the #jsConsumerNamesList object. */ NATS_EXTERN void jsConsumerNamesList_Destroy(jsConsumerNamesList *list); /** \brief Retrieves information about the JetStream usage from an account. * * Retrieves information about the JetStream usage from an account. * * \note The returned object should be destroyed using #jsAccountInfo_Destroy in order * to free allocated memory. * * @param ai the location where to store the pointer to the new #jsAccountInfo object in * response to the account information request. * @param js the pointer to the #jsCtx context. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_GetAccountInfo(jsAccountInfo **ai, jsCtx *js, jsOptions *opts, jsErrCode *errCode); /** \brief Destroys the account information object. * * Releases memory allocated for this account information object. * * @param ai the pointer to the #jsAccountInfo object. */ NATS_EXTERN void jsAccountInfo_Destroy(jsAccountInfo *ai); /** @} */ // end of jsAssetsGroup /** \defgroup jsPubGroup Publishing * * Publishing functions * @{ */ /** \brief Initializes a publish options structure. * * Use this before setting specific publish options and passing this * configuration to the JetStream publish APIs. * * @param opts the pointer to the #jsPubOptions to initialize. */ NATS_EXTERN natsStatus jsPubOptions_Init(jsPubOptions *opts); /** \brief Publishes data on a subject to JetStream. * * Publishes the data to the given subject to JetStream. * * See #js_PublishMsg for details. * * @param pubAck the location where to store the pub acknowledgment, or `NULL` if not needed. * @param js the pointer to the #jsCtx object. * @param subj the subject the data is sent to. * @param data the data to be sent, can be `NULL`. * @param dataLen the length of the data to be sent. * @param opts the publish options, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_Publish(jsPubAck **pubAck, jsCtx *js, const char *subj, const void *data, int dataLen, jsPubOptions *opts, jsErrCode *errCode); /** \brief Publishes a message to JetStream. * * Publishes the given message to JetStream. * * \note If you are not interested in inspecting the publish acknowledgment, you can * pass `NULL`, but keep in mind that the publish acknowledgment is still sent by * the server. * \note The returned #jsPubAck object needs to be destroyed with #jsPubAck_Destroy * when no longer needed. * * @see jsPubAck_Destroy * * @param pubAck the location where to store the pub acknowledgment, or `NULL` if not needed. * @param js the pointer to the #jsCtx object. * @param msg the pointer to the #natsMsg object to send. * @param opts the publish options, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus js_PublishMsg(jsPubAck **pubAck, jsCtx *js, natsMsg *msg, jsPubOptions *opts, jsErrCode *errCode); /** \brief Destroys the publish acknowledgment object. * * Releases memory allocated for this publish acknowledgment object. * * @param pubAck the #jsPubAck object to destroy. */ NATS_EXTERN void jsPubAck_Destroy(jsPubAck *pubAck); /** \brief Publishes data to JetStream but does not wait for a #jsPubAck. * * See #js_PublishMsgAsync for details. * * @param js the pointer to the #jsCtx object. * @param subj the subject the data is sent to. * @param data the data to be sent, can be `NULL`. * @param dataLen the length of the data to be sent. * @param opts the publish options, possibly `NULL`. */ NATS_EXTERN natsStatus js_PublishAsync(jsCtx *js, const char *subj, const void *data, int dataLen, jsPubOptions *opts); /** \brief Publishes a message to JetStream but does not wait for a #jsPubAck. * * Publishes a message asynchronously to JetStream. User can call #js_PublishAsyncComplete * to be notified when all publish acknowledgments for the pending publish calls * have been received. * * \note If this call is successful, the library takes ownership of the message * and will destroy it after the acknowledgment has been received, or will * present it to the user through the #jsPubAckErrHandler callback. To prevent the user * from accessing/destroying the message while in use by the library, this function * requires a pointer to the pointer of the message so that it can be cleared. * That way, the user should always call #natsMsg_Destroy, regardless of success or * failure, since #natsMsg_Destroy will have no effect if the message pointer is `NULL`. * * @see js_PublishAsyncComplete * @see jsPubAckErrHandler * * @param js the pointer to the #jsCtx object. * @param msg the memory location where the pointer to the #natsMsg object is located. * If the library takes ownership of the message, this location will be cleared so a following * call to #natsMsg_Destroy would have no effect. * @param opts the publish options, possibly `NULL`. */ NATS_EXTERN natsStatus js_PublishMsgAsync(jsCtx *js, natsMsg **msg, jsPubOptions *opts); /** \brief Wait for all outstanding messages to be acknowledged. * * This call will block until the library has received acknowledgment for * all outstanding published messages. * * To limit the wait, user can pass a #jsPubOptions with a `MaxWait` set to the * maximum number of milliseconds that the call should block. * * @param js the pointer to the #jsCtx object. * @param opts the publish options, possibly `NULL`. */ NATS_EXTERN natsStatus js_PublishAsyncComplete(jsCtx *js, jsPubOptions *opts); /** \brief Returns the list of pending messages published asynchronously. * * This call returns the list of all asynchronously published messages * for which no acknowledgment have been received yet. * * The user has now back ownership of the messages and can resend send if * desired or simply destroy them. * * \note After this call returns, it is possible that acknowledgments arrive * from the server but since they have been removed from the pending list, the * acknowledgments will be discarded (no #jsPubAckErrHandler callback invoked). * If the server did receive a particular message and the user in the meantime * has resent that message, it would be a duplicate, so in order for the server * to detect this duplicate, ensure that the stream's duplicate window setting * is specified and a unique message ID was set when sending the message. * * \warning The user must call #natsMsgList_Destroy to release memory * allocated by this call and destroy all pending messages still present in the list. * * \code{.unparsed} * natsMsgList pending; * * s = js_PublishAsyncGetPendingList(&pending, js); * if (s == NATS_OK) * { * int i; * * for (i=0; i * It means that calling `natsSubscription_Fetch(&list, sub, 10, 5000)` may * return after less than 5 seconds with only 3 messages. * * @param list the location to a #natsMsgList that will be filled by the result of this call. * @param sub the pointer to the #natsSubscription object. * @param batch the batch size, that is, the maximum number of messages to return. * @param timeout the timeout (required) expressed in number of milliseconds. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus natsSubscription_Fetch(natsMsgList *list, natsSubscription *sub, int batch, int64_t timeout, jsErrCode *errCode); /** \brief Initializes a fetch request options structure. * * Use this before setting specific fetch options and passing it to #natsSubscription_FetchRequest. * * @param request the pointer to the #jsFetchRequest object. */ NATS_EXTERN natsStatus jsFetchRequest_Init(jsFetchRequest *request); /** \brief Fetches messages for a pull subscription with a complete request configuration * * Similar to #natsSubscription_Fetch but a full #jsFetchRequest configuration is provided * for maximum control. * * Initialize the #jsFetchRequest structure using #jsFetchRequest_Init and then set * the parameters desired, then invoke this function. * * @param list the location to a #natsMsgList that will be filled by the result of this call. * @param sub the pointer to the #natsSubscription object. * @param request the pointer to a #jsFetchRequest configuration. */ NATS_EXTERN natsStatus natsSubscription_FetchRequest(natsMsgList *list, natsSubscription *sub, jsFetchRequest *request); /** \brief Returns the jsConsumerInfo associated with this subscription. * * Returns the #jsConsumerInfo associated with this subscription. * * @param ci the location where to store the pointer to the new #jsConsumerInfo object. * @param sub the pointer to the #natsSubscription object. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus natsSubscription_GetConsumerInfo(jsConsumerInfo **ci, natsSubscription *sub, jsOptions *opts, jsErrCode *errCode); /** \brief Returns the consumer sequence mismatch information. * * If `Heartbeat` is configured in #jsConsumerConfig object (or configured in an existing * JetStream consumer), the server sends heartbeats to the client at the given interval. * * Those heartbeats contains information that allow the application to detect a mismatch * between the server and client's view of the state of the consumer. * * If the library detects a sequence mismatch, the behavior is different depending on * the type of subscription: * * * For asynchronous subscriptions: the error #NATS_MISMATCH is published to the error handler * (see #natsOptions_SetErrorHandler). * * For synchronous subscriptions: the next call to #natsSubscription_NextMsg() will * return the error #NATS_MISMATCH (but will succeed afterwards). * * In both cases, the user should check what the mismatch is using this function and * possibly recreate the consumer based on the provided information. * * \note For a valid JetStream subscription, this function will return #NATS_NOT_FOUND * if no consumer sequence mismatch has been detected. * * @see jsConsumerSequenceMismatch * * @param csm the pointer location where to copy the consumer sequence mismatch information. * @param sub the pointer to the #natsSubscription object. */ NATS_EXTERN natsStatus natsSubscription_GetSequenceMismatch(jsConsumerSequenceMismatch *csm, natsSubscription *sub); /** @} */ // end of jsSubGroup /** \defgroup jsMsg Messages * * Function specific to JetStream messages * @{ */ /** \brief Returns metadata from this JetStream message. * * This works only for JetStream messages that have been received through * a subscription callback or calling #natsSubscription_NextMsg. * * \note The user must destroy the returned object with #jsMsgMetaData_Destroy. * * \note This function will return an error for non JetStream messages. * * @param new_meta the location where to store the pointer to the newly created * #jsMsgMetaData object. * @param msg the pointer to the #natsMsg object, which should be a JetStream * message received through a subscription callback or #natsSubscription_NextMsg. */ NATS_EXTERN natsStatus natsMsg_GetMetaData(jsMsgMetaData **new_meta, natsMsg *msg); /** \brief Destroys the message metadata object. * * Releases memory allocated for this #jsMsgMetaData object. * * @param meta the pointer to the #jsMsgMetaData object. */ NATS_EXTERN void jsMsgMetaData_Destroy(jsMsgMetaData *meta); /** \brief Acknowledges a message. * * This tells the server that the message was successfully processed and * it can move on to the next message. * * @param msg the pointer to the #natsMsg object. * @param opts the pointer to the #jsOptions object, possibly `NULL`. */ NATS_EXTERN natsStatus natsMsg_Ack(natsMsg *msg, jsOptions *opts); /** \brief Acknowledges a message and wait for a confirmation. * * This is the synchronous version of #natsMsg_Ack. This indicates successful * message processing, and waits for confirmation from the server that * the acknowledgment has been processed. * * @param msg the pointer to the #natsMsg object. * @param opts the pointer to the #jsOptions object, possibly `NULL`. * @param errCode the location where to store the JetStream specific error code, or `NULL` * if not needed. */ NATS_EXTERN natsStatus natsMsg_AckSync(natsMsg *msg, jsOptions *opts, jsErrCode *errCode); /** \brief Negatively acknowledges a message. * * This tells the server to redeliver the message. You can configure the * number of redeliveries by passing `MaxDeliver` when you subscribe. * * The default is infinite redeliveries. * * @param msg the pointer to the #natsMsg object. * @param opts the pointer to the #jsOptions object, possibly `NULL`. */ NATS_EXTERN natsStatus natsMsg_Nak(natsMsg *msg, jsOptions *opts); /** \brief Negatively acknowledges a message. * * This tells the server to redeliver the message after the given `delay` * duration expressed in milliseconds. You can configure the number of * redeliveries by passing `MaxDeliver` when you subscribe. * * The default is infinite redeliveries. * * @param msg the pointer to the #natsMsg object. * @param delay the amount of time before the redelivery expressed in milliseconds. * @param opts the pointer to the #jsOptions object, possibly `NULL`. */ NATS_EXTERN natsStatus natsMsg_NakWithDelay(natsMsg *msg, int64_t delay, jsOptions *opts); /** \brief Resets redelivery timer on the server. * * This tells the server that this message is being worked on. It resets * the redelivery timer on the server. * * @param msg the pointer to the #natsMsg object. * @param opts the pointer to the #jsOptions object, possibly `NULL`. */ NATS_EXTERN natsStatus natsMsg_InProgress(natsMsg *msg, jsOptions *opts); /** \brief Abandon this message. * * This tells the server to not redeliver this message, regardless of * the value `MaxDeliver`. * * @param msg the pointer to the #natsMsg object. * @param opts the pointer to the #jsOptions object, possibly `NULL`. */ NATS_EXTERN natsStatus natsMsg_Term(natsMsg *msg, jsOptions *opts); /** \brief Returns the sequence number of this JetStream message. * * Returns the sequence number of this JetStream message, or `0` if `msg` is `NULL` * or not a JetStream message. * * \note This applies to JetStream messages retrieved with #js_GetMsg or #js_GetLastMsg. * * @param msg the pointer to the #natsMsg object. */ NATS_EXTERN uint64_t natsMsg_GetSequence(natsMsg *msg); /** \brief Returns the timestamp (in UTC) of this JetStream message. * * Returns the timestamp (in UTC) of this JetStream message, or `0` if `msg` is `NULL` * or not a JetStream message. * * \note This applies to JetStream messages retrieved with #js_GetMsg or #js_GetLastMsg. * * @param msg the pointer to the #natsMsg object. */ NATS_EXTERN int64_t natsMsg_GetTime(natsMsg *msg); /** @} */ // end of jsMsg /** @} */ // end of jsGroup /** \defgroup kvGroup KeyValue store * * A KeyValue store is a materialized view of JetStream. * * \warning EXPERIMENTAL FEATURE! We reserve the right to change the API without * necessarily bumping the major version of the library. * * @{ */ /** \defgroup kvGroupMgt KeyValue store management * * These functions allow to create, get or delete a KeyValue store. * * \warning EXPERIMENTAL FEATURE! We reserve the right to change the API without * necessarily bumping the major version of the library. * * @{ */ /** \brief Initializes a KeyValue configuration structure. * * Use this before setting specific #kvConfig options and passing it to #js_CreateKeyValue. * * @see js_CreateKeyValue * * @param cfg the pointer to the stack variable #kvConfig to initialize. */ NATS_EXTERN natsStatus kvConfig_Init(kvConfig *cfg); /** \brief Creates a KeyValue store with a given configuration. * * Creates a KeyValue store with a given configuration. * * Bucket names are restricted to this set of characters: `A-Z`, `a-z`, `0-9`, `_` and `-`. * * \note The return #kvStore object needs to be destroyed using #kvStore_Destroy when * no longer needed to free allocated memory. This is different from deleting a KeyValue store * from the server using the #js_DeleteKeyValue API. * * @param new_kv the location where to store the newly created #kvStore object. * @param js the pointer to the #jsCtx object. * @param cfg the pointer to the #kvConfig configuration information used to create the #kvStore object. */ NATS_EXTERN natsStatus js_CreateKeyValue(kvStore **new_kv, jsCtx *js, kvConfig *cfg); /** \brief Looks-up and binds to an existing KeyValue store. * * This call is when the user wants to use an existing KeyValue store. * If the store does not already exists, an error is returned. * * Bucket names are restricted to this set of characters: `A-Z`, `a-z`, `0-9`, `_` and `-`. * * \note The return #kvStore object needs to be destroyed using #kvStore_Destroy when * no longer needed to free allocated memory. This is different from deleting a KeyValue store * from the server using the #js_DeleteKeyValue API. * * @param new_kv the location where to store the newly created #kvStore object. * @param js the pointer to the #jsCtx object. * @param bucket the name of the bucket of the existing KeyValue store. */ NATS_EXTERN natsStatus js_KeyValue(kvStore **new_kv, jsCtx *js, const char *bucket); /** \brief Deletes a KeyValue store. * * This will delete the KeyValue store with the `bucket` name. * * Bucket names are restricted to this set of characters: `A-Z`, `a-z`, `0-9`, `_` and `-`. * * @param js the pointer to the #jsCtx object. * @param bucket the name of the bucket of the existing KeyValue store. */ NATS_EXTERN natsStatus js_DeleteKeyValue(jsCtx *js, const char *bucket); /** \brief Destroys a KeyValue store object. * * This will simply free memory resources in the library for this #kvStore, * but does not delete the KeyValue store in the server. * * @param kv the pointer to the #kvStore object. */ NATS_EXTERN void kvStore_Destroy(kvStore *kv); /** @} */ // end of kvGroupMgt /** \defgroup kvEntry KeyValue store entries * * These functions allow to inspect a the value, or entry, of a given key. * * \warning EXPERIMENTAL FEATURE! We reserve the right to change the API without * necessarily bumping the major version of the library. * * @{ */ /** \brief Returns the name of the bucket the data was loaded from. * * Returns the name of the bucket the data was loaded from, or `NULL` if `e` itself is `NULL`. * * @param e the pointer to the #kvEntry object. */ NATS_EXTERN const char* kvEntry_Bucket(kvEntry *e); /** \brief Returns the name of the key that was retrieved. * * Returns the name of the key that was retrieved, or `NULL` if `e` itself is `NULL`. * * @param e the pointer to the #kvEntry object. */ NATS_EXTERN const char* kvEntry_Key(kvEntry *e); /** \brief Returns the value for this key. * * Returns the value for this key, or `NULL` if `e` itself is `NULL`. * * @param e the pointer to the #kvEntry object. */ NATS_EXTERN const void* kvEntry_Value(kvEntry *e); /** \brief Returns the value length for this key. * * Returns the value length for this key, or `-1` if `e` itself is `NULL`. * * @param e the pointer to the #kvEntry object. */ NATS_EXTERN int kvEntry_ValueLen(kvEntry *e); /** \brief Returns the value, as a string, for this key. * * If the value is an actual string, this call will return a NULL terminating string (`const char*`), * or `NULL` if `e` itself is `NULL`. * * @param e the pointer to the #kvEntry object. */ NATS_EXTERN const char* kvEntry_ValueString(kvEntry *e); /** \brief Returns the unique sequence for this value. * * Returns the unique sequence for this value, or `0` if `e` itself is `NULL`. * * @param e the pointer to the #kvEntry object. */ NATS_EXTERN uint64_t kvEntry_Revision(kvEntry *e); /** \brief Returns the time (in UTC) the data was put in the bucket. * * Returns the time (in UTC) the data was put in the bucket, or `0` if `e` itself is `NULL`. * * @param e the pointer to the #kvEntry object. */ NATS_EXTERN int64_t kvEntry_Created(kvEntry *e); /** \brief Returns the distance from the latest value. * * Returns the distance from the latest value, or `0` if `e` itself is `NULL`. * * If history is enabled this is effectively the index of the historical value, * 0 for latest, 1 for most recent etc... * * @param e the pointer to the #kvEntry object. */ NATS_EXTERN uint64_t kvEntry_Delta(kvEntry *e); /** \brief Returns the type of operation of this value. * * Returns the type of operation of this value. * * @see kvOperation * * @param e the pointer to the #kvEntry object. */ NATS_EXTERN kvOperation kvEntry_Operation(kvEntry *e); /** \brief Destroys the KeyValue entry object. * * Releases memory allocated for this #kvEntry object. * * @param e the pointer to the #kvEntry object. */ NATS_EXTERN void kvEntry_Destroy(kvEntry *e); /** @} */ // end of kvEntry /** \brief Returns the latest entry for the key. * * Returns the latest entry for the key. * * \note The entry should be destroyed to release memory using #kvEntry_Destroy. * * @param new_entry the location where to store the pointer to the entry associated with the `key`. * @param kv the pointer to the #kvStore object. * @param key the name of the key. */ NATS_EXTERN natsStatus kvStore_Get(kvEntry **new_entry, kvStore *kv, const char *key); /** \brief Returns the entry at the specific revision for the key. * * Returns the entry at the specific revision for the key, or #NATS_NOT_FOUND if there is no * entry for that key and revision. * * \note The entry should be destroyed to release memory using #kvEntry_Destroy. * * @param new_entry the location where to store the pointer to the entry associated with the `key`. * @param kv the pointer to the #kvStore object. * @param key the name of the key. * @param revision the revision of the entry (must be > 0). */ NATS_EXTERN natsStatus kvStore_GetRevision(kvEntry **new_entry, kvStore *kv, const char *key, uint64_t revision); /** \brief Places the new value for the key into the store. * * Places the new value for the key into the store. * * @param rev the location where to store the revision of this value, or `NULL` if the stream information is not needed. * @param kv the pointer to the #kvStore object. * @param key the name of the key. * @param data the pointer to the data in memory. * @param len the number of bytes to copy from the data's memory location. */ NATS_EXTERN natsStatus kvStore_Put(uint64_t *rev, kvStore *kv, const char *key, const void *data, int len); /** \brief Places the new value (as a string) for the key into the store. * * Places the new value, as a string, for the key into the store. * * \note This is equivalent of calling #kvStore_Put with `(int) strlen(data)`. * * \warning The NULL terminating character is not included in the number of bytes stored in the KeyValue store. * * @param rev the location where to store the revision of this value, or `NULL` if the stream information is not needed. * @param kv the pointer to the #kvStore object. * @param key the name of the key. * @param data the pointer to the string to store. */ NATS_EXTERN natsStatus kvStore_PutString(uint64_t *rev, kvStore *kv, const char *key, const char *data); /** \brief Places the value for the key into the store if and only if the key does not exist. * * Places the value for the key into the store if and only if the key does not exist. * * @param rev the location where to store the revision of this value, or `NULL` if the stream information is not needed. * @param kv the pointer to the #kvStore object. * @param key the name of the key. * @param data the pointer to the data in memory. * @param len the number of bytes to copy from the data's memory location. */ NATS_EXTERN natsStatus kvStore_Create(uint64_t *rev, kvStore *kv, const char *key, const void *data, int len); /** \brief Places the value (as a string) for the key into the store if and only if the key does not exist. * * Places the value (as a string) for the key into the store if and only if the key does not exist. * * \note This is equivalent of calling #kvStore_Create with `(int) strlen(data)`. * * \warning The NULL terminating character is not included in the number of bytes stored in the KeyValue store. * * @param rev the location where to store the revision of this value, or `NULL` if the stream information is not needed. * @param kv the pointer to the #kvStore object. * @param key the name of the key. * @param data the pointer to the string. */ NATS_EXTERN natsStatus kvStore_CreateString(uint64_t *rev, kvStore *kv, const char *key, const char *data); /** \brief Updates the value for the key into the store if and only if the latest revision matches. * * Updates the value for the key into the store if and only if the latest revision matches. * * @param rev the location where to store the revision of this value, or `NULL` if the stream information is not needed. * @param kv the pointer to the #kvStore object. * @param key the name of the key. * @param data the pointer to the data in memory. * @param len the number of bytes to copy from the data's memory location. * @param last the expected latest revision prior to the update. */ NATS_EXTERN natsStatus kvStore_Update(uint64_t *rev, kvStore *kv, const char *key, const void *data, int len, uint64_t last); /** \brief Updates the value (as a string) for the key into the store if and only if the latest revision matches. * * Updates the value (as a string) for the key into the store if and only if the latest revision matches. * * \note This is equivalent of calling #kvStore_Update with `(int) strlen(data)`. * * \warning The NULL terminating character is not included in the number of bytes stored in the KeyValue store. * * @param rev the location where to store the revision of this value, or `NULL` if the stream information is not needed. * @param kv the pointer to the #kvStore object. * @param key the name of the key. * @param data the pointer to the string. * @param last the expected latest revision prior to the update. */ NATS_EXTERN natsStatus kvStore_UpdateString(uint64_t *rev, kvStore *kv, const char *key, const char *data, uint64_t last); /** \brief Deletes a key by placing a delete marker and leaving all revisions. * * Deletes a key by placing a delete marker and leaving all revisions. * * @param kv the pointer to the #kvStore object. * @param key the name of the key. */ NATS_EXTERN natsStatus kvStore_Delete(kvStore *kv, const char *key); /** \brief Deletes a key by placing a purge marker and removing all revisions. * * Deletes a key by placing a purge marker and removing all revisions. * * @param kv the pointer to the #kvStore object. * @param key the name of the key. * @param opts the pointer to the #kvPurgeOptions, possibly `NULL`. */ NATS_EXTERN natsStatus kvStore_Purge(kvStore *kv, const char *key, kvPurgeOptions *opts); /** \brief Initializes a KeyValue watcher options structure. * * Use this before setting specific watcher options and passing it * to #kvStore_Watch. * * @param opts the pointer to the #kvWatchOptions to initialize. */ NATS_EXTERN natsStatus kvWatchOptions_Init(kvWatchOptions *opts); /** \brief Initializes a KeyValue purge options structure. * * Use this before setting specific purge options and passing it * to #kvStore_Purge or #kvStore_PurgeDeletes. * * @param opts the pointer to the #kvPurgeOptions to initialize. */ NATS_EXTERN natsStatus kvPurgeOptions_Init(kvPurgeOptions *opts); /** \brief Purge and removes delete markers. * * Removes data and delete markers, but may keep the markers that are considered * more recent than a certain threshold (default is 30 minutes). * * This is a maintenance option if there is a larger buildup of delete markers. * * \note Use #kvPurgeOptions.Timeout to specify how long to wait (in milliseconds) * in gathering all keys that have purge markers. This function will still * purge some of the keys and return #NATS_TIMEOUT to indicate that it may not * have deleted them all. * * @see kvPurgeOptions_Init * * @param kv the pointer to the #kvStore object. * @param opts the pointer to the #kvPurgeOptions, possibly `NULL`. */ NATS_EXTERN natsStatus kvStore_PurgeDeletes(kvStore *kv, kvPurgeOptions *opts); /** \brief Returns a watcher for any updates to keys that match the `keys` argument. * * Returns a watcher for any updates to keys that match the `keys` argument, which * could include wildcard. * * A `NULL` entry will be posted when the watcher has received all initial values. * * Call #kvWatcher_Next to get the next #kvEntry. * * \note The watcher should be destroyed to release memory using #kvWatcher_Destroy. * * @param new_watcher the location where to store the pointer to the new #kvWatcher object. * @param kv the pointer to the #kvStore object. * @param keys the keys (wildcard possible) to create the watcher for. * @param opts the watcher options, possibly `NULL`. */ NATS_EXTERN natsStatus kvStore_Watch(kvWatcher **new_watcher, kvStore *kv, const char *keys, kvWatchOptions *opts); /** \brief Returns a watcher for any updates to any keys of the KeyValue store bucket. * * Returns a watcher for any updates to any keys of the KeyValue store bucket. * * A `NULL` entry will be posted when the watcher has received all initial values. * * Call #kvWatcher_Next to get the next #kvEntry. * * \note The watcher should be destroyed to release memory using #kvWatcher_Destroy. * * @param new_watcher the location where to store the pointer to the new #kvWatcher object. * @param kv the pointer to the #kvStore object. * @param opts the watcher options, possibly `NULL`. */ NATS_EXTERN natsStatus kvStore_WatchAll(kvWatcher **new_watcher, kvStore *kv, kvWatchOptions *opts); /** \brief Returns all keys in the bucket. * * Returns all keys in the bucket. * * \note Use #kvWatchOptions.Timeout to specify how long to wait (in milliseconds) * to gather all keys for this bucket. If the deadline is reached, this function * will return #NATS_TIMEOUT and no keys. * * \warning The user should call #kvKeysList_Destroy to release memory allocated * for the entries list. * * @see kvWatchOptions_Init * @see kvKeysList_Destroy * * @param list list the pointer to a #kvKeysList that will be initialized and filled with resulting key strings. * @param kv the pointer to the #kvStore object. * @param opts the history options, possibly `NULL`. */ NATS_EXTERN natsStatus kvStore_Keys(kvKeysList *list, kvStore *kv, kvWatchOptions *opts); /** \brief Destroys this list of KeyValue store key strings. * * This function iterates through the list of all key strings and free them. * It then frees the array that was allocated to hold pointers to those keys. * * \note The #kvKeysList object itself is not freed since it is expected that * users will pass a pointer to a stack object. Should the user create its own * object, it will be the user responsibility to free this object. * * @param list the #kvKeysList list of key strings to destroy. */ NATS_EXTERN void kvKeysList_Destroy(kvKeysList *list); /** \brief Returns all historical entries for the key. * * Returns all historical entries for the key * * Use the options to alter the behavior. For instance, if delete markers * are not desired, option #kvWatchOptions.IgnoreDeletes should be specified. * * \note Use #kvWatchOptions.Timeout to specify how long to wait (in milliseconds) * to gather all entries for this key. If the deadline is reached, this function * will return #NATS_TIMEOUT and no entries. * * \warning The user should call #kvEntryList_Destroy to release memory allocated * for the entries list. * * @see kvWatchOptions_Init * @see kvEntryList_Destroy * * @param list the pointer to a #kvEntryList that will be initialized and filled with resulting entries. * @param kv the pointer to the #kvStore object. * @param key the key for which the history is requested. * @param opts the history options, possibly `NULL`. */ NATS_EXTERN natsStatus kvStore_History(kvEntryList *list, kvStore *kv, const char *key, kvWatchOptions *opts); /** \brief Destroys this list of KeyValue store entries. * * This function iterates through the list of all entries and call #kvEntry_Destroy. * It then frees the array that was allocated to hold pointers to those entries. * * \note The #kvEntryList object itself is not freed since it is expected that * users will pass a pointer to a stack object. Should the user create its own * object, it will be the user responsibility to free this object. * * @param list the #kvEntryList list of #kvEntry objects to destroy. */ NATS_EXTERN void kvEntryList_Destroy(kvEntryList *list); /** \brief Returns the bucket name of this KeyValue store object. * * Returns the bucket name of this KeyValue store object, or `NULL` if * `kv` itself is NULL. * * \warning Do not free the string returned by this function. * * @param kv the pointer to the #kvStore object. */ NATS_EXTERN const char* kvStore_Bucket(kvStore *kv); // PurgeDeletes /** \brief Returns the status and configuration of a bucket. * * Returns the status and configuration of a bucket. * * \note The status should be destroyed to release memory using #kvStatus_Destroy. * * @param new_status the location where to store the status of this KeyValue store. * @param kv the pointer to the #kvStore object. */ NATS_EXTERN natsStatus kvStore_Status(kvStatus **new_status, kvStore *kv); /** \defgroup kvWatcher KeyValue store watcher * * These functions allow to receive updates for key(s) on a given bucket. * * \warning EXPERIMENTAL FEATURE! We reserve the right to change the API without * necessarily bumping the major version of the library. * * @{ */ /** \brief Returns the next entry for this watcher. * * Returns the next entry for this watcher. The entry may be `NULL` * (with #NATS_OK status) to indicate that the initial state has * been retrieved. * * If a thread is waiting on this call, it can be canceled with a call to * #kvWatcher_Stop. * * \note The entry should be destroyed to release memory using #kvEntry_Destroy. * * @param new_entry the location where to store the pointer to the #kvEntry object. * @param w the pointer to the #kvWatcher object. * @param timeout how long to wait (in milliseconds) for the next entry. */ NATS_EXTERN natsStatus kvWatcher_Next(kvEntry **new_entry, kvWatcher *w, int64_t timeout); /** \brief Stops the watcher. * * Stops the watcher. Stopping a stopped watcher returns #NATS_OK. * * After this call, new and existing calls to #kvWatcher_Next (that are waiting * for an update) will return with #NATS_ILLEGAL_STATE. * * @param w the pointer to the #kvWatcher object. */ NATS_EXTERN natsStatus kvWatcher_Stop(kvWatcher *w); /** \brief Destroys the KeyValue watcher object. * * Releases memory allocated for this #kvWatcher object. * * @param w the pointer to the #kvWatcher object. */ NATS_EXTERN void kvWatcher_Destroy(kvWatcher *w); /** @} */ // end of kvWatcher /** \defgroup kvStatus KeyValue store status * * These functions allow to inspect the status of a bucket. * * \warning EXPERIMENTAL FEATURE! We reserve the right to change the API without * necessarily bumping the major version of the library. * * @{ */ /** \brief Returns the bucket name. * * Returns the bucket name, or `NULL` if `sts` itself is `NULL`. * * @param sts the pointer to the #kvStatus object. */ NATS_EXTERN const char* kvStatus_Bucket(kvStatus *sts); /** \brief Returns how many messages are in the bucket, including historical values. * * Returns how many messages are in the bucket, including historical values, or `0` if `sts` itself is `NULL`. * * @param sts the pointer to the #kvStatus object. */ NATS_EXTERN uint64_t kvStatus_Values(kvStatus *sts); /** \brief Returns the configured history kept per key. * * Returns the configured history kept per key, or `0` if `sts` itself is `NULL`. * * @param sts the pointer to the #kvStatus object. */ NATS_EXTERN int64_t kvStatus_History(kvStatus *sts); /** \brief Returns how long the bucket keeps values for. * * Returns how long the bucket keeps values for, or `0` if `sts` itself is `NULL`. * * @param sts the pointer to the #kvStatus object. */ NATS_EXTERN int64_t kvStatus_TTL(kvStatus *sts); /** \brief Returns the number of replicas to keep for a bucket. * * Returns the number of replicas to keep for a bucket, or `0` if `sts` itself is `NULL`. * * @param sts the pointer to the #kvStatus object. */ NATS_EXTERN int64_t kvStatus_Replicas(kvStatus *sts); /** \brief Returns the size (in bytes) of this bucket. * * Returns the size (in bytes) of this bucket, or `0` if `sts` itself is `NULL`. * * @param sts the pointer to the #kvStatus object. */ NATS_EXTERN uint64_t kvStatus_Bytes(kvStatus *sts); /** \brief Destroys the KeyValue status object. * * Releases memory allocated for this #kvStatus object. * * @param sts the pointer to the #kvStatus object. */ NATS_EXTERN void kvStatus_Destroy(kvStatus *sts); /** @} */ // end of kvStatus /** @} */ // end of kvGroup /** @} */ // end of funcGroup /** \defgroup wildcardsGroup Wildcards * @{ * Use of wildcards. There are two type of wildcards: `*` for partial, * and `>` for full. * * A subscription on subject `foo.*` would receive messages sent to: * - `foo.bar` * - `foo.baz` * * but not on: * * - `foo.bar.baz` (too many elements) * - `bar.foo`. (does not start with `foo`). * * A subscription on subject `foo.>` would receive messages sent to: * - `foo.bar` * - `foo.baz` * - `foo.bar.baz` * * but not on: * - `foo` (only one element, needs at least two) * - `bar.baz` (does not start with `foo`). ** @} */ /** \defgroup envVariablesGroup Environment Variables * @{ * You will find here the environment variables that change the default behavior * of the NATS C Client library. *

* Name | Effect * -----|:-----: * `NATS_DEFAULT_TO_LIB_MSG_DELIVERY` | On #nats_Open, the library looks for this environment variable. If set (to any value), the library will default to using a global thread pool to perform message delivery. See #natsOptions_UseGlobalMessageDelivery and #nats_SetMessageDeliveryPoolSize. * ** @} */ #ifdef __cplusplus } #endif #endif /* NATS_H_ */