mirror of
https://github.com/nats-io/nats.go.git
synced 2025-09-27 04:46:01 +08:00
798 lines
21 KiB
Go
798 lines
21 KiB
Go
// Copyright 2012-2023 The NATS Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package nats_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/nats-io/nats.go"
|
|
)
|
|
|
|
// Shows different ways to create a Conn.
|
|
func ExampleConnect() {
|
|
nc, _ := nats.Connect("demo.nats.io")
|
|
nc.Close()
|
|
|
|
nc, _ = nats.Connect("nats://derek:secretpassword@demo.nats.io:4222")
|
|
nc.Close()
|
|
|
|
nc, _ = nats.Connect("tls://derek:secretpassword@demo.nats.io:4443")
|
|
nc.Close()
|
|
|
|
opts := nats.Options{
|
|
AllowReconnect: true,
|
|
MaxReconnect: 10,
|
|
ReconnectWait: 5 * time.Second,
|
|
Timeout: 1 * time.Second,
|
|
}
|
|
|
|
nc, _ = opts.Connect()
|
|
nc.Close()
|
|
}
|
|
|
|
type skipTLSDialer struct {
|
|
dialer *net.Dialer
|
|
skipTLS bool
|
|
}
|
|
|
|
func (sd *skipTLSDialer) Dial(network, address string) (net.Conn, error) {
|
|
return sd.dialer.Dial(network, address)
|
|
}
|
|
|
|
func (sd *skipTLSDialer) SkipTLSHandshake() bool {
|
|
return sd.skipTLS
|
|
}
|
|
|
|
func ExampleCustomDialer() {
|
|
// Given the following CustomDialer implementation:
|
|
//
|
|
// type skipTLSDialer struct {
|
|
// dialer *net.Dialer
|
|
// skipTLS bool
|
|
// }
|
|
//
|
|
// func (sd *skipTLSDialer) Dial(network, address string) (net.Conn, error) {
|
|
// return sd.dialer.Dial(network, address)
|
|
// }
|
|
//
|
|
// func (sd *skipTLSDialer) SkipTLSHandshake() bool {
|
|
// return true
|
|
// }
|
|
//
|
|
sd := &skipTLSDialer{dialer: &net.Dialer{Timeout: 2 * time.Second}, skipTLS: true}
|
|
nc, _ := nats.Connect("demo.nats.io", nats.SetCustomDialer(sd))
|
|
defer nc.Close()
|
|
}
|
|
|
|
// This Example shows an asynchronous subscriber.
|
|
func ExampleConn_Subscribe() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
nc.Subscribe("foo", func(m *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(m.Data))
|
|
})
|
|
}
|
|
|
|
func ExampleConn_ForceReconnect() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
nc.Subscribe("foo", func(m *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(m.Data))
|
|
})
|
|
|
|
// Reconnect to the server.
|
|
// the subscription will be recreated after the reconnect.
|
|
nc.ForceReconnect()
|
|
}
|
|
|
|
// This Example shows a synchronous subscriber.
|
|
func ExampleConn_SubscribeSync() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
sub, _ := nc.SubscribeSync("foo")
|
|
m, err := sub.NextMsg(1 * time.Second)
|
|
if err == nil {
|
|
fmt.Printf("Received a message: %s\n", string(m.Data))
|
|
} else {
|
|
fmt.Println("NextMsg timed out.")
|
|
}
|
|
}
|
|
|
|
func ExampleSubscription_NextMsg() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
sub, _ := nc.SubscribeSync("foo")
|
|
m, err := sub.NextMsg(1 * time.Second)
|
|
if err == nil {
|
|
fmt.Printf("Received a message: %s\n", string(m.Data))
|
|
} else {
|
|
fmt.Println("NextMsg timed out.")
|
|
}
|
|
}
|
|
|
|
func ExampleSubscription_Unsubscribe() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
sub, _ := nc.SubscribeSync("foo")
|
|
// ...
|
|
sub.Unsubscribe()
|
|
}
|
|
|
|
func ExampleConn_Publish() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
nc.Publish("foo", []byte("Hello World!"))
|
|
}
|
|
|
|
func ExampleConn_PublishMsg() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
msg := &nats.Msg{Subject: "foo", Reply: "bar", Data: []byte("Hello World!")}
|
|
nc.PublishMsg(msg)
|
|
}
|
|
|
|
func ExampleConn_Flush() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
msg := &nats.Msg{Subject: "foo", Reply: "bar", Data: []byte("Hello World!")}
|
|
for i := 0; i < 1000; i++ {
|
|
nc.PublishMsg(msg)
|
|
}
|
|
err := nc.Flush()
|
|
if err == nil {
|
|
// Everything has been processed by the server for nc *Conn.
|
|
}
|
|
}
|
|
|
|
func ExampleConn_FlushTimeout() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
msg := &nats.Msg{Subject: "foo", Reply: "bar", Data: []byte("Hello World!")}
|
|
for i := 0; i < 1000; i++ {
|
|
nc.PublishMsg(msg)
|
|
}
|
|
// Only wait for up to 1 second for Flush
|
|
err := nc.FlushTimeout(1 * time.Second)
|
|
if err == nil {
|
|
// Everything has been processed by the server for nc *Conn.
|
|
}
|
|
}
|
|
|
|
func ExampleConn_Request() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
nc.Subscribe("foo", func(m *nats.Msg) {
|
|
nc.Publish(m.Reply, []byte("I will help you"))
|
|
})
|
|
nc.Request("foo", []byte("help"), 50*time.Millisecond)
|
|
}
|
|
|
|
func ExampleConn_QueueSubscribe() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
received := 0
|
|
|
|
nc.QueueSubscribe("foo", "worker_group", func(_ *nats.Msg) {
|
|
received++
|
|
})
|
|
}
|
|
|
|
func ExampleSubscription_AutoUnsubscribe() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
defer nc.Close()
|
|
|
|
received, wanted, total := 0, 10, 100
|
|
|
|
sub, _ := nc.Subscribe("foo", func(_ *nats.Msg) {
|
|
received++
|
|
})
|
|
sub.AutoUnsubscribe(wanted)
|
|
|
|
for i := 0; i < total; i++ {
|
|
nc.Publish("foo", []byte("Hello"))
|
|
}
|
|
nc.Flush()
|
|
|
|
fmt.Printf("Received = %d", received)
|
|
}
|
|
|
|
func ExampleConn_Close() {
|
|
nc, _ := nats.Connect(nats.DefaultURL)
|
|
nc.Close()
|
|
}
|
|
|
|
func ExampleJetStream() {
|
|
nc, err := nats.Connect("localhost")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Use the JetStream context to produce and consumer messages
|
|
// that have been persisted.
|
|
js, err := nc.JetStream(nats.PublishAsyncMaxPending(256))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
js.AddStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
Subjects: []string{"foo"},
|
|
})
|
|
|
|
js.Publish("foo", []byte("Hello JS!"))
|
|
|
|
// Publish messages asynchronously.
|
|
for i := 0; i < 500; i++ {
|
|
js.PublishAsync("foo", []byte("Hello JS Async!"))
|
|
}
|
|
select {
|
|
case <-js.PublishAsyncComplete():
|
|
case <-time.After(5 * time.Second):
|
|
fmt.Println("Did not resolve in time")
|
|
}
|
|
|
|
// Create async consumer on subject 'foo'. Async subscribers
|
|
// ack a message once exiting the callback.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
meta, _ := msg.Metadata()
|
|
fmt.Printf("Stream Sequence : %v\n", meta.Sequence.Stream)
|
|
fmt.Printf("Consumer Sequence: %v\n", meta.Sequence.Consumer)
|
|
})
|
|
|
|
// Async subscriber with manual acks.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
msg.Ack()
|
|
}, nats.ManualAck())
|
|
|
|
// Async queue subscription where members load balance the
|
|
// received messages together.
|
|
// If no consumer name is specified, either with nats.Bind()
|
|
// or nats.Durable() options, the queue name is used as the
|
|
// durable name (that is, as if you were passing the
|
|
// nats.Durable(<queue group name>) option.
|
|
// It is recommended to use nats.Bind() or nats.Durable()
|
|
// and preferably create the JetStream consumer beforehand
|
|
// (using js.AddConsumer) so that the JS consumer is not
|
|
// deleted on an Unsubscribe() or Drain() when the member
|
|
// that created the consumer goes away first.
|
|
// Check Godoc for the QueueSubscribe() API for more details.
|
|
js.QueueSubscribe("foo", "group", func(msg *nats.Msg) {
|
|
msg.Ack()
|
|
}, nats.ManualAck())
|
|
|
|
// Subscriber to consume messages synchronously.
|
|
sub, _ := js.SubscribeSync("foo")
|
|
msg, _ := sub.NextMsg(2 * time.Second)
|
|
msg.Ack()
|
|
|
|
// We can add a member to the group, with this member using
|
|
// the synchronous version of the QueueSubscribe.
|
|
sub, _ = js.QueueSubscribeSync("foo", "group")
|
|
msg, _ = sub.NextMsg(2 * time.Second)
|
|
msg.Ack()
|
|
|
|
// ChanSubscribe
|
|
msgCh := make(chan *nats.Msg, 8192)
|
|
sub, _ = js.ChanSubscribe("foo", msgCh)
|
|
|
|
select {
|
|
case msg := <-msgCh:
|
|
fmt.Println("[Received]", msg)
|
|
case <-time.After(1 * time.Second):
|
|
}
|
|
|
|
// Create Pull based consumer with maximum 128 inflight.
|
|
sub, _ = js.PullSubscribe("foo", "wq", nats.PullMaxWaiting(128))
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
default:
|
|
}
|
|
|
|
msgs, _ := sub.Fetch(10, nats.Context(ctx))
|
|
for _, msg := range msgs {
|
|
msg.Ack()
|
|
}
|
|
}
|
|
}
|
|
|
|
// A JetStream context can be configured with a default timeout using nats.MaxWait
|
|
// or with a custom API prefix in case of using an imported JetStream from another account.
|
|
func ExampleJSOpt() {
|
|
nc, err := nats.Connect("localhost")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Use the JetStream context to manage streams and consumers (with nats.APIPrefix JSOpt)
|
|
js, err := nc.JetStream(nats.APIPrefix("dlc"), nats.MaxWait(5*time.Second))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
sub, _ := js.SubscribeSync("foo")
|
|
js.Publish("foo", []byte("Hello JS!"))
|
|
sub.NextMsg(2 * time.Second)
|
|
}
|
|
|
|
func ExampleJetStreamManager() {
|
|
nc, _ := nats.Connect("localhost")
|
|
|
|
js, _ := nc.JetStream()
|
|
|
|
// Create a stream
|
|
js.AddStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
Subjects: []string{"foo"},
|
|
MaxBytes: 1024,
|
|
})
|
|
|
|
// Update a stream
|
|
js.UpdateStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
MaxBytes: 2048,
|
|
})
|
|
|
|
// Create a durable consumer
|
|
js.AddConsumer("FOO", &nats.ConsumerConfig{
|
|
Durable: "BAR",
|
|
})
|
|
|
|
// Get information about all streams (with Context JSOpt)
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
for info := range js.StreamsInfo(nats.Context(ctx)) {
|
|
fmt.Println("stream name:", info.Config.Name)
|
|
}
|
|
|
|
// Get information about all consumers (with MaxWait JSOpt)
|
|
for info := range js.ConsumersInfo("FOO", nats.MaxWait(10*time.Second)) {
|
|
fmt.Println("consumer name:", info.Name)
|
|
}
|
|
|
|
// Delete a consumer
|
|
js.DeleteConsumer("FOO", "BAR")
|
|
|
|
// Delete a stream
|
|
js.DeleteStream("FOO")
|
|
}
|
|
|
|
// A JetStreamContext is the composition of a JetStream and JetStreamManagement interfaces.
|
|
// In case of only requiring publishing/consuming messages, can create a context that
|
|
// only uses the JetStream interface.
|
|
func ExampleJetStreamContext() {
|
|
nc, _ := nats.Connect("localhost")
|
|
|
|
var js nats.JetStream
|
|
var jsm nats.JetStreamManager
|
|
var jsctx nats.JetStreamContext
|
|
|
|
// JetStream that can publish/subscribe but cannot manage streams.
|
|
js, _ = nc.JetStream()
|
|
js.Publish("foo", []byte("hello"))
|
|
|
|
// JetStream context that can manage streams/consumers but cannot produce messages.
|
|
jsm, _ = nc.JetStream()
|
|
jsm.AddStream(&nats.StreamConfig{Name: "FOO"})
|
|
|
|
// JetStream context that can both manage streams/consumers
|
|
// as well as publish/subscribe.
|
|
jsctx, _ = nc.JetStream()
|
|
jsctx.AddStream(&nats.StreamConfig{Name: "BAR"})
|
|
jsctx.Publish("bar", []byte("hello world"))
|
|
}
|
|
|
|
func ExamplePubOpt() {
|
|
nc, err := nats.Connect("localhost")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Create JetStream context to produce/consumer messages that will be persisted.
|
|
js, err := nc.JetStream()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Create stream to persist messages published on 'foo'.
|
|
js.AddStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
Subjects: []string{"foo"},
|
|
})
|
|
|
|
// Publish is synchronous by default, and waits for a PubAck response.
|
|
js.Publish("foo", []byte("Hello JS!"))
|
|
|
|
// Publish with a custom timeout.
|
|
js.Publish("foo", []byte("Hello JS!"), nats.AckWait(500*time.Millisecond))
|
|
|
|
// Publish with a context.
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
|
|
js.Publish("foo", []byte("Hello JS!"), nats.Context(ctx))
|
|
|
|
// Publish and assert the expected stream name.
|
|
js.Publish("foo", []byte("Hello JS!"), nats.ExpectStream("FOO"))
|
|
|
|
// Publish and assert the last sequence.
|
|
js.Publish("foo", []byte("Hello JS!"), nats.ExpectLastSequence(5))
|
|
|
|
// Publish and tag the message with an ID.
|
|
js.Publish("foo", []byte("Hello JS!"), nats.MsgId("foo:6"))
|
|
|
|
// Publish and assert the last msg ID.
|
|
js.Publish("foo", []byte("Hello JS!"), nats.ExpectLastMsgId("foo:6"))
|
|
}
|
|
|
|
func ExampleSubOpt() {
|
|
nc, err := nats.Connect("localhost")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Create JetStream context to produce/consumer messages that will be persisted.
|
|
js, err := nc.JetStream()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Auto-ack each individual message.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
})
|
|
|
|
// Auto-ack current sequence and all below.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.AckAll())
|
|
|
|
// Auto-ack each individual message.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.AckExplicit())
|
|
|
|
// Acks are not required.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.AckNone())
|
|
|
|
// Manually acknowledge messages.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
msg.Ack()
|
|
}, nats.ManualAck())
|
|
|
|
// Bind to an existing stream.
|
|
sub, _ := js.SubscribeSync("origin", nats.BindStream("m1"))
|
|
msg, _ := sub.NextMsg(2 * time.Second)
|
|
msg.Ack()
|
|
|
|
// Deliver all messages from the beginning.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.DeliverAll())
|
|
|
|
// Deliver messages starting from the last one.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.DeliverLast())
|
|
|
|
// Deliver only new messages that arrive after subscription.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.DeliverNew())
|
|
|
|
// Create durable consumer FOO, if it doesn't exist.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.Durable("FOO"))
|
|
|
|
// Create consumer on Foo with flow control and heartbeats.
|
|
js.SubscribeSync("foo",
|
|
// Redeliver after 30s
|
|
nats.AckWait(30*time.Second),
|
|
// Redeliver only once
|
|
nats.MaxDeliver(1),
|
|
// Activate Flow control algorithm from the server.
|
|
nats.EnableFlowControl(),
|
|
// Track heartbeats from the server for missed sequences.
|
|
nats.IdleHeartbeat(500*time.Millisecond),
|
|
)
|
|
|
|
// Set the allowable number of outstanding acks.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.MaxAckPending(5))
|
|
|
|
// Set the number of redeliveries for a message.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.MaxDeliver(5))
|
|
|
|
// Set the number the max inflight pull requests.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.PullMaxWaiting(5))
|
|
|
|
// Set the number the max inflight pull requests.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.PullMaxWaiting(5))
|
|
|
|
// Set the rate limit on a push consumer.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.RateLimit(1024))
|
|
|
|
// Replay messages at original speed, instead of as fast as possible.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.ReplayOriginal())
|
|
|
|
// Start delivering messages at a given sequence.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.StartSequence(10))
|
|
|
|
// Start delivering messages at a given time.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.StartTime(time.Now().Add(-2*time.Hour)))
|
|
|
|
// Start delivering messages with delay based on BackOff array of time durations.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.ManualAck(), nats.MaxDeliver(2), nats.BackOff([]time.Duration{50 * time.Millisecond, 250 * time.Millisecond}))
|
|
|
|
// Set consumer replicas count for a durable while subscribing.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.Durable("FOO"), nats.ConsumerReplicas(1))
|
|
|
|
// Force memory storage while subscribing.
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.Durable("FOO"), nats.ConsumerMemoryStorage())
|
|
|
|
// Skip consumer lookup when using explicit consumer name
|
|
js.Subscribe("foo", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.Durable("FOO"), nats.SkipConsumerLookup())
|
|
|
|
// Use multiple subject filters.
|
|
js.Subscribe("", func(msg *nats.Msg) {
|
|
fmt.Printf("Received a message: %s\n", string(msg.Data))
|
|
}, nats.Durable("FOO"), nats.ConsumerFilterSubjects("foo", "bar"), nats.BindStream("test_stream"))
|
|
}
|
|
|
|
func ExampleMaxWait() {
|
|
nc, _ := nats.Connect("localhost")
|
|
|
|
// Set default timeout for JetStream API requests,
|
|
// following requests will inherit this timeout.
|
|
js, _ := nc.JetStream(nats.MaxWait(3 * time.Second))
|
|
|
|
// Set custom timeout for a JetStream API request.
|
|
js.AddStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
Subjects: []string{"foo"},
|
|
}, nats.MaxWait(2*time.Second))
|
|
|
|
sub, _ := js.PullSubscribe("foo", "my-durable-name")
|
|
|
|
// Fetch using the default timeout of 3 seconds.
|
|
msgs, _ := sub.Fetch(1)
|
|
|
|
// Set custom timeout for a pull batch request.
|
|
msgs, _ = sub.Fetch(1, nats.MaxWait(2*time.Second))
|
|
|
|
for _, msg := range msgs {
|
|
msg.Ack()
|
|
}
|
|
}
|
|
|
|
func ExampleAckWait() {
|
|
nc, _ := nats.Connect("localhost")
|
|
js, _ := nc.JetStream()
|
|
|
|
// Set custom timeout for a JetStream API request.
|
|
js.AddStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
Subjects: []string{"foo"},
|
|
})
|
|
|
|
// Wait for an ack response for 2 seconds.
|
|
js.Publish("foo", []byte("Hello JS!"), nats.AckWait(2*time.Second))
|
|
|
|
// Create consumer on 'foo' subject that waits for an ack for 10s,
|
|
// after which the message will be delivered.
|
|
sub, _ := js.SubscribeSync("foo", nats.AckWait(10*time.Second))
|
|
msg, _ := sub.NextMsg(2 * time.Second)
|
|
|
|
// Wait for ack of ack for 2s.
|
|
msg.AckSync(nats.AckWait(2 * time.Second))
|
|
}
|
|
|
|
func ExampleMsg_AckSync() {
|
|
nc, _ := nats.Connect("localhost")
|
|
js, _ := nc.JetStream()
|
|
|
|
// Set custom timeout for a JetStream API request.
|
|
js.AddStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
Subjects: []string{"foo"},
|
|
})
|
|
|
|
sub, _ := js.SubscribeSync("foo")
|
|
msg, _ := sub.NextMsg(2 * time.Second)
|
|
|
|
// Wait for ack of an ack.
|
|
msg.AckSync()
|
|
}
|
|
|
|
// When a message has been delivered by JetStream, it will be possible
|
|
// to access some of its metadata such as sequence numbers.
|
|
func ExampleMsg_Metadata() {
|
|
nc, _ := nats.Connect("localhost")
|
|
js, _ := nc.JetStream()
|
|
|
|
// Set custom timeout for a JetStream API request.
|
|
js.AddStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
Subjects: []string{"foo"},
|
|
})
|
|
|
|
js.Publish("foo", []byte("hello"))
|
|
|
|
sub, _ := js.SubscribeSync("foo")
|
|
msg, _ := sub.NextMsg(2 * time.Second)
|
|
|
|
//
|
|
meta, _ := msg.Metadata()
|
|
|
|
// Stream and Consumer sequences.
|
|
fmt.Printf("Stream seq: %s:%d, Consumer seq: %s:%d\n", meta.Stream, meta.Sequence.Stream, meta.Consumer, meta.Sequence.Consumer)
|
|
fmt.Printf("Pending: %d\n", meta.NumPending)
|
|
fmt.Printf("Pending: %d\n", meta.NumDelivered)
|
|
}
|
|
|
|
// AckOpt are the options that can be passed when acknowledge a message.
|
|
func ExampleAckOpt() {
|
|
nc, err := nats.Connect("localhost")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Create JetStream context to produce/consumer messages that will be persisted.
|
|
js, err := nc.JetStream()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Create stream to persist messages published on 'foo'.
|
|
js.AddStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
Subjects: []string{"foo"},
|
|
})
|
|
|
|
// Publish is synchronous by default, and waits for a PubAck response.
|
|
js.Publish("foo", []byte("Hello JS!"))
|
|
|
|
sub, _ := js.SubscribeSync("foo")
|
|
msg, _ := sub.NextMsg(2 * time.Second)
|
|
|
|
// Ack and wait for 2 seconds
|
|
msg.InProgress(nats.AckWait(2))
|
|
|
|
// Using a context.
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
msg.Ack(nats.Context(ctx))
|
|
}
|
|
|
|
func ExamplePullOpt() {
|
|
nc, err := nats.Connect("localhost")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Create JetStream context to produce/consumer messages that will be persisted.
|
|
js, err := nc.JetStream()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Create stream to persist messages published on 'foo'.
|
|
js.AddStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
Subjects: []string{"foo"},
|
|
})
|
|
|
|
// Publish is synchronous by default, and waits for a PubAck response.
|
|
js.Publish("foo", []byte("Hello JS!"))
|
|
|
|
sub, _ := js.PullSubscribe("foo", "wq")
|
|
|
|
// Pull one message,
|
|
msgs, _ := sub.Fetch(1, nats.MaxWait(2*time.Second))
|
|
for _, msg := range msgs {
|
|
msg.Ack()
|
|
}
|
|
|
|
// Using a context to timeout waiting for a message.
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
|
|
msgs, _ = sub.Fetch(1, nats.Context(ctx))
|
|
for _, msg := range msgs {
|
|
msg.Ack()
|
|
}
|
|
}
|
|
|
|
func ExampleContext() {
|
|
nc, err := nats.Connect("localhost")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
js, _ := nc.JetStream()
|
|
|
|
// Base context
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
// nats.Context option implements context.Context interface, so can be used
|
|
// to create a new context from top level one.
|
|
nctx := nats.Context(ctx)
|
|
|
|
// JetStreamManager functions all can use context.
|
|
js.AddStream(&nats.StreamConfig{
|
|
Name: "FOO",
|
|
Subjects: []string{"foo"},
|
|
}, nctx)
|
|
|
|
// Custom context with timeout
|
|
tctx, tcancel := context.WithTimeout(nctx, 2*time.Second)
|
|
defer tcancel()
|
|
|
|
// Set a timeout for publishing using context.
|
|
deadlineCtx := nats.Context(tctx)
|
|
|
|
js.Publish("foo", []byte("Hello JS!"), deadlineCtx)
|
|
sub, _ := js.SubscribeSync("foo")
|
|
msg, _ := sub.NextMsgWithContext(deadlineCtx)
|
|
|
|
// Acks can also use a context to await for a response.
|
|
msg.Ack(deadlineCtx)
|
|
}
|