mirror of
https://github.com/taigrr/nats.docs
synced 2025-01-18 04:03:23 -08:00
96 lines
2.7 KiB
Markdown
96 lines
2.7 KiB
Markdown
# Request-Reply Semantics
|
|
|
|
The pattern of sending a message and receiving a response is encapsulated in most client libraries into a request method. Under the covers this method will publish a message with a unique reply-to subject and wait for the response before returning.
|
|
|
|
In the older versions of some libraries a completely new reply-to subject is created each time. In newer versions, a subject hierarchy is used so that a single subscriber in the client library listens for a wildcard, and requests are sent with a unique child subject of a single subject.
|
|
|
|
The primary difference between the request method and publishing with a reply-to is that the library is only going to accept one response, and in most libraries the request will be treated as a synchronous action. The library may even provide a way to set the timeout.
|
|
|
|
For example, updating the previous publish example we may request `time` with a one second timeout:
|
|
|
|
!INCLUDE "../../\_examples/request\_reply.html"
|
|
|
|
You can think of request-reply in the library as a subscribe, get one message, unsubscribe pattern. In Go this might look something like:
|
|
|
|
```go
|
|
sub, err := nc.SubscribeSync(replyTo)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
nc.Flush()
|
|
|
|
// Send the request
|
|
nc.PublishRequest(subject, replyTo, []byte(input))
|
|
|
|
// Wait for a single response
|
|
for {
|
|
msg, err := sub.NextMsg(1 * time.Second)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
response = string(msg.Data)
|
|
break
|
|
}
|
|
sub.Unsubscribe()
|
|
```
|
|
|
|
## Scatter-Gather
|
|
|
|
You can expand the request-reply pattern into something often called scatter-gather. To receive multiple messages, with a timeout, you could do something like the following, where the loop getting messages is using time as the limitation, not the receipt of a single message:
|
|
|
|
```go
|
|
sub, err := nc.SubscribeSync(replyTo)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
nc.Flush()
|
|
|
|
// Send the request
|
|
nc.PublishRequest(subject, replyTo, []byte(input))
|
|
|
|
// Wait for a single response
|
|
max := 100 * time.Millisecond
|
|
start := time.Now()
|
|
for time.Now().Sub(start) < max {
|
|
msg, err := sub.NextMsg(1 * time.Second)
|
|
if err != nil {
|
|
break
|
|
}
|
|
|
|
responses = append(responses, string(msg.Data))
|
|
}
|
|
sub.Unsubscribe()
|
|
```
|
|
|
|
Or, you can loop on a counter and a timeout to try to get _at least N_ responses:
|
|
|
|
```go
|
|
sub, err := nc.SubscribeSync(replyTo)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
nc.Flush()
|
|
|
|
// Send the request
|
|
nc.PublishRequest(subject, replyTo, []byte(input))
|
|
|
|
// Wait for a single response
|
|
max := 500 * time.Millisecond
|
|
start := time.Now()
|
|
for time.Now().Sub(start) < max {
|
|
msg, err := sub.NextMsg(1 * time.Second)
|
|
if err != nil {
|
|
break
|
|
}
|
|
|
|
responses = append(responses, string(msg.Data))
|
|
|
|
if len(responses) >= minResponses {
|
|
break
|
|
}
|
|
}
|
|
sub.Unsubscribe()
|
|
```
|
|
|