mirror of
https://github.com/taigrr/nats.docs
synced 2025-01-18 04:03:23 -08:00
452 lines
11 KiB
Markdown
452 lines
11 KiB
Markdown
# Wildcard Subscriptions
|
|
|
|
There is no special code to subscribe with a wildcard subject. Wildcards are a normal part of the subject name.
|
|
|
|
However, there is a common technique that may come in to play when you use wildcards. This technique is to use the subject provided with the incoming message to determine what to do with the message.
|
|
|
|
For example, you can subscribe using `*` and then act based on the actual subject.
|
|
|
|
{% tabs %}
|
|
{% tab title="Go" %}
|
|
```go
|
|
nc, err := nats.Connect("demo.nats.io")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer nc.Close()
|
|
|
|
// Use a WaitGroup to wait for 2 messages to arrive
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(2)
|
|
|
|
// Subscribe
|
|
if _, err := nc.Subscribe("time.*.east", func(m *nats.Msg) {
|
|
log.Printf("%s: %s", m.Subject, m.Data)
|
|
wg.Done()
|
|
}); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Wait for the 2 messages to come in
|
|
wg.Wait()
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="Java" %}
|
|
```java
|
|
Connection nc = Nats.connect("nats://demo.nats.io:4222");
|
|
|
|
// Use a latch to wait for 2 messages to arrive
|
|
CountDownLatch latch = new CountDownLatch(2);
|
|
|
|
// Create a dispatcher and inline message handler
|
|
Dispatcher d = nc.createDispatcher((msg) -> {
|
|
String subject = msg.getSubject();
|
|
String str = new String(msg.getData(), StandardCharsets.UTF_8);
|
|
System.out.println(subject + ": " + str);
|
|
latch.countDown();
|
|
});
|
|
|
|
// Subscribe
|
|
d.subscribe("time.*.east");
|
|
|
|
// Wait for messages to come in
|
|
latch.await();
|
|
|
|
// Close the connection
|
|
nc.close();
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="JavaScript" %}
|
|
```javascript
|
|
let nc = NATS.connect({
|
|
url: "nats://demo.nats.io:4222"});
|
|
|
|
nc.subscribe('time.us.*', (msg, reply, subject) => {
|
|
// converting timezones correctly in node requires a library
|
|
// this doesn't take into account *many* things.
|
|
let time = "";
|
|
switch (subject) {
|
|
case 'time.us.east':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/New_York"});
|
|
break;
|
|
case 'time.us.central':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Chicago"});
|
|
break;
|
|
case 'time.us.mountain':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Denver"});
|
|
break;
|
|
case 'time.us.west':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Los_Angeles"});
|
|
break;
|
|
default:
|
|
time = "I don't know what you are talking about Willis";
|
|
}
|
|
t.log(subject, time);
|
|
});
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="Python" %}
|
|
```python
|
|
nc = NATS()
|
|
|
|
await nc.connect(servers=["nats://demo.nats.io:4222"])
|
|
|
|
# Use queue to wait for 2 messages to arrive
|
|
queue = asyncio.Queue()
|
|
async def cb(msg):
|
|
await queue.put_nowait(msg)
|
|
|
|
await nc.subscribe("time.*.east", cb=cb)
|
|
|
|
# Send 2 messages and wait for them to come in
|
|
await nc.publish("time.A.east", b'A')
|
|
await nc.publish("time.B.east", b'B')
|
|
|
|
msg_A = await queue.get()
|
|
msg_B = await queue.get()
|
|
|
|
print("Msg A:", msg_A)
|
|
print("Msg B:", msg_B)
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="Ruby" %}
|
|
```ruby
|
|
require 'nats/client'
|
|
require 'fiber'
|
|
|
|
NATS.start(servers:["nats://127.0.0.1:4222"]) do |nc|
|
|
Fiber.new do
|
|
f = Fiber.current
|
|
|
|
nc.subscribe("time.*.east") do |msg, reply|
|
|
f.resume Time.now
|
|
end
|
|
|
|
nc.publish("time.A.east", "A")
|
|
nc.publish("time.B.east", "B")
|
|
|
|
# Use the response
|
|
msg_A = Fiber.yield
|
|
puts "Msg A: #{msg_A}"
|
|
|
|
msg_B = Fiber.yield
|
|
puts "Msg B: #{msg_B}"
|
|
|
|
end.resume
|
|
end
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="TypeScript" %}
|
|
```typescript
|
|
await nc.subscribe('time.us.*', (err, msg) => {
|
|
// converting timezones correctly in node requires a library
|
|
// this doesn't take into account *many* things.
|
|
let time = "";
|
|
switch (msg.subject) {
|
|
case 'time.us.east':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/New_York"});
|
|
break;
|
|
case 'time.us.central':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Chicago"});
|
|
break;
|
|
case 'time.us.mountain':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Denver"});
|
|
break;
|
|
case 'time.us.west':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Los_Angeles"});
|
|
break;
|
|
default:
|
|
time = "I don't know what you are talking about Willis";
|
|
}
|
|
console.log(msg.subject, time);
|
|
});
|
|
```
|
|
{% endtab %}
|
|
{% endtabs %}
|
|
|
|
or do something similar with `>`:
|
|
|
|
{% tabs %}
|
|
{% tab title="Go" %}
|
|
```go
|
|
nc, err := nats.Connect("demo.nats.io")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer nc.Close()
|
|
|
|
// Use a WaitGroup to wait for 4 messages to arrive
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(4)
|
|
|
|
// Subscribe
|
|
if _, err := nc.Subscribe("time.>", func(m *nats.Msg) {
|
|
log.Printf("%s: %s", m.Subject, m.Data)
|
|
wg.Done()
|
|
}); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Wait for the 4 messages to come in
|
|
wg.Wait()
|
|
|
|
// Close the connection
|
|
nc.Close()
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="Java" %}
|
|
```java
|
|
Connection nc = Nats.connect("nats://demo.nats.io:4222");
|
|
|
|
// Use a latch to wait for 4 messages to arrive
|
|
CountDownLatch latch = new CountDownLatch(4);
|
|
|
|
// Create a dispatcher and inline message handler
|
|
Dispatcher d = nc.createDispatcher((msg) -> {
|
|
String subject = msg.getSubject();
|
|
String str = new String(msg.getData(), StandardCharsets.UTF_8);
|
|
System.out.println(subject + ": " + str);
|
|
latch.countDown();
|
|
});
|
|
|
|
// Subscribe
|
|
d.subscribe("time.>");
|
|
|
|
// Wait for messages to come in
|
|
latch.await();
|
|
|
|
// Close the connection
|
|
nc.close();
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="JavaScript" %}
|
|
```javascript
|
|
let nc = NATS.connect({
|
|
url: "nats://demo.nats.io:4222"});
|
|
|
|
nc.subscribe('time.>', (msg, reply, subject) => {
|
|
// converting timezones correctly in node requires a library
|
|
// this doesn't take into account *many* things.
|
|
let time = "";
|
|
switch (subject) {
|
|
case 'time.us.east':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/New_York"});
|
|
break;
|
|
case 'time.us.central':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Chicago"});
|
|
break;
|
|
case 'time.us.mountain':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Denver"});
|
|
break;
|
|
case 'time.us.west':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Los_Angeles"});
|
|
break;
|
|
default:
|
|
time = "I don't know what you are talking about Willis";
|
|
}
|
|
t.log(subject, time);
|
|
});
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="Python" %}
|
|
```python
|
|
nc = NATS()
|
|
|
|
await nc.connect(servers=["nats://demo.nats.io:4222"])
|
|
|
|
# Use queue to wait for 4 messages to arrive
|
|
queue = asyncio.Queue()
|
|
async def cb(msg):
|
|
await queue.put(msg)
|
|
|
|
await nc.subscribe("time.>", cb=cb)
|
|
|
|
# Send 2 messages and wait for them to come in
|
|
await nc.publish("time.A.east", b'A')
|
|
await nc.publish("time.B.east", b'B')
|
|
await nc.publish("time.C.west", b'C')
|
|
await nc.publish("time.D.west", b'D')
|
|
|
|
for i in range(0, 4):
|
|
msg = await queue.get()
|
|
print("Msg:", msg)
|
|
|
|
await nc.close()
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="Ruby" %}
|
|
```ruby
|
|
require 'nats/client'
|
|
require 'fiber'
|
|
|
|
NATS.start(servers:["nats://127.0.0.1:4222"]) do |nc|
|
|
Fiber.new do
|
|
f = Fiber.current
|
|
|
|
nc.subscribe("time.>") do |msg, reply|
|
|
f.resume Time.now.to_f
|
|
end
|
|
|
|
nc.publish("time.A.east", "A")
|
|
nc.publish("time.B.east", "B")
|
|
nc.publish("time.C.west", "C")
|
|
nc.publish("time.D.west", "D")
|
|
|
|
# Use the response
|
|
4.times do
|
|
msg = Fiber.yield
|
|
puts "Msg: #{msg}"
|
|
end
|
|
end.resume
|
|
end
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="TypeScript" %}
|
|
```typescript
|
|
await nc.subscribe('time.>', (err, msg) => {
|
|
// converting timezones correctly in node requires a library
|
|
// this doesn't take into account *many* things.
|
|
let time = "";
|
|
switch (msg.subject) {
|
|
case 'time.us.east':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/New_York"});
|
|
break;
|
|
case 'time.us.central':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Chicago"});
|
|
break;
|
|
case 'time.us.mountain':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Denver"});
|
|
break;
|
|
case 'time.us.west':
|
|
time = new Date().toLocaleTimeString("en-us", {timeZone: "America/Los_Angeles"});
|
|
break;
|
|
default:
|
|
time = "I don't know what you are talking about Willis";
|
|
}
|
|
t.log(msg.subject, time);
|
|
});
|
|
```
|
|
{% endtab %}
|
|
{% endtabs %}
|
|
|
|
The following example can be used to test these two subscribers. The `*` subscriber should receive at most 2 messages, while the `>` subscriber receives 4. More importantly the `time.*.east` subscriber won't receive on `time.us.east.atlanta` because that won't match.
|
|
|
|
{% tabs %}
|
|
{% tab title="Go" %}
|
|
```go
|
|
nc, err := nats.Connect("demo.nats.io")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer nc.Close()
|
|
|
|
zoneID, err := time.LoadLocation("America/New_York")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
now := time.Now()
|
|
zoneDateTime := now.In(zoneID)
|
|
formatted := zoneDateTime.String()
|
|
|
|
nc.Publish("time.us.east", []byte(formatted))
|
|
nc.Publish("time.us.east.atlanta", []byte(formatted))
|
|
|
|
zoneID, err = time.LoadLocation("Europe/Warsaw")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
zoneDateTime = now.In(zoneID)
|
|
formatted = zoneDateTime.String()
|
|
|
|
nc.Publish("time.eu.east", []byte(formatted))
|
|
nc.Publish("time.eu.east.warsaw", []byte(formatted))
|
|
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="Java" %}
|
|
```java
|
|
Connection nc = Nats.connect("nats://demo.nats.io:4222");
|
|
ZoneId zoneId = ZoneId.of("America/New_York");
|
|
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(Instant.now(), zoneId);
|
|
String formatted = zonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME);
|
|
|
|
nc.publish("time.us.east", formatted.getBytes(StandardCharsets.UTF_8));
|
|
nc.publish("time.us.east.atlanta", formatted.getBytes(StandardCharsets.UTF_8));
|
|
|
|
zoneId = ZoneId.of("Europe/Warsaw");
|
|
zonedDateTime = ZonedDateTime.ofInstant(Instant.now(), zoneId);
|
|
formatted = zonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME);
|
|
nc.publish("time.eu.east", formatted.getBytes(StandardCharsets.UTF_8));
|
|
nc.publish("time.eu.east.warsaw", formatted.getBytes(StandardCharsets.UTF_8));
|
|
|
|
nc.flush(Duration.ZERO);
|
|
nc.close();
|
|
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="JavaScript" %}
|
|
```javascript
|
|
nc.publish('time.us.east');
|
|
nc.publish('time.us.central');
|
|
nc.publish('time.us.mountain');
|
|
nc.publish('time.us.west');
|
|
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="Python" %}
|
|
```python
|
|
nc = NATS()
|
|
|
|
await nc.connect(servers=["nats://demo.nats.io:4222"])
|
|
|
|
await nc.publish("time.us.east", b'...')
|
|
await nc.publish("time.us.east.atlanta", b'...')
|
|
|
|
await nc.publish("time.eu.east", b'...')
|
|
await nc.publish("time.eu.east.warsaw", b'...')
|
|
|
|
await nc.close()
|
|
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="Ruby" %}
|
|
```ruby
|
|
NATS.start do |nc|
|
|
nc.publish("time.us.east", '...')
|
|
nc.publish("time.us.east.atlanta", '...')
|
|
|
|
nc.publish("time.eu.east", '...')
|
|
nc.publish("time.eu.east.warsaw", '...')
|
|
|
|
nc.drain
|
|
end
|
|
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="TypeScript" %}
|
|
```typescript
|
|
nc.publish('time.us.east');
|
|
nc.publish('time.us.central');
|
|
nc.publish('time.us.mountain');
|
|
nc.publish('time.us.west');
|
|
|
|
```
|
|
{% endtab %}
|
|
{% endtabs %}
|
|
|