Golang client for NATS, the cloud native messaging system.

NATS - Go Client

A Go client for the NATS messaging system.

License Apache 2 FOSSA Status Go Report Card Build Status GoDoc Coverage Status

Installation

# Go client
go get github.com/nats-io/nats.go/

# Server
go get github.com/nats-io/nats-server

When using or transitioning to Go modules support:

# Go client latest or explicit version
go get github.com/nats-io/nats.go/@latest
go get github.com/nats-io/nats.go/@v1.10.0

# For latest NATS Server, add /v2 at the end
go get github.com/nats-io/nats-server/v2

# NATS Server v1 is installed otherwise
# go get github.com/nats-io/nats-server

Basic Usage

import nats "github.com/nats-io/nats.go"

// Connect to a server
nc, _ := nats.Connect(nats.DefaultURL)

// Simple Publisher
nc.Publish("foo", []byte("Hello World"))

// Simple Async Subscriber
nc.Subscribe("foo", func(m *nats.Msg) {
    fmt.Printf("Received a message: %s\n", string(m.Data))
})

// Responding to a request message
nc.Subscribe("request", func(m *nats.Msg) {
    m.Respond([]byte("answer is 42"))
})

// Simple Sync Subscriber
sub, err := nc.SubscribeSync("foo")
m, err := sub.NextMsg(timeout)

// Channel Subscriber
ch := make(chan *nats.Msg, 64)
sub, err := nc.ChanSubscribe("foo", ch)
msg := <- ch

// Unsubscribe
sub.Unsubscribe()

// Drain
sub.Drain()

// Requests
msg, err := nc.Request("help", []byte("help me"), 10*time.Millisecond)

// Replies
nc.Subscribe("help", func(m *nats.Msg) {
    nc.Publish(m.Reply, []byte("I can help!"))
})

// Drain connection (Preferred for responders)
// Close() not needed if this is called.
nc.Drain()

// Close connection
nc.Close()

Encoded Connections

nc, _ := nats.Connect(nats.DefaultURL)
c, _ := nats.NewEncodedConn(nc, nats.JSON_ENCODER)
defer c.Close()

// Simple Publisher
c.Publish("foo", "Hello World")

// Simple Async Subscriber
c.Subscribe("foo", func(s string) {
    fmt.Printf("Received a message: %s\n", s)
})

// EncodedConn can Publish any raw Go type using the registered Encoder
type person struct {
     Name     string
     Address  string
     Age      int
}

// Go type Subscriber
c.Subscribe("hello", func(p *person) {
    fmt.Printf("Received a person: %+v\n", p)
})

me := &person{Name: "derek", Age: 22, Address: "140 New Montgomery Street, San Francisco, CA"}

// Go type Publisher
c.Publish("hello", me)

// Unsubscribe
sub, err := c.Subscribe("foo", nil)
// ...
sub.Unsubscribe()

// Requests
var response string
err = c.Request("help", "help me", &response, 10*time.Millisecond)
if err != nil {
    fmt.Printf("Request failed: %v\n", err)
}

// Replying
c.Subscribe("help", func(subj, reply string, msg string) {
    c.Publish(reply, "I can help!")
})

// Close connection
c.Close();

New Authentication (Nkeys and User Credentials)

This requires server with version >= 2.0.0

NATS servers have a new security and authentication mechanism to authenticate with user credentials and Nkeys. The simplest form is to use the helper method UserCredentials(credsFilepath).

nc, err := nats.Connect(url, nats.UserCredentials("user.creds"))

The helper methods creates two callback handlers to present the user JWT and sign the nonce challenge from the server. The core client library never has direct access to your private key and simply performs the callback for signing the server challenge. The helper will load and wipe and erase memory it uses for each connect or reconnect.

The helper also can take two entries, one for the JWT and one for the NKey seed file.

nc, err := nats.Connect(url, nats.UserCredentials("user.jwt", "user.nk"))

You can also set the callback handlers directly and manage challenge signing directly.

nc, err := nats.Connect(url, nats.UserJWT(jwtCB, sigCB))

Bare Nkeys are also supported. The nkey seed should be in a read only file, e.g. seed.txt

> cat seed.txt
# This is my seed nkey!
SUAGMJH5XLGZKQQWAWKRZJIGMOU4HPFUYLXJMXOO5NLFEO2OOQJ5LPRDPM

This is a helper function which will load and decode and do the proper signing for the server nonce. It will clear memory in between invocations. You can choose to use the low level option and provide the public key and a signature callback on your own.

opt, err := nats.NkeyOptionFromSeed("seed.txt")
nc, err := nats.Connect(serverUrl, opt)

// Direct
nc, err := nats.Connect(serverUrl, nats.Nkey(pubNkey, sigCB))

TLS

// tls as a scheme will enable secure connections by default. This will also verify the server name.
nc, err := nats.Connect("tls://nats.demo.io:4443")

// If you are using a self-signed certificate, you need to have a tls.Config with RootCAs setup.
// We provide a helper method to make this case easier.
nc, err = nats.Connect("tls://localhost:4443", nats.RootCAs("./configs/certs/ca.pem"))

// If the server requires client certificate, there is an helper function for that too:
cert := nats.ClientCert("./configs/certs/client-cert.pem", "./configs/certs/client-key.pem")
nc, err = nats.Connect("tls://localhost:4443", cert)

// You can also supply a complete tls.Config

certFile := "./configs/certs/client-cert.pem"
keyFile := "./configs/certs/client-key.pem"
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
    t.Fatalf("error parsing X509 certificate/key pair: %v", err)
}

config := &tls.Config{
    ServerName: 	opts.Host,
    Certificates: 	[]tls.Certificate{cert},
    RootCAs:    	pool,
    MinVersion: 	tls.VersionTLS12,
}

nc, err = nats.Connect("nats://localhost:4443", nats.Secure(config))
if err != nil {
	t.Fatalf("Got an error on Connect with Secure Options: %+v\n", err)
}

Using Go Channels (netchan)

nc, _ := nats.Connect(nats.DefaultURL)
ec, _ := nats.NewEncodedConn(nc, nats.JSON_ENCODER)
defer ec.Close()

type person struct {
     Name     string
     Address  string
     Age      int
}

recvCh := make(chan *person)
ec.BindRecvChan("hello", recvCh)

sendCh := make(chan *person)
ec.BindSendChan("hello", sendCh)

me := &person{Name: "derek", Age: 22, Address: "140 New Montgomery Street"}

// Send via Go channels
sendCh <- me

// Receive via Go channels
who := <- recvCh

Wildcard Subscriptions

// "*" matches any token, at any level of the subject.
nc.Subscribe("foo.*.baz", func(m *Msg) {
    fmt.Printf("Msg received on [%s] : %s\n", m.Subject, string(m.Data));
})

nc.Subscribe("foo.bar.*", func(m *Msg) {
    fmt.Printf("Msg received on [%s] : %s\n", m.Subject, string(m.Data));
})

// ">" matches any length of the tail of a subject, and can only be the last token
// E.g. 'foo.>' will match 'foo.bar', 'foo.bar.baz', 'foo.foo.bar.bax.22'
nc.Subscribe("foo.>", func(m *Msg) {
    fmt.Printf("Msg received on [%s] : %s\n", m.Subject, string(m.Data));
})

// Matches all of the above
nc.Publish("foo.bar.baz", []byte("Hello World"))

Queue Groups

// All subscriptions with the same queue name will form a queue group.
// Each message will be delivered to only one subscriber per queue group,
// using queuing semantics. You can have as many queue groups as you wish.
// Normal subscribers will continue to work as expected.

nc.QueueSubscribe("foo", "job_workers", func(_ *Msg) {
  received += 1;
})

Advanced Usage

// Normally, the library will return an error when trying to connect and
// there is no server running. The RetryOnFailedConnect option will set
// the connection in reconnecting state if it failed to connect right away.
nc, err := nats.Connect(nats.DefaultURL,
    nats.RetryOnFailedConnect(true),
    nats.MaxReconnects(10),
    nats.ReconnectWait(time.Second),
    nats.ReconnectHandler(func(_ *nats.Conn) {
        // Note that this will be invoked for the first asynchronous connect.
    }))
if err != nil {
    // Should not return an error even if it can't connect, but you still
    // need to check in case there are some configuration errors.
}

// Flush connection to server, returns when all messages have been processed.
nc.Flush()
fmt.Println("All clear!")

// FlushTimeout specifies a timeout value as well.
err := nc.FlushTimeout(1*time.Second)
if err != nil {
    fmt.Println("All clear!")
} else {
    fmt.Println("Flushed timed out!")
}

// Auto-unsubscribe after MAX_WANTED messages received
const MAX_WANTED = 10
sub, err := nc.Subscribe("foo")
sub.AutoUnsubscribe(MAX_WANTED)

// Multiple connections
nc1 := nats.Connect("nats://host1:4222")
nc2 := nats.Connect("nats://host2:4222")

nc1.Subscribe("foo", func(m *Msg) {
    fmt.Printf("Received a message: %s\n", string(m.Data))
})

nc2.Publish("foo", []byte("Hello World!"));

Clustered Usage

var servers = "nats://localhost:1222, nats://localhost:1223, nats://localhost:1224"

nc, err := nats.Connect(servers)

// Optionally set ReconnectWait and MaxReconnect attempts.
// This example means 10 seconds total per backend.
nc, err = nats.Connect(servers, nats.MaxReconnects(5), nats.ReconnectWait(2 * time.Second))

// You can also add some jitter for the reconnection.
// This call will add up to 500 milliseconds for non TLS connections and 2 seconds for TLS connections.
// If not specified, the library defaults to 100 milliseconds and 1 second, respectively.
nc, err = nats.Connect(servers, nats.ReconnectJitter(500*time.Millisecond, 2*time.Second))

// You can also specify a custom reconnect delay handler. If set, the library will invoke it when it has tried
// all URLs in its list. The value returned will be used as the total sleep time, so add your own jitter.
// The library will pass the number of times it went through the whole list.
nc, err = nats.Connect(servers, nats.CustomReconnectDelay(func(attempts int) time.Duration {
    return someBackoffFunction(attempts)
}))

// Optionally disable randomization of the server pool
nc, err = nats.Connect(servers, nats.DontRandomize())

// Setup callbacks to be notified on disconnects, reconnects and connection closed.
nc, err = nats.Connect(servers,
	nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
		fmt.Printf("Got disconnected! Reason: %q\n", err)
	}),
	nats.ReconnectHandler(func(nc *nats.Conn) {
		fmt.Printf("Got reconnected to %v!\n", nc.ConnectedUrl())
	}),
	nats.ClosedHandler(func(nc *nats.Conn) {
		fmt.Printf("Connection closed. Reason: %q\n", nc.LastError())
	})
)

// When connecting to a mesh of servers with auto-discovery capabilities,
// you may need to provide a username/password or token in order to connect
// to any server in that mesh when authentication is required.
// Instead of providing the credentials in the initial URL, you will use
// new option setters:
nc, err = nats.Connect("nats://localhost:4222", nats.UserInfo("foo", "bar"))

// For token based authentication:
nc, err = nats.Connect("nats://localhost:4222", nats.Token("S3cretT0ken"))

// You can even pass the two at the same time in case one of the server
// in the mesh requires token instead of user name and password.
nc, err = nats.Connect("nats://localhost:4222",
    nats.UserInfo("foo", "bar"),
    nats.Token("S3cretT0ken"))

// Note that if credentials are specified in the initial URLs, they take
// precedence on the credentials specified through the options.
// For instance, in the connect call below, the client library will use
// the user "my" and password "pwd" to connect to localhost:4222, however,
// it will use username "foo" and password "bar" when (re)connecting to
// a different server URL that it got as part of the auto-discovery.
nc, err = nats.Connect("nats://my:pwd@localhost:4222", nats.UserInfo("foo", "bar"))

Context support (+Go 1.7)

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

nc, err := nats.Connect(nats.DefaultURL)

// Request with context
msg, err := nc.RequestWithContext(ctx, "foo", []byte("bar"))

// Synchronous subscriber with context
sub, err := nc.SubscribeSync("foo")
msg, err := sub.NextMsgWithContext(ctx)

// Encoded Request with context
c, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER)
type request struct {
	Message string `json:"message"`
}
type response struct {
	Code int `json:"code"`
}
req := &request{Message: "Hello"}
resp := &response{}
err := c.RequestWithContext(ctx, "foo", req, resp)

License

Unless otherwise noted, the NATS source files are distributed under the Apache Version 2.0 license found in the LICENSE file.

FOSSA Status

Owner
NATS - The Cloud Native Messaging System
NATS is a simple, secure and performant communications system for digital systems, services and devices.
NATS - The Cloud Native Messaging System
Comments
  • Cannot go get client

    Cannot go get client

    I have a project that is outside of the go src folder, I am running go 1.12.5 on windows amd64 (win10) This is my first attempt to use NATS, not a great start!

    Getting this error:

    go get github.com/nats-io/nats.go/ go: finding github.com/nats-io/nats.go v1.8.0 go: finding github.com/nats-io/nkeys v0.0.2 go: finding github.com/nats-io/nuid v1.0.1 go: finding golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 CreateFile github.com/nats-io/nats.go: The system cannot find the path specified.

  • Not seeing v2.0.0 for nats-io/nats.go

    Not seeing v2.0.0 for nats-io/nats.go

    $ mkdir mymod
    $ cd mymod
    $ touch go.mod
    $ go get github.com/nats-io/nats.go@latest
    stat github.com/nats-io/nats.go: no such file or directory
    $ go get github.com/nats-io/nats.go/@latest
    $ cat go.mod
    module mymod
    
    go 1.12
    
    require (
    	github.com/nats-io/go-nats v1.7.2 // indirect
    	github.com/nats-io/nats.go v1.7.2 // indirect
    	github.com/nats-io/nkeys v0.0.2 // indirect
    	github.com/nats-io/nuid v1.0.1 // indirect
    )
    $ 
    

    Shouldn't it be v2.0.0?

  • Add TokenHandler option to connection options

    Add TokenHandler option to connection options

    This pull request adds TokenFunc to the Options struct. This adds a way to generate a new token every time a connectProto is built and allows the use of expiring tokens like JWTs when authenticating.

  • Mock NATS server implementation in order to be able to write unit tests

    Mock NATS server implementation in order to be able to write unit tests

    In order for consumers to be able to write unit tests for their subscription logic, they need a way to publish messages. Right now, this is not possible because a mock NATS server implementation has not been provided.

    This leaves the consumer with only one option: bring up an actual NATS server in your test suite. Which effectively means you are writing an integration test now. I want to avoid this as I want to test my service logic without bringing up external dependencies. Unit tests should be deterministic and not rely on any kind of network connectivity (e.g. bringing up NATS server locally would imply a port needs to be free on CI).

    The other option consumers have is to simply just unit test the message handler they pass in to their call to Subscribe(subj string, cb MsgHandler).

    What do you propose? Is there any workaround to this? Ideally, this package would provide some kind of mock NATS server somewhat similar to how opentracing go provides a mocktracer - https://github.com/opentracing/opentracing-go/tree/master/mocktracer so folks can write tests to ensure that their spans are being created as expected.

  • Subject interning

    Subject interning

    @derekcollison Please review. The price of this comparison near 2ns per operation but in case of plain subscriptions it reduces single allocation per operation and results in speedup. Looking forward for your comments. If somehow to know beforehand that subscription using wildcard then it's possible to make it no cost. So I suggest to merge this pull request first, than make some changes to subscription struct to contain isWildcard bool field and then switch to using it. so no need to compare strings just single if isWildcard and nothings else.

  • message consume too slow

    message consume too slow

    i created a stream in Retention=WorkQueuePolicy, and published 1 million messages. then i start to consume it.

    for {
      msgs, err := sub.Fetch(10000, nats.Context(ctx))
     for _, msg := range msgs {
    	msg.AckSync()
     }
    }
    

    the first batch fetched fast enough, after a few loops, Fetch( ) becomes too slow (> 10 seconds), and the whole batch ack time become too slow also.

  • Jetstream KV watcher does not watch after NATS server restart

    Jetstream KV watcher does not watch after NATS server restart

    KV watcher does not do its job after Nats server is restarted.

    nats.go version v1.17.0 nats server v2.9.1

    Steps or code to reproduce the issue:

    • Implement simple watch-all logic.
    • Run nats server and client. Make updates with keys in a bucket. See, updates are coming.
    • Restart nats server
    watcher, err := flowsKV.WatchAll(nats.Context(ctx))
    	if err != nil {
    		return err
    	}
    	defer watcher.Stop()
    	for {
    		select {
    		case update := <-watcher.Updates():
    			if update == nil {
    				break
    			}
    			
    		case <-ctx.Done():
    			return nil
    		}
    	}
    

    Expected result:

    After nats restart watcher backs to printing latest KV updates

    Actual result:

    Watcher gives no updates Error happens time to time nats: consumer not active on connection [101] for subscription on "$KV.bucket.>"


    js.Subscribe() without nats.OrderedConsumer() option behaves correctly, but this option is built-in into kv.Watch...

    Thanks.

  • Clean up logic around max handling to regress

    Clean up logic around max handling to regress

    I'm trying to test changes against my new Java client and believe that this is a little cleaner and fixes some edge race conditions. There are several more and not sure that these changes should be applied until a wider look at delivered/max logic is looked at here...

  • Unsubscribe does not allow consumption of already fetched messages

    Unsubscribe does not allow consumption of already fetched messages

    Perhaps there is a good reason for this, but it appears that Unsubscribe sets it's message channel to nil which is potentially a destructive action.

    Unless there is another way to consume messages that have already been fetched by the client. I would expect the channel to be closed to prevent future writes but to remain available for reads.

    s.unsubscribe()
    ...consume remaining messages in channel
    

    I am working on a PR that addresses this. I am curious though if this was intended behavior and if I am misusing it.

  • Golang client for NATS web socket

    Golang client for NATS web socket

    nats 2.2 supports binary web sockets which means I can use golang to build wasm based web apps to communicate with NATS server ?

    i was told via the nats.ws repo that the nats.go client may support compiling to wasm .

    Is this true ? It would be rather awesome

  • Return error if actual consumer configuration is different

    Return error if actual consumer configuration is different

    Feature Request

    When creating subscriptions I can pass extra options, e.g.:

    sub, err := js.PullSubscribe("TEST.*", "testing", nats.MaxDeliver(3))
    

    The consumer is created in NATS if it didn't exist yet:

    $ nats con info TEST testing
    Information for Consumer TEST > testing created 2021-08-17T11:37:10+02:00
    
    Configuration:
    
            Durable Name: testing
               Pull Mode: true
          Filter Subject: TEST.*
             Deliver All: true
              Ack Policy: Explicit
                Ack Wait: 30s
           Replay Policy: Instant
      Maximum Deliveries: 3
         Max Ack Pending: 20,000
       Max Waiting Pulls: 512
    
    State:
    ...
    

    If I then change the options, e.g.:

    sub, err := js.PullSubscribe("TEST.*", "testing", nats.MaxDeliver(5))
    

    Then the new value is silently ignored and the consumer still has Maximum Deliveries: 3. The options seems to be used only when creating a new consumer, but ignored otherwise (some of them at least).

    While it might not be feasible to transparently update the consumer, I would expect to get an error telling me that the requested options do not match the actual consumer configuration.

    Use Case:

    I can very easily imagine a situation where a developer changes the options (adds a new one, removes one, changes a value) thinking that it will work. For someone unfamiliar with NATS JS it's not obvious that some consumer object exists in NATS itself and that these options are not just client-side connection options. It's easy for the code to diverge from the actual configuration.

    Proposed Change:

    Compare the actual consumer configuration with the requested one an return an error if there's a mismatch.

    It seems that the existing configuration is already read (the info variable), so this shouldn't affect performance.

    Who Benefits From The Change(s)?

    Unwitting developers trying to change the consumer configuration.

    Alternative Approaches

    Update the consumer configuration to match the requested one.

  • add optional metadata to service

    add optional metadata to service

    This allows to add optional meta data to a service, for instance, in my case, the services are dispatched across multiple machines, on the edge.

    The ability to add meta data like this, and retrieve them in the PING, INFO... is very useful :

    	// ...
    	hostname, _ := os.Hostname()
    	externalIP := getmyip.ViaOpenDNS()
    
    	config := micro.Config{
    		Name:        "EchoService",
    		Version:     "1.0.0",
    		Description: "Send back what you receive",
    		Meta: map[string]interface{}{
    			"hostname":    hostname,
    			"external-ip": externalIP,
    		},
    		Endpoint: micro.Endpoint{
    			Subject: "echo",
    			Handler: echoHandler,
    		},
    		// ...
    	}
    	svc, err := micro.AddService(nc, config)
    	// ...
    
  • Unbound memory footprint growth with slow consumers

    Unbound memory footprint growth with slow consumers

    Defect

    • [x] Included nats.go version
    • [x] Included a [Minimal, Complete, and Verifiable example] (https://stackoverflow.com/help/mcve)

    Versions of nats.go and the nats-server if one was involved:

    nats.go @ 95a7e5090fda9532342375fe2954362905d43434 (today's main branch) nats-server @ 2.9.8 (probably not relevant)

    OS/Container environment:

    Not relevant

    Steps or code to reproduce the issue:

    • Create one or more NATS consumers that can't/won't keep up with actual traffic, e.g:
      • Sync subscription not being consumed
      • Async subscription where handler is slow
    • Publish messages faster than consumers consume them
    • Observe memory at the client grow until OOM

    This test (artificially) reproduces the situation in just a few seconds: https://github.com/mprimi/nats.go/commit/78cee182ea34ed864e2b67653a9b81fd2f1ecf1c

    Expected result:

    Client of slow consumers starts dropping messages. (This is NATS without JetStream, so message loss is acceptable)

    Actual result:

    Messages build up in the consumer client until the program starts trashing or gets OOM killed

    Comments

    The attached repro shows how a client can blow up in just a few seconds:

        [...]
        Published 1319 messages (12 MiB), runtime mem: 59 GiB
        Published 1379 messages (13 MiB), runtime mem: 62 GiB
        Published 1435 messages (14 MiB), runtime mem: 65 GiB
        Published 1551 messages (15 MiB), runtime mem: 70 GiB
        Published 1607 messages (15 MiB), runtime mem: 73 GiB
        Published 1663 messages (16 MiB), runtime mem: 76 GiB
       
    Process finished with the exit code 1 (OOM panic)
    

    The test is artificial, probably no real-world application behaves this way (e.g. thousands of subscriptions to the same subject, none being consumed).

    However this behavior is generalizable, this is the real takeaway:

    If an application is consuming subscriptions at a rate slower than messages are being published, then the client memory usage will keep growing without bounds. Eventually this application will run out of memory and crash (it may take hours/days/weeks instead of seconds).

    Suggested change

    The client should cap the amount of memory used to store unconsumed messages. Once the limit is reached, the client should start dropping messages.

    Optimizations

    This experiment also suggests a couple possible optimizations.

    Take the following situation:

    • Publisher is publishing the same 10KiB message 1000 times with subject 's'
    • Subscriber has 5000 subscriptions matching 's'

    As of now, the subscriber client will use an estimate ~50GiB (10KiB * 1000 messages * 5000 subscriptions)

    1. If the message content was de-duped internally and shared across subscriptions, then the memory footprint could be just 10MiB (10KiB * 1000 messages)

    2. If the message content was further de-duped because the client notices it's the same message being published over and over, then the footprint could be just 10KiB

    (I'm not suggesting semantical de-duping -- just internal memory storage de-duping, not visible outside the client)

    These optimizations may not be very beneficial in 'real world' scenario, since a client may not often be receiving tons of duplicate messages in the same subscription or across subscriptions.

  • JetStreamContext AddConsumer calls ConsumerInfo without passing context

    JetStreamContext AddConsumer calls ConsumerInfo without passing context

    Defect

    Make sure that these boxes are checked before submitting your issue -- thank you!

    • [x] Included nats.go version
    • [x] Included a [Minimal, Complete, and Verifiable example] (https://stackoverflow.com/help/mcve)

    Versions of nats.go and the nats-server if one was involved:

    nats.go 1.21.0 nats-server 2.9.9

    OS/Container environment:

    server is running using nats:2.9.9-alpine docker

    Steps or code to reproduce the issue:

    When using the AddConsumer with a custom context (by passing nats.Context(...) as jsOpts), with a durable name, which means it needs to check it's config against the server. This can be seen at this code: https://github.com/nats-io/nats.go/blob/6c6add8d63597f84bee75d37bb1520e01552a02d/jsm.go#L312-L326

    But the call to js.ConsumerInfo isn't passed the context, which results in it using the defaults of the configured jetstream. As a result, I can't control manually the context and cancel it, even thought the function call looks like it should do it.

    	consumer, err := js.AddConsumer("A", &nats.ConsumerConfig{
    		Durable:        consumerName,
    		FilterSubject:  subject,
    	}, nats.Context(ctx))
    

    Expected result:

    As long as I don't cancel the context, the client should error with context deadline reached.

    Actual result:

    If for 5 seconds (the default timeout interval) the server didn't respond, the context is cancel and AddConsumer fails.

Simple TCP proxy to visualise NATS client/server traffic
Simple TCP proxy to visualise NATS client/server traffic

NATS uses a simple publish/subscribe style plain-text protocol to communicate between a NATS Server and its clients. Whilst this connection should remain opaque to the user, it can be quite handy to see the data being passed from time to time - this tool does just that (it also saves me loading Wireshark and filtering the NATS traffic).

Jan 15, 2022
A gRPC based pub/sub messaging system

Arrebato Arrebato is a gRPC based pub/sub messaging system with an emphasis on strong message typing & message verification using public-key cryptogra

Aug 3, 2022
Instant messaging platform. Backend in Go and Client in Flutter

Seemer Messaging Server Instant messaging server. Backend in pure Go (license GPL 3.0), client-side binding in Flutter as well as gRPC client support

Nov 28, 2022
A Realtime API Gateway used with NATS to build REST, real time, and RPC APIs, where all your clients are synchronized seamlessly.
A Realtime API Gateway used with NATS to build REST, real time, and RPC APIs, where all your clients are synchronized seamlessly.

Realtime API Gateway Synchronize Your Clients Visit Resgate.io for guides, live demos, and resources. Resgate is a Go project implementing a realtime

Dec 31, 2022
A pizza store design using NATS pub sub queue.
A pizza store design using NATS pub sub queue.

A pizza store design using NATS pub sub queue.

Oct 12, 2022
Json to rpc example with envoy, go, grpc, nats

grpc-nats-envoy json to rpc example with envoy, go, grpc, redis This repo is a mirror of https://github.com/charlesonunze/grpc-redis-envoy-example It

Dec 7, 2021
A cloud native distributed streaming network telemetry.
A cloud native distributed streaming network telemetry.

Panoptes Streaming Panoptes Streaming is a cloud native distributed streaming network telemetry. It can be installed as a single binary or clustered n

Sep 27, 2022
The Cloud Native Application Proxy
The Cloud Native Application Proxy

Traefik (pronounced traffic) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. Traefik integrates with your ex

Dec 30, 2022
MOSN is a cloud native proxy for edge or service mesh. https://mosn.io
MOSN is a cloud native proxy for edge or service mesh. https://mosn.io

中文 MOSN is a network proxy written in Golang. It can be used as a cloud-native network data plane, providing services with the following proxy functio

Dec 30, 2022
Cloud Native Tunnel
Cloud Native Tunnel

inlets is a Cloud Native Tunnel written in Go Expose your local endpoints to the Internet or within a remote network, without touching firewalls. Foll

Jan 4, 2022
Whats-da-twilio - Small Golang HTTP Server that leverages Twilio's API for calling and SMS messaging

What's da twilio Description Small Golang HTTP Server that leverages Twilio's API for calling and SMS messaging Note: trial Twilio accounts and number

Dec 31, 2021
go implementation of fissions web-native file system

wnfs-go go language implementation of the fission web-native file system, using the typescript implementation as a reference. Development Status: Work

Oct 15, 2022
🤘 The native golang ssh client to execute your commands over ssh connection. 🚀🚀
🤘 The native golang ssh client to execute your commands over ssh connection. 🚀🚀

Golang SSH Client. Fast and easy golang ssh client module. Goph is a lightweight Go SSH client focusing on simplicity! Installation ❘ Features ❘ Usage

Dec 24, 2022
纯Go编写的IM,完全自定义协议的高性能即时通讯服务(High-performance instant messaging service with fully customizable protocol)
纯Go编写的IM,完全自定义协议的高性能即时通讯服务(High-performance instant messaging service with fully customizable protocol)

LiMaoIM (Everything so easy) This project is a simple and easy to use, powerful performance, simple design concept instant messaging service, fully cu

Dec 5, 2022
Centralized Configuration System written in Golang - Spring cloud compatible
Centralized Configuration System written in Golang - Spring cloud compatible

Centralized Configuration System What is Vecosy Vecosy is a configuration service exposed through REST/GRPC. Is Spring Cloud Conf compatible and also

Dec 13, 2022
Native ZooKeeper client for Go. This project is no longer maintained. Please use https://github.com/go-zookeeper/zk instead.

Native Go Zookeeper Client Library License 3-clause BSD. See LICENSE file. This Repository is No Longer Maintained Please use https://github.com/go-zo

Dec 19, 2022
Tapestry is an underlying distributed object location and retrieval system (DOLR) which can be used to store and locate objects. This distributed system provides an interface for storing and retrieving key-value pairs.

Tapestry This project implements Tapestry, an underlying distributed object location and retrieval system (DOLR) which can be used to store and locate

Mar 16, 2022
☁️ Cloud Torrent: a self-hosted remote torrent client
☁️ Cloud Torrent: a self-hosted remote torrent client

Cloud torrent is a a self-hosted remote torrent client, written in Go (golang). You start torrents remotely, which are downloaded as sets of files on

Jan 6, 2023
hazelcast go-client interaction with hazelcast cloud

sample-application hazelcast go-client interaction with hazelcast cloud smart-client-deployment https://guides.hazelcast.org/kubernetes-external-clien

Nov 23, 2022