Skip to content

Releases: nats-io/nats.py

Release v2.9.0

26 Aug 15:18
6286035
Compare
Choose a tag to compare

Added

  • Added micro module implementing services ADR-32 (#566)

Thank you to @charbonnierg for the community implementation that served as a kick-off point.

import asyncio
import contextlib
import signal

import nats
import nats.micro


async def echo(req) -> None:
   """Echo the request data back to the client."""
   await req.respond(req.data)


async def main():
   # Define an event to signal when to quit
   quit_event = asyncio.Event()

   # Attach signal handler to the event loop
   loop = asyncio.get_event_loop()
   for sig in (signal.Signals.SIGINT, signal.Signals.SIGTERM):
       loop.add_signal_handler(sig, lambda *_: quit_event.set())

   # Create an async exit stack
   async with contextlib.AsyncExitStack() as stack:
       # Connect to NATS
       nc = await stack.enter_async_context(await nats.connect())

       # Add the service
       service = await stack.enter_async_context(
           await nats.micro.add_service(nc, name="demo_service", version="0.0.1")
       )

       group = service.add_group(name="demo")
       # Add an endpoint to the service
       await group.add_endpoint(
           name="echo",
           handler=echo,
       )
       # Wait for the quit event
       await quit_event.wait()


if __name__ == "__main__":
   asyncio.run(main())
  • Added pagination to JetStream stream info (#594)
nc = await nats.connect()
js = nc.jetstream()
jsm = nc.jsm()

for i in range(300):
  await jsm.add_stream(name=f"stream_{i}")

streams_page_1 = await jsm.streams_info(offset=0)
streams_page_1 = await jsm.streams_info(offset=256)

Fixed

  • Fixed resource leak in JetStream push subscription (#597)

Release v2.8.0

26 Jun 05:11
v2.8.0
981e5d6
Compare
Choose a tag to compare

Added

  • Added publish_async method to jetstream

    ack_future = await js.publish_async("foo", b'bar')
    await ack_future
  • Added the ability to file contents as user_credentials (#546)

from nats.aio.client import RawCredentials
...
await nats.connect(user_credentials=RawCredentials("<creds file contents as string>"))

Fixed

  • Fixed a race condition that could trigger error callbacks if a timeout and a response from a request where in-conflict (#573).

Release v2.7.2

28 Feb 02:15
ae09ea4
Compare
Choose a tag to compare
  • Added heartbeat option to pull subscribers fetch API

    await sub.fetch(1, timeout=1, heartbeat=0.1)

    It can be useful to help distinguish API timeouts from not receiving messages:

    try:
      await sub.fetch(100, timeout=1, heartbeat=0.2)
    except nats.js.errors.FetchTimeoutError:
      # timeout due to not receiving messages
    except asyncio.TimeoutError:
      # unexpected timeout
  • Added subject_transform to add_consumer

    await js.add_stream(
      name="TRANSFORMS",
      subjects=["test", "foo"],
      subject_transform=nats.js.api.SubjectTransform(
        src=">", dest="transformed.>"
      ),
    )
  • Added subject_transform to sources as well:

    transformed_source = nats.js.api.StreamSource(
        name="TRANSFORMS",
        # The source filters cannot overlap.
        subject_transforms=[
            nats.js.api.SubjectTransform(
                src="transformed.>", dest="fromtest.transformed.>"
            ),
            nats.js.api.SubjectTransform(
                src="foo.>", dest="fromtest.foo.>"
            ),
        ],
    )
    await js.add_stream(
      name="SOURCING",
      sources=[transformed_source],
    )
  • Added backoff option to add_consumer

    await js.add_consumer(
              "events",
              durable_name="a",
              max_deliver=3,    # has to be greater than length as backoff array
              backoff=[1, 2],   # defined in seconds
              ack_wait=999999,  # ignored once using backoff
              max_ack_pending=3,
              filter_subject="events.>",
          )
  • Added compression to add_consumer

    await js.add_stream(
      name="COMPRESSION",
      subjects=["test", "foo"],
      compression="s2",
    )
  • Added metadata to add_stream

    await js.add_stream(
        name="META",
        subjects=["test", "foo"],
        metadata={'foo': 'bar'},
    )

Release v2.7.0

05 Feb 03:06
16e905a
Compare
Choose a tag to compare

Added

  • Added support for multiple filter consumers when using nats-server +v2.10
    This is only supported when using the pull_subscribe_bind API:
await jsm.add_stream(name="multi", subjects=["a", "b", "c.>"])
cinfo = await jsm.add_consumer(
    "multi",
    name="myconsumer",
    filter_subjects=["a", "b"],
)
psub = await js.pull_subscribe_bind("multi", "myconsumer")
msgs = await psub.fetch(2)
for msg in msgs:
  await msg.ack()
  • Added subjects_filter option to js.stream_info() API
stream = await js.add_stream(name="foo", subjects=["foo.>"])
for i in range(0, 5):
    await js.publish("foo.%d" % i, b'A')

si = await js.stream_info("foo", subjects_filter=">")
print(si.state.subjects)
# => {'foo.0': 1, 'foo.1': 1, 'foo.2': 1, 'foo.3': 1, 'foo.4': 1}

Changed

  • Changed kv.watch default inactive_threshold cleanup timeout to be 5 minutes.
    It can now be customized as well by passing inactive_threshold as argument in seconds:
w = await kv.watchall(inactive_threshold=30.0)
  • Changed pull_subscribe_bind first argument to be called consumer instead of durable
    since it also supports ephemeral consumers. This should be backwards compatible.
psub = await js.pull_subscribe_bind(consumer="myconsumer", stream="test")

Release v2.6.0

28 Oct 00:01
v2.6.0
8d3f053
Compare
Choose a tag to compare

Added

  • Added support to ephemeral pull consumers (#412)

Changed

  • Changed default max control line to 4K as in the server since v2.2

Fixed

  • Fixed ordered consumer implementation not being recreated when consumer deleted (#510)
  • Fixed accounting issue pending data which would have caused slow consumers on ordered consumers using next_msg
  • Fixed subscribe to missing stream not raising NotFoundError (#499 )

Full Changelog: v2.5.0...v2.6.0

Release v2.5.0

27 Oct 23:53
12fe022
Compare
Choose a tag to compare

Added

  • Add tls_handshake_first option (#511)

Fixed

  • fix: improve types on kv/object_store updates by @tekumara in #497
  • fix: KeyWatcher.updates() returns type of Entry | None by @tekumara in #500

New Contributors

Full Changelog: v2.4.0...v2.5.0

Release v2.4.0

14 Sep 17:51
7e8dd94
Compare
Choose a tag to compare

Fixed

  • Fixed Python 3.7 compatibility: use uuid4 to gen unique task names by @Lancetnik in #457
  • Fixed websocket connection when not using TLS (#463)
  • Remove msg from fut.cancel to ensure backward compatibility by @raprek in #479
  • Fixed connect() by @dsodx in #484
  • Fixed auth to respect provided server address username and password if no_auth_user is set by @anthonyjacques20 in #488
  • Fixed reconnect in websockets: CLOSED WS connection detection by @sebastian-king in #477

Added

Improved

New Contributors

Full Changelog: v2.3.1...v2.4.0

Release v2.3.0

03 Jun 04:14
533bd8f
Compare
Choose a tag to compare
pip install nats-py

Added

  • Added object store feature based on initial contribution by @domderen (#452 || #446)

Upload example:

import nats
import asyncio

async def main():
    nc = await nats.connect("locahost", name="object.py")
    js = nc.jetstream()
    obs = await js.create_object_store("nats-py-object-store")

    object_name = 'my-file.mp4'
    with open(object_name) as f:
        await obs.put(object_name, f)

    await nc.close()

if __name__ == '__main__':
    asyncio.run(main())

Download example:

import nats
import asyncio

async def main():
    nc = await nats.connect("localhost", name="object.py")
    js = nc.jetstream()
    obs = await js.object_store("nats-py-object-store")

    files = await obs.list()
    for f in files:
        print(f.name, "-", f.size)

    object_name = 'my-file.mp4'
    with open("copy-"+object_name, 'w') as f:
        await obs.get(object_name, f)

    await nc.close()

if __name__ == '__main__':
    asyncio.run(main())
  • Updated the WebSocketTransport to detect the attempt to upgrade the connection to TLS by @allanbank (#443)

Fixed

  • Fixed example from jetstream pull subscriber sample by @csuriano23 (#366)
  • Fixed issue where protocol was changed for ws and wss if no port was
    provided by @bvanelli (#371)
  • Fixed untreated error callbacks when using websockets by @bvanelli (#361 || #375)
  • Fixes to next_msg and tasks cancellation (#446)

Changed

  • Updated signatures for 'servers' and 'discovered_servers' properties by @jonchammer (#374)
  • Move configs from setup.cfg into pyproject.toml by @orsinium (#394)
  • Forbid None for Msg.Metadata fields by @orsinium (#401)
  • Convert republish value into dataclass by @orsinium (#405)
  • Change the type of client_id to int by @kkqy (#435)
  • Raise asyncio.CancelledError back by @charbonnierg (#378)
  • Send credentials even if no_auth_required is set on INFO (#399)
  • Add sid property to nats.aio.msg.Msg class by @charbonnierg (#430)
  • Add custom inbox prefix support for JS pull subscribe by @alparslanavci (#419)

Internal changes

New Contributors

Release v2.2.0

02 Oct 06:32
Compare
Choose a tag to compare

Added

  • Added support sending requests with reconnected client (by @charbonnierg #343)
  • Added websockets support (by @bvanelli #356)
  • Added support for new KV features (#347 | #355)
    • direct mode
    • republish
  • Added support to create consumers with a name (#358)

Changed

  • Modernizes the way we package and distribute nats.py by using PEP621 (by @4383 #341)
  • Removed the server address from reconnection logs in examples (by @4383 #346)
  • Makes connections examples more configurable (by @4383 (#342)
  • update account limits (#357)

Fixed

Full Changelog: v2.1.7...v2.2.0

Release v2.1.7

18 Aug 19:52
12c85cc
Compare
Choose a tag to compare

Changed

  • Changed nc.request to have more unique inboxes to avoid accidental reuse of response tokens #335