Changelog
View Source1.18.1
Gnat.pub/4,Gnat.request/4, andGnat.request_multi/4now return{:error, :max_payload_exceeded}without sending when the body plus encoded headers is larger than the server'smax_payload.- Previously these message was sent and the server would close the connection with a
Maximum Payload Violation, disrupting every subscription on it. This matches the official Go client'sErrMaxPayload. See #245 Gnat.ServerandGnat.Services.Servernow pass:max_payload_exceededto yourerror/2callback when a reply is rejected. If the reply returned fromerror/2is also rejected, it is logged instead of callingerror/2again. Services count a rejected reply as an endpoint error instead of a successful request.- JetStream APIs built on
Gnat.request/4(KV, Object store, and so on) can now return{:error, :max_payload_exceeded}.
- Previously these message was sent and the server would close the connection with a
- Fixed subscription cleanup when a subscriber process exits. See #244
- A subscriber exit that no longer matched a subscription used to crash the connection. It's now ignored.
- A process with several subscriptions could leave one behind when it exited. Each subscription is now matched by its own monitor.
- A subscription with
Gnat.unsub/3'smax_messagesoption is now removed, and anUNSUBis sent, if the subscriber exits before the last message. Previously the subscription leaked.
1.18.0
- Supervised PullConsumers will now only attempt to re-create the consumer on disconnect/reconnect for ephemeral consumers. Any durable consumer will just register a new pull request for its durable name. See #233 for details.
- Subject names with
\r,\nor\tcharacters are now validated by the client before sending over the wire to prevent potential injection. See #232 - Behavior change:
Gnat.start_link/2now returns{:error, reason}when the TLS upgrade, the header support check or sendingCONNECTfails, instead of crashing during initialization. TLS alerts come back as-is (for example{:error, {:tls_alert, {:certificate_expired, _}}}), soGnat.ConnectionSupervisorlogs why the connection failed. Invalidssl_optsreturn{:error, {:options, {option, :redacted}}}because:sslechoes the option value, which can be a key or password. - Behavior change:
Gnat.Jetstream.API.KV.put_value/5,delete_key/4, andpurge_key/4now validate the JetStream publish acknowledgement instead of reporting:okfor any reply. They share the same ack validation ascreate_key/5: a rejected write returns{:error, reason}with the server's error map, and a malformed or unrelated ack returns{:error, :invalid_publish_ack}. Previously a server-side rejection (for example aput_value/5larger than the bucket'smax_value_size) was silently reported as:ok. See #235 - Behavior change:
Gnat.Jetstream.API.KV.create_key/5now only creates a key when one doesn't already exist. Previously it behaved likeput_value/5and silently overwrote existing keys, and it returned:okeven when the server rejected the write. This aligns the library with the NATS server and the official clients: the publish is conditional on the key's current revision (Nats-Expected-Last-Subject-Sequence), so concurrent creators can't overwrite each other, and keys that were deleted or purged can be recreated. If you relied oncreate_keyoverwriting an existing key, useput_value/5instead. Thanks to @ericmj for #234- Returns
{:error, :key_exists}when a live value already exists for the key. - Validates the publish acknowledgement and returns
{:error, reason}when the server rejects the write. - Accepts a
:domainoption so the tombstone lookup works on JetStream domains.
- Returns
Gnat.Jetstream.API.KV.Entry.operation/1is now public and is the single definition of how KV records are classified as a put, delete, or purge. It follows the official clients: akv-operationheader takes precedence, and server-generatednats-marker-reasonmarkers mapMaxAgeandPurgeto:purgeandRemoveto:delete.create_key/5,keys/3,contents/3, and the watcher all share it.- Behavior change: the watcher now reports keys removed by a TTL limit marker as
:key_purgedinstead of:key_deleted. keys/3andcontents/3now exclude keys removed by limit markers, andcontents/3no longer includes purged keys with an empty value.
- Behavior change: the watcher now reports keys removed by a TTL limit marker as
1.17.0
- Adds support for
PullConsumerwithack_policy: :explicitthat pull in batch mode. This makes durable and multi-client consumers strongly consistent. Big thanks to @ericmj for #230- Also fixes a bug where batch consumers with
ack_policy: :allused to ignore return values of:nack,:termand:noreplywhich was confusing/incorrect (we logged an error and treated them as:ack). Now we will raise anArgumentErrorand require that yourPullConsumers withack_policy: :allcan only respond with:acksince we can't individually address the messages with our flow.
- Also fixes a bug where batch consumers with
Gnat.Jetstream.API.Objectnow validates that each chunk properly stored in the stream and does content hash validation on read. You can now rely on getting:okvs:errorfrom this API. Previously we didn't check the SHA-256 hash on read, so you could get:okeven if we missed a chunk or the final contents didn't line up with the recorded integrity hash. Again, thanks to @ericmj for #231
1.16.1
- Fix
PullConsumerdropping:request_expiresand:idle_heartbeatafter successfully processing a message. The resulting unbounded, heartbeat-free pull caused false watchdog reconnects on quiet streams. ACK-next requests now retain the configured pull options.
1.16
- Add support for the
nameconnection setting, which is reported to NATS monitoring endpoints. Contributed by @ahamez in #227 - Require Elixir 1.16+. Elixir 1.14 and 1.15 are no longer supported (both are past their upstream maintenance window). The CI matrix now runs on Elixir 1.16 through 1.19 and Erlang/OTP 26 through 28.
1.15
PullConsumernow requests anidle_heartbeat(defaults to half of:request_expires, i.e. 2.5s) from the server on every long-poll pull request and runs a local watchdog. If no traffic (data, status, or100heartbeat) is observed within2 * idle_heartbeat, the consumer assumes its pull request was lost (e.g. dropped during a JetStream leadership change without killing the TCP connection) and forces a reconnect. Configurable via the:idle_heartbeatand:heartbeat_check_intervaloptions.PullConsumeremits a new telemetry event[:gnat, :jetstream, :pull_consumer, :heartbeat_expired]when the watchdog fires. Measurements:%{gap_ms, threshold_ms}. Metadata:%{module, stream_name, consumer_name, connection_name}.- Improve parsing performance for large messages. Contributed by @cbecker in #225
- Remove the
cowlibdependency, which carried an unfixed CVE flagged bymix hex.audit. Header encoding/decoding is now handled internally with no change in behavior. Contributed by @tank-bohr in #226
1.14
- Add
PullConsumer.handle_connected/2optional callback to get consumer info - Add
PullConsumer.handle_status/2optional callback to observe status messages - Added support for
batch_sizeoption in PullConsumer options to pull messages and acknowledge them in batches. - Add
Gnat.Jetstream.API.KV.Entrywithfrom_message/2for parsing a raw NATS message from a KV bucket's underlying stream into a structured entry (operation, key, value, revision, created, delta). Intended to be shared between the built-inKV.Watcherand user-suppliedPullConsumerimplementations (e.g. caches that need to detect when they are caught up with the stream). Returns:ignorefor messages that are not KV records. KV.Watchernow usesKV.Entryinternally; its public callback API is unchanged. The push consumer it creates now enables server-driven flow control and a 5s idle heartbeat (matching nats.go's ordered-consumer defaults), so slow handlers apply backpressure instead of being dropped as slow consumers.- Behavior change (bugfix):
PullConsumerno longer forwards JetStream informational status messages (e.g.100idle heartbeat,409leadership change) toc:handle_message/2. These are not stream records and cannot be acked. In single-message mode the consumer now drops them and re-issues a pull request. - Add an optional
c:handle_status/2callback toGnat.Jetstream.PullConsumerfor users who want to observe status messages (e.g. log on409).
1.11
- Allow clients to force authentication without server auth_required by @mmmries in #205
- Support ephemeral consumers and auto-cleanup consumers in the PullConsumer module by @mmmries in #202
- Implement regularly scheduled PING/PONG health check by @mmmries in #200
- Add Erlang 28 with Elixir 1.18 to the build matrix by @davydog187 in #201
- Use Pager module for KV.contents by @mmmries in #198
- Hint
:timeoutoption in KV's typespec by @rixmann in #193
1.10
- Clarify authentication setup during test by @davydog187 in #187
- Test on Elixir 1.18 and NATS 2.10.24 by @davydog187 in #188
- Gnat.Jetstream.API.KV.info/3 by @davydog187 in #189
- Remove function_exported? check for Keyword.validate!/2 by @davydog187 in #186
- Tiny optimization to KV.list_buckets/1 by @davydog187 in #185
- make KV-watcher emit :key_added events when the message has a header by @rixmann in #191
- add :compression to stream attributes by @rixmann in #192
- fix: unknown field domain in Stream.create (#194) by @c0deaddict
- feat: add jetstream message metadata helper (#197) by @c0deaddict
- fix: deliver policy (#196) by @c0deaddict
1.9
- Housecleaning by @mmmries in #176
- switch to charlist sigils
- update to newest nkeys
- require elixir 1.14 and erlang 25+
- Fix incorrect useage of charlist by @davydog187 in #179
- Soft deprecate is_kv_bucket_stream?/1 in favor of kv_bucket_stream?/1 by @davydog187 in #183
- Clean up examples in KV by @davydog187 in #181
- Document options for Gnat.Jetstream.API.KV by @davydog187 in #180
1.8
- Integrated the jetstream functionality into this client directly https://github.com/nats-io/nats.ex/pull/146
- Add ability to list KV buckets https://github.com/nats-io/nats.ex/pull/152
- Improve CI Reliability https://github.com/nats-io/nats.ex/pull/154
- Bugfix to treat no streams as an empty list rather than a null https://github.com/nats-io/nats.ex/pull/155
- Added supported for
allow_directandmirror_directattributes of streams https://github.com/nats-io/nats.ex/pull/161 - Added support for
discard_new_per_subjectattribute of streams https://github.com/nats-io/nats.ex/pull/163 - Added support for
Object.list_bucketshttps://github.com/nats-io/nats.ex/pull/169
1.7
- Added support for the NATS services API, letting developers participate in service discovery and stats https://github.com/nats-io/nats.ex/pull/141
- A bugfix to remove the queue_group from a service config and some optimization for the services API https://github.com/nats-io/nats.ex/pull/145
1.6
- added the
no_respondersbehavior https://github.com/nats-io/nats.ex/pull/137
1.5
- add the
inbox_prefixoption https://github.com/nats-io/nats.ex/pull/121 - add the
Gnat.server_info/1function https://github.com/nats-io/nats.ex/pull/124 - fix header parsing issue https://github.com/nats-io/nats.ex/pull/125
1.4
- add the
Gnat.request_multi/4function https://github.com/nats-io/nats.ex/pull/120 - add elixir 1.13 to the test matrix
1.3
- adding support for sending and receiving headers https://github.com/nats-io/nats.ex/pull/116
1.2
Gnat.Serverbehaviour with support in theConsumerSupervisorhttps://github.com/nats-io/nats.ex/compare/1b1adc85e4b28231218ef87c7fc3445fce854377...b24a7e14325b51fbb93fde7e3d891d18b4fa8afb- avoid logging sensitive credentials https://github.com/nats-io/nats.ex/pull/105
- deprecate Gnat.ping, improved typespecs https://github.com/nats-io/nats.ex/pull/103
- relax the version constraint on nimble_parsec https://github.com/nats-io/nats.ex/issues/112
1.1
- add support for nkeys and NGS https://github.com/nats-io/nats.ex/pull/101
- Fix supervisor ConsumerSuperivsor crash https://github.com/nats-io/nats.ex/pull/96
1.0
- Make supervisors officially supported https://github.com/nats-io/nats.ex/pull/96
0.7.0
- update to telemetry 0.4 https://github.com/nats-io/nats.ex/pull/86 and https://github.com/nats-io/nats.ex/pull/87
- support for token authentication https://github.com/nats-io/nats.ex/pull/92
- support elixir 1.9 https://github.com/nats-io/nats.ex/pull/93
0.6.0
- Dropped support for Erlang < 19 and Elixir <= 1.5
- Added Telemetry to the project (thanks @rubysolo)
- Switched to nimble_parsec for parsing
- Updated benchmarking/performance information. We can now do 170k requests per second on a 16-core server.
- Fixed a bug around re-subscribing for the
ConsumerSupervisor - Pass
sidwhen delivering message (thanks @entone) - Documentation fixes from @deini and @johannestroeger
0.5.0
- Dropped support for Elixir 1.4 and OTP 18 releases. You will need to use Elixir 1.5+ and OTP 19+.
- Switched to running our tests against gnatsd
1.3.0