mirror of
https://github.com/nats-io/nats.go.git
synced 2025-10-28 02:42:14 +08:00
310 lines
9.4 KiB
Go
310 lines
9.4 KiB
Go
// Copyright 2020-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 jetstream
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
type pullOptFunc func(*consumeOpts) error
|
|
|
|
func (fn pullOptFunc) configureConsume(opts *consumeOpts) error {
|
|
return fn(opts)
|
|
}
|
|
|
|
func (fn pullOptFunc) configureMessages(opts *consumeOpts) error {
|
|
return fn(opts)
|
|
}
|
|
|
|
// WithClientTrace enables request/response API calls tracing
|
|
// ClientTrace is used to provide handlers for each event
|
|
func WithClientTrace(ct *ClientTrace) JetStreamOpt {
|
|
return func(opts *jsOpts) error {
|
|
opts.clientTrace = ct
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithPublishAsyncErrHandler sets error handler for async message publish
|
|
func WithPublishAsyncErrHandler(cb MsgErrHandler) JetStreamOpt {
|
|
return func(opts *jsOpts) error {
|
|
opts.publisherOpts.aecb = cb
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithPublishAsyncMaxPending sets the maximum outstanding async publishes that can be inflight at one time.
|
|
func WithPublishAsyncMaxPending(max int) JetStreamOpt {
|
|
return func(opts *jsOpts) error {
|
|
if max < 1 {
|
|
return fmt.Errorf("%w: max ack pending should be >= 1", ErrInvalidOption)
|
|
}
|
|
opts.publisherOpts.maxpa = max
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithPurgeSubject sets a sprecific subject for which messages on a stream will be purged
|
|
func WithPurgeSubject(subject string) StreamPurgeOpt {
|
|
return func(req *StreamPurgeRequest) error {
|
|
req.Subject = subject
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithPurgeSequence is used to set a sprecific sequence number up to which (but not including) messages will be purged from a stream
|
|
// Can be combined with [WithPurgeSubject] option, but not with [WithPurgeKeep]
|
|
func WithPurgeSequence(sequence uint64) StreamPurgeOpt {
|
|
return func(req *StreamPurgeRequest) error {
|
|
if req.Keep != 0 {
|
|
return fmt.Errorf("%w: both 'keep' and 'sequence' cannot be provided in purge request", ErrInvalidOption)
|
|
}
|
|
req.Sequence = sequence
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithPurgeKeep sets the number of messages to be kept in the stream after purge.
|
|
// Can be combined with [WithPurgeSubject] option, but not with [WithPurgeSequence]
|
|
func WithPurgeKeep(keep uint64) StreamPurgeOpt {
|
|
return func(req *StreamPurgeRequest) error {
|
|
if req.Sequence != 0 {
|
|
return fmt.Errorf("%w: both 'keep' and 'sequence' cannot be provided in purge request", ErrInvalidOption)
|
|
}
|
|
req.Keep = keep
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// PullMaxMessages limits the number of messages to be fetched from the stream in one request
|
|
// If not provided, a default of 100 messages will be used
|
|
type PullMaxMessages int
|
|
|
|
func (max PullMaxMessages) configureConsume(opts *consumeOpts) error {
|
|
if max <= 0 {
|
|
return fmt.Errorf("%w: maxMessages size must be at least 1", ErrInvalidOption)
|
|
}
|
|
opts.MaxMessages = int(max)
|
|
return nil
|
|
}
|
|
|
|
func (max PullMaxMessages) configureMessages(opts *consumeOpts) error {
|
|
if max <= 0 {
|
|
return fmt.Errorf("%w: maxMessages size must be at least 1", ErrInvalidOption)
|
|
}
|
|
opts.MaxMessages = int(max)
|
|
return nil
|
|
}
|
|
|
|
// PullExpiry sets timeout on a single batch request, waiting until at least one message is available
|
|
type PullExpiry time.Duration
|
|
|
|
func (exp PullExpiry) configureConsume(opts *consumeOpts) error {
|
|
if exp < 0 {
|
|
return fmt.Errorf("%w: expires value must be positive", ErrInvalidOption)
|
|
}
|
|
opts.Expires = time.Duration(exp)
|
|
return nil
|
|
}
|
|
|
|
func (exp PullExpiry) configureMessages(opts *consumeOpts) error {
|
|
if exp < 0 {
|
|
return fmt.Errorf("%w: expires value must be positive", ErrInvalidOption)
|
|
}
|
|
opts.Expires = time.Duration(exp)
|
|
return nil
|
|
}
|
|
|
|
// PullMaxBytes sets max_bytes limit on a fetch request
|
|
type PullMaxBytes int
|
|
|
|
func (max PullMaxBytes) configureConsume(opts *consumeOpts) error {
|
|
if max <= 0 {
|
|
return fmt.Errorf("%w: max bytes must be greater then 0", ErrInvalidOption)
|
|
}
|
|
opts.MaxBytes = int(max)
|
|
return nil
|
|
}
|
|
|
|
func (max PullMaxBytes) configureMessages(opts *consumeOpts) error {
|
|
if max <= 0 {
|
|
return fmt.Errorf("%w: max bytes must be greater then 0", ErrInvalidOption)
|
|
}
|
|
opts.MaxBytes = int(max)
|
|
return nil
|
|
}
|
|
|
|
// PullThresholdMessages sets the message count on which Consume will trigger
|
|
// new pull request to the server. Defaults to 50% of MaxMessages.
|
|
type PullThresholdMessages int
|
|
|
|
func (t PullThresholdMessages) configureConsume(opts *consumeOpts) error {
|
|
opts.ThresholdMessages = int(t)
|
|
return nil
|
|
}
|
|
|
|
// PullThresholdBytes sets the byte count on which Consume will trigger
|
|
// new pull request to the server. Defaults to 50% of MaxBytes (if set).
|
|
type PullThresholBytes int
|
|
|
|
func (t PullThresholBytes) configureConsume(opts *consumeOpts) error {
|
|
opts.ThresholdBytes = int(t)
|
|
return nil
|
|
}
|
|
|
|
// PullHeartbeat sets the idle heartbeat duration for a pull subscription
|
|
// If a client does not receive a heartbeat message from a stream for more
|
|
// than the idle heartbeat setting, the subscription will be removed
|
|
// and error will be passed to the message handler
|
|
type PullHeartbeat time.Duration
|
|
|
|
func (hb PullHeartbeat) configureConsume(opts *consumeOpts) error {
|
|
hbTime := time.Duration(hb)
|
|
if hbTime < 1*time.Second || hbTime > 30*time.Second {
|
|
return fmt.Errorf("%w: idle_heartbeat value must be within 1s-30s range", ErrInvalidOption)
|
|
}
|
|
opts.Heartbeat = hbTime
|
|
return nil
|
|
}
|
|
|
|
func (hb PullHeartbeat) configureMessages(opts *consumeOpts) error {
|
|
hbTime := time.Duration(hb)
|
|
if hbTime < 1*time.Second || hbTime > 30*time.Second {
|
|
return fmt.Errorf("%w: idle_heartbeat value must be within 1s-30s range", ErrInvalidOption)
|
|
}
|
|
opts.Heartbeat = hbTime
|
|
return nil
|
|
}
|
|
|
|
// ConsumeErrHandler sets custom error handler invoked when an error was encountered while consuming messages
|
|
// It will be invoked for both terminal (Consumer Deleted, invalid request body) and non-terminal (e.g. missing heartbeats) errors
|
|
func ConsumeErrHandler(cb ConsumeErrHandlerFunc) PullConsumeOpt {
|
|
return pullOptFunc(func(cfg *consumeOpts) error {
|
|
cfg.ErrHandler = cb
|
|
return nil
|
|
})
|
|
}
|
|
|
|
// ConsumeErrHandler sets custom error handler invoked when an error was encountered while consuming messages
|
|
// It will be invoked for both terminal (Consumer Deleted, invalid request body) and non-terminal (e.g. missing heartbeats) errors
|
|
func WithMessagesErrOnMissingHeartbeat(hbErr bool) PullMessagesOpt {
|
|
return pullOptFunc(func(cfg *consumeOpts) error {
|
|
cfg.ReportMissingHeartbeats = hbErr
|
|
return nil
|
|
})
|
|
}
|
|
|
|
// FetchMaxWait sets custom timeout fir fetching predefined batch of messages
|
|
func FetchMaxWait(timeout time.Duration) FetchOpt {
|
|
return func(req *pullRequest) error {
|
|
if timeout <= 0 {
|
|
return fmt.Errorf("%w: timeout value must be greater than 0", ErrInvalidOption)
|
|
}
|
|
req.Expires = timeout
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithDeletedDetails can be used to display the information about messages deleted from a stream on a stream info request
|
|
func WithDeletedDetails(deletedDetails bool) StreamInfoOpt {
|
|
return func(req *streamInfoRequest) error {
|
|
req.DeletedDetails = deletedDetails
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithSubjectFilter can be used to display the information about messages stored on given subjects
|
|
func WithSubjectFilter(subject string) StreamInfoOpt {
|
|
return func(req *streamInfoRequest) error {
|
|
req.SubjectFilter = subject
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithNakDelay can be used to specify the duration after which the message should be redelivered
|
|
func WithNakDelay(delay time.Duration) NakOpt {
|
|
return func(opts *ackOpts) error {
|
|
opts.nakDelay = delay
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithMsgID sets the message ID used for deduplication.
|
|
func WithMsgID(id string) PublishOpt {
|
|
return func(opts *pubOpts) error {
|
|
opts.id = id
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithExpectStream sets the expected stream to respond from the publish.
|
|
func WithExpectStream(stream string) PublishOpt {
|
|
return func(opts *pubOpts) error {
|
|
opts.stream = stream
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithExpectLastSequence sets the expected sequence in the response from the publish.
|
|
func WithExpectLastSequence(seq uint64) PublishOpt {
|
|
return func(opts *pubOpts) error {
|
|
opts.lastSeq = &seq
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithExpectLastSequencePerSubject sets the expected sequence per subject in the response from the publish.
|
|
func WithExpectLastSequencePerSubject(seq uint64) PublishOpt {
|
|
return func(opts *pubOpts) error {
|
|
opts.lastSubjectSeq = &seq
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// ExpectLastMsgId sets the expected last msgId in the response from the publish.
|
|
func WithExpectLastMsgID(id string) PublishOpt {
|
|
return func(opts *pubOpts) error {
|
|
opts.lastMsgID = id
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithRetryWait sets the retry wait time when ErrNoResponders is encountered.
|
|
func WithRetryWait(dur time.Duration) PublishOpt {
|
|
return func(opts *pubOpts) error {
|
|
opts.retryWait = dur
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithRetryAttempts sets the retry number of attempts when ErrNoResponders is encountered.
|
|
func WithRetryAttempts(num int) PublishOpt {
|
|
return func(opts *pubOpts) error {
|
|
opts.retryAttempts = num
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithStallWait sets the max wait when the producer becomes stall producing messages.
|
|
func WithStallWait(ttl time.Duration) PublishOpt {
|
|
return func(opts *pubOpts) error {
|
|
if ttl <= 0 {
|
|
return fmt.Errorf("%w: stall wait should be more than 0", ErrInvalidOption)
|
|
}
|
|
opts.stallWait = ttl
|
|
return nil
|
|
}
|
|
}
|