mirror of
https://github.com/taigrr/nats.docs
synced 2025-01-18 04:03:23 -08:00
fix folder structure from gitbook import
This commit is contained in:
119
developing-with-nats/events/README.md
Normal file
119
developing-with-nats/events/README.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Monitoring the Connection
|
||||
|
||||
Managing the interaction with the server is primarily the job of the client library but most of the libraries also provide some insight into what is happening under the covers.
|
||||
|
||||
For example, the client library may provide a mechanism to get the connection's current status:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
nc, err := nats.Connect("demo.nats.io", nats.Name("API Example"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
getStatusTxt := func(nc *nats.Conn) string {
|
||||
switch nc.Status() {
|
||||
case nats.CONNECTED:
|
||||
return "Connected"
|
||||
case nats.CLOSED:
|
||||
return "Closed"
|
||||
default:
|
||||
return "Other"
|
||||
}
|
||||
}
|
||||
log.Printf("The connection is %v\n", getStatusTxt(nc))
|
||||
|
||||
nc.Close()
|
||||
|
||||
log.Printf("The connection is %v\n", getStatusTxt(nc))
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
Connection nc = Nats.connect("nats://demo.nats.io:4222");
|
||||
|
||||
System.out.println("The Connection is: " + nc.getStatus());
|
||||
|
||||
nc.close();
|
||||
|
||||
System.out.println("The Connection is: " + nc.getStatus());
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let nc = NATS.connect("nats://demo.nats.io:4222");
|
||||
|
||||
// on node you *must* register an error listener. If not registered
|
||||
// the library emits an 'error' event, the node process will exit.
|
||||
nc.on('error', (err) => {
|
||||
t.log('client got an error:', err);
|
||||
});
|
||||
|
||||
if(nc.closed) {
|
||||
t.log('client is closed');
|
||||
} else {
|
||||
t.log('client is not closed');
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
await nc.connect(
|
||||
servers=["nats://demo.nats.io:4222"],
|
||||
)
|
||||
|
||||
# Do something with the connection.
|
||||
|
||||
print("The connection is connected?", nc.is_connected)
|
||||
|
||||
while True:
|
||||
if nc.is_reconnecting:
|
||||
print("Reconnecting to NATS...")
|
||||
break
|
||||
await asyncio.sleep(1)
|
||||
|
||||
await nc.close()
|
||||
|
||||
print("The connection is closed?", nc.is_closed)
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
NATS.start(max_reconnect_attempts: 2) do |nc|
|
||||
puts "Connect is connected?: #{nc.connected?}"
|
||||
|
||||
timer = EM.add_periodic_timer(1) do
|
||||
if nc.closing?
|
||||
puts "Connection closed..."
|
||||
EM.cancel_timer(timer)
|
||||
NATS.stop
|
||||
end
|
||||
|
||||
if nc.reconnecting?
|
||||
puts "Reconnecting to NATS..."
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
if(nc.isClosed()) {
|
||||
t.log('the client is closed');
|
||||
} else {
|
||||
t.log('the client is running');
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
357
developing-with-nats/events/events.md
Normal file
357
developing-with-nats/events/events.md
Normal file
@@ -0,0 +1,357 @@
|
||||
# Listen for Connection Events
|
||||
|
||||
While the connection status is interesting, it is perhaps more interesting to know when the status changes. Most, if not all, of the NATS client libraries provide a way to listen for events related to the connection and its status.
|
||||
|
||||
The actual API for these listeners is language dependent, but the following examples show a few of the more common use cases. See the API documentation for the client library you are using for more specific instructions.
|
||||
|
||||
Connection events may include the connection being closed, disconnected or reconnected. Reconnecting involves a disconnect and connect, but depending on the library implementation may also include multiple disconnects as the client tries to find a server, or the server is rebooted.
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
// There is not a single listener for connection events in the NATS Go Client.
|
||||
// Instead, you can set individual event handlers using:
|
||||
|
||||
DisconnectHandler(cb ConnHandler)
|
||||
ReconnectHandler(cb ConnHandler)
|
||||
ClosedHandler(cb ConnHandler)
|
||||
DiscoveredServersHandler(cb ConnHandler)
|
||||
ErrorHandler(cb ErrHandler)
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
class MyConnectionListener implements ConnectionListener {
|
||||
public void connectionEvent(Connection natsConnection, Events event) {
|
||||
System.out.println("Connection event - "+event);
|
||||
}
|
||||
}
|
||||
|
||||
public class SetConnectionListener {
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
Options options = new Options.Builder().
|
||||
server("nats://demo.nats.io:4222").
|
||||
connectionListener(new MyConnectionListener()). // Set the listener
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let nc = NATS.connect("nats://demo.nats.io:4222");
|
||||
|
||||
nc.on('error', (err) => {
|
||||
t.log('error', err);
|
||||
});
|
||||
|
||||
nc.on('connect', () => {
|
||||
t.log('client connected');
|
||||
});
|
||||
|
||||
nc.on('disconnect', () => {
|
||||
t.log('client disconnected');
|
||||
});
|
||||
|
||||
nc.on('reconnecting', () => {
|
||||
t.log('client reconnecting');
|
||||
});
|
||||
|
||||
nc.on('reconnect', () => {
|
||||
t.log('client reconnected');
|
||||
});
|
||||
|
||||
nc.on('close', () => {
|
||||
t.log('client closed');
|
||||
});
|
||||
|
||||
nc.on('permission_error', (err) => {
|
||||
t.log('permission_error', err);
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
# Asyncio NATS client can be defined a number of event callbacks
|
||||
async def disconnected_cb():
|
||||
print("Got disconnected!")
|
||||
|
||||
async def reconnected_cb():
|
||||
# See who we are connected to on reconnect.
|
||||
print("Got reconnected to {url}".format(url=nc.connected_url.netloc))
|
||||
|
||||
async def error_cb(e):
|
||||
print("There was an error: {}".format(e))
|
||||
|
||||
async def closed_cb():
|
||||
print("Connection is closed")
|
||||
|
||||
# Setup callbacks to be notified on disconnects and reconnects
|
||||
options["disconnected_cb"] = disconnected_cb
|
||||
options["reconnected_cb"] = reconnected_cb
|
||||
|
||||
# Setup callbacks to be notified when there is an error
|
||||
# or connection is closed.
|
||||
options["error_cb"] = error_cb
|
||||
options["closed_cb"] = closed_cb
|
||||
|
||||
await nc.connect(**options)
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
r# There is not a single listener for connection events in the Ruby NATS Client.
|
||||
# Instead, you can set individual event handlers using:
|
||||
|
||||
NATS.on_disconnect do
|
||||
end
|
||||
|
||||
NATS.on_reconnect do
|
||||
end
|
||||
|
||||
NATS.on_close do
|
||||
end
|
||||
|
||||
NATS.on_error do
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
// connect will happen once - the first connect
|
||||
nc.on('connect', (nc) => {
|
||||
// nc is the connection that connected
|
||||
t.log('client connected');
|
||||
});
|
||||
|
||||
nc.on('disconnect', (url) => {
|
||||
// nc is the connection that reconnected
|
||||
t.log('disconnected from', url);
|
||||
});
|
||||
|
||||
nc.on('reconnecting', (url) => {
|
||||
t.log('reconnecting to', url);
|
||||
});
|
||||
|
||||
nc.on('reconnect', (nc, url) => {
|
||||
// nc is the connection that reconnected
|
||||
t.log('reconnected to', url);
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
## Listen for New Servers
|
||||
|
||||
When working with a cluster, servers may be added or changed. Some of the clients allow you to listen for this notification:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
// Be notified if a new server joins the cluster.
|
||||
// Print all the known servers and the only the ones that were discovered.
|
||||
nc, err := nats.Connect("demo.nats.io",
|
||||
nats.DiscoveredServersHandler(func(nc *nats.Conn) {
|
||||
log.Printf("Known servers: %v\n", nc.Servers())
|
||||
log.Printf("Discovered servers: %v\n", nc.DiscoveredServers())
|
||||
}))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
class ServersAddedListener implements ConnectionListener {
|
||||
public void connectionEvent(Connection nc, Events event) {
|
||||
if (event == Events.DISCOVERED_SERVERS) {
|
||||
for (String server : nc.getServers()) {
|
||||
System.out.println("Known server: "+server);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ListenForNewServers {
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
Options options = new Options.Builder().
|
||||
server("nats://demo.nats.io:4222").
|
||||
connectionListener(new ServersAddedListener()). // Set the listener
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let nc = NATS.connect("nats://demo.nats.io:4222");
|
||||
nc.on('serversDiscovered', (urls) => {
|
||||
t.log('serversDiscovered', urls);
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
# Asyncio NATS client does not support discovered servers handler right now
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
r# The Ruby NATS client does not support discovered servers handler right now
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
nc.on('serversChanged', (ce) => {
|
||||
t.log('servers changed\n', 'added: ',ce.added, 'removed:', ce.removed);
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
## Listen for Errors
|
||||
|
||||
The client library may separate server-to-client errors from events. Many server events are not handled by application code and result in the connection being closed. Listening for the errors can be very useful for debugging problems.
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
// Set the callback that will be invoked when an asynchronous error occurs.
|
||||
nc, err := nats.Connect("demo.nats.io",
|
||||
nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) {
|
||||
log.Printf("Error: %v", err)
|
||||
}))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
class MyErrorListener implements ErrorListener {
|
||||
public void errorOccurred(Connection conn, String error)
|
||||
{
|
||||
System.out.println("The server notificed the client with: "+error);
|
||||
}
|
||||
|
||||
public void exceptionOccurred(Connection conn, Exception exp) {
|
||||
System.out.println("The connection handled an exception: "+exp.getLocalizedMessage());
|
||||
}
|
||||
|
||||
public void slowConsumerDetected(Connection conn, Consumer consumer) {
|
||||
System.out.println("A slow consumer was detected.");
|
||||
}
|
||||
}
|
||||
|
||||
public class SetErrorListener {
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
Options options = new Options.Builder().
|
||||
server("nats://demo.nats.io:4222").
|
||||
errorListener(new MyErrorListener()). // Set the listener
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let nc = NATS.connect("nats://demo.nats.io:4222");
|
||||
|
||||
// on node you *must* register an error listener. If not registered
|
||||
// the library emits an 'error' event, the node process will exit.
|
||||
nc.on('error', (err) => {
|
||||
t.log('client got an error:', err);
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
async def error_cb(e):
|
||||
print("Error: ", e)
|
||||
|
||||
await nc.connect(
|
||||
servers=["nats://demo.nats.io:4222"],
|
||||
reconnect_time_wait=10,
|
||||
error_cb=error_cb,
|
||||
)
|
||||
|
||||
# Do something with the connection.
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
require 'nats/client'
|
||||
|
||||
NATS.start(servers:["nats://demo.nats.io:4222"]) do |nc|
|
||||
nc.on_error do |e|
|
||||
puts "Error: #{e}"
|
||||
end
|
||||
|
||||
nc.close
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
// on node you *must* register an error listener. If not registered
|
||||
// the library emits an 'error' event, the node process will exit.
|
||||
nc.on('error', (err) => {
|
||||
t.log('client got an out of band error:', err);
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
237
developing-with-nats/events/slow.md
Normal file
237
developing-with-nats/events/slow.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# Slow Consumers
|
||||
|
||||
NATS is designed to move messages through the server quickly. As a result, NATS depends on the applications to consider and respond to changing message rates. The server will do a bit of impedance matching, but if a client is too slow the server will eventually cut them off. These cut off connections are called _slow consumers_.
|
||||
|
||||
One way some of the libraries deal with bursty message traffic is to cache incoming messages for a subscription. So if an application can handle 10 messages per second and sometimes receives 20 messages per second, the library may hold the extra 10 to give the application time to catch up. To the server, the application will appear to be handling the messages and consider the connection healthy. It is up to the client library to decide what to do when the cache is too big, but most client libraries will drop incoming messages.
|
||||
|
||||
Receiving and dropping messages from the server keeps the connection to the server healthy, but creates an application requirement. There are several common patterns:
|
||||
|
||||
* Use request/reply to throttle the sender and prevent overloading the subscriber
|
||||
* Use a queue with multiple subscribers splitting the work
|
||||
* Persist messages with something like NATS streaming
|
||||
|
||||
Libraries that cache incoming messages may provide two controls on the incoming queue, or pending messages. These are useful if the problem is bursty publishers and not a continuous performance mismatch. Disabling these limits can be dangerous in production and although setting these limits to 0 may help find problems, it is also a dangerous proposition in production.
|
||||
|
||||
> Check your libraries documentation for the default settings, and support for disabling these limits.
|
||||
|
||||
The incoming cache is usually per subscriber, but again, check the specific documentation for your client library.
|
||||
|
||||
## Limiting Incoming/Pending Messages by Count and Bytes
|
||||
|
||||
The first way that the incoming queue can be limited is by message count. The second way to limit the incoming queue is by total size. For example, to limit the incoming cache to 1,000 messages or 5mb whichever comes first:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
nc, err := nats.Connect("demo.nats.io")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Subscribe
|
||||
sub1, err := nc.Subscribe("updates", func(m *nats.Msg) {})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Set limits of 1000 messages or 5MB, whichever comes first
|
||||
sub1.SetPendingLimits(1000, 5*1024*1024)
|
||||
|
||||
// Subscribe
|
||||
sub2, err := nc.Subscribe("updates", func(m *nats.Msg) {})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Set no limits for this subscription
|
||||
sub2.SetPendingLimits(-1, -1)
|
||||
|
||||
// Close the connection
|
||||
nc.Close()
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
Connection nc = Nats.connect("nats://demo.nats.io:4222");
|
||||
|
||||
Dispatcher d = nc.createDispatcher((msg) -> {
|
||||
// do something
|
||||
});
|
||||
|
||||
d.subscribe("updates");
|
||||
|
||||
d.setPendingLimits(1_000, 5 * 1024 * 1024); // Set limits on a dispatcher
|
||||
|
||||
// Subscribe
|
||||
Subscription sub = nc.subscribe("updates");
|
||||
|
||||
sub.setPendingLimits(1_000, 5 * 1024 * 1024); // Set limits on a subscription
|
||||
|
||||
// Do something
|
||||
|
||||
// Close the connection
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
// slow pending limits are not configurable on node-nats
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
await nc.connect(servers=["nats://demo.nats.io:4222"])
|
||||
|
||||
future = asyncio.Future()
|
||||
|
||||
async def cb(msg):
|
||||
nonlocal future
|
||||
future.set_result(msg)
|
||||
|
||||
# Set limits of 1000 messages or 5MB
|
||||
await nc.subscribe("updates", cb=cb, pending_bytes_limit=5*1024*1024, pending_msgs_limit=1000)
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
# The Ruby NATS client currently does not have option to customize slow consumer limits per sub.
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
// slow pending limits are not configurable on TypeScript NATS client.
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
## Detect a Slow Consumer and Check for Dropped Messages
|
||||
|
||||
When a slow consumer is detected and messages are about to be dropped, the library may notify the application. This process may be similar to other errors or may involve a custom callback.
|
||||
|
||||
Some libraries, like Java, will not send this notification on every dropped message because that could be noisy. Rather the notification may be sent once per time the subscriber gets behind. Libraries may also provide a way to get a count of dropped messages so that applications can at least detect a problem is occurring.
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
// Set the callback that will be invoked when an asynchronous error occurs.
|
||||
nc, err := nats.Connect("demo.nats.io", nats.ErrorHandler(logSlowConsumer))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
class SlowConsumerReporter implements ErrorListener {
|
||||
public void errorOccurred(Connection conn, String error)
|
||||
{
|
||||
}
|
||||
|
||||
public void exceptionOccurred(Connection conn, Exception exp) {
|
||||
}
|
||||
|
||||
// Detect slow consumers
|
||||
public void slowConsumerDetected(Connection conn, Consumer consumer) {
|
||||
// Get the dropped count
|
||||
System.out.println("A slow consumer dropped messages: "+ consumer.getDroppedCount());
|
||||
}
|
||||
}
|
||||
|
||||
public class SlowConsumerListener {
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
Options options = new Options.Builder().
|
||||
server("nats://demo.nats.io:4222").
|
||||
errorListener(new SlowConsumerReporter()). // Set the listener
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
// slow consumer detection is not configurable on NATS JavaScript client.
|
||||
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
|
||||
nc = NATS()
|
||||
|
||||
async def error_cb(e):
|
||||
if type(e) is nats.aio.errors.ErrSlowConsumer:
|
||||
print("Slow consumer error, unsubscribing from handling further messages...")
|
||||
await nc.unsubscribe(e.sid)
|
||||
|
||||
await nc.connect(
|
||||
servers=["nats://demo.nats.io:4222"],
|
||||
error_cb=error_cb,
|
||||
)
|
||||
|
||||
msgs = []
|
||||
future = asyncio.Future()
|
||||
async def cb(msg):
|
||||
nonlocal msgs
|
||||
nonlocal future
|
||||
print(msg)
|
||||
msgs.append(msg)
|
||||
|
||||
if len(msgs) == 3:
|
||||
# Head of line blocking on other messages caused
|
||||
# by single message proccesing taking long...
|
||||
await asyncio.sleep(1)
|
||||
|
||||
await nc.subscribe("updates", cb=cb, pending_msgs_limit=5)
|
||||
|
||||
for i in range(0, 10):
|
||||
await nc.publish("updates", "msg #{}".format(i).encode())
|
||||
await asyncio.sleep(0)
|
||||
|
||||
try:
|
||||
await asyncio.wait_for(future, 1)
|
||||
except asyncio.TimeoutError:
|
||||
pass
|
||||
|
||||
for msg in msgs:
|
||||
print("[Received]", msg)
|
||||
|
||||
await nc.close()
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
# The Ruby NATS client currently does not have option to customize slow consumer limits per sub.
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
// slow consumer detection is not configurable on NATS TypeScript client.
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
Reference in New Issue
Block a user