主要变更: 1. 重构NATS、RabbitMQ和Redis连接管理模块,支持多数据源配置 2. 统一连接管理接口,增加数据源名称参数 3. 优化连接状态检查和错误处理 4. 增加连接池管理和资源清理机制 5. 改进日志输出格式和内容
213 lines
7.8 KiB
Go
213 lines
7.8 KiB
Go
// Copyright 2019-2026 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 message
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// StreamConfig will determine the name, subjects and retention policy
|
|
// for a given stream. If subjects is empty the name will be used.
|
|
type StreamConfig struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description,omitempty"`
|
|
Subjects []string `json:"subjects,omitempty"`
|
|
Retention RetentionPolicy `json:"retention"`
|
|
MaxConsumers int `json:"max_consumers"`
|
|
MaxMsgs int64 `json:"max_msgs"`
|
|
MaxBytes int64 `json:"max_bytes"`
|
|
MaxAge time.Duration `json:"max_age"`
|
|
MaxMsgsPer int64 `json:"max_msgs_per_subject"`
|
|
MaxMsgSize int32 `json:"max_msg_size,omitempty"`
|
|
Discard DiscardPolicy `json:"discard"`
|
|
Storage StorageType `json:"storage"`
|
|
Replicas int `json:"num_replicas"`
|
|
NoAck bool `json:"no_ack,omitempty"`
|
|
Duplicates time.Duration `json:"duplicate_window,omitempty"`
|
|
Placement *Placement `json:"placement,omitempty"`
|
|
Mirror *StreamSource `json:"mirror,omitempty"`
|
|
Sources []*StreamSource `json:"sources,omitempty"`
|
|
Compression StoreCompression `json:"compression"`
|
|
FirstSeq uint64 `json:"first_seq,omitempty"`
|
|
|
|
// Allow applying a subject transform to incoming messages before doing anything else
|
|
SubjectTransform *SubjectTransformConfig `json:"subject_transform,omitempty"`
|
|
|
|
// Allow republish of the message after being sequenced and stored.
|
|
RePublish *RePublish `json:"republish,omitempty"`
|
|
|
|
// Allow higher performance, direct access to get individual messages. E.g. KeyValue
|
|
AllowDirect bool `json:"allow_direct"`
|
|
// Allow higher performance and unified direct access for mirrors as well.
|
|
MirrorDirect bool `json:"mirror_direct"`
|
|
|
|
// Allow KV like semantics to also discard new on a per subject basis
|
|
DiscardNewPer bool `json:"discard_new_per_subject,omitempty"`
|
|
|
|
// Optional qualifiers. These can not be modified after set to true.
|
|
|
|
// Sealed will seal a stream so no messages can get out or in.
|
|
Sealed bool `json:"sealed"`
|
|
// DenyDelete will restrict the ability to delete messages.
|
|
DenyDelete bool `json:"deny_delete"`
|
|
// DenyPurge will restrict the ability to purge messages.
|
|
DenyPurge bool `json:"deny_purge"`
|
|
// AllowRollup allows messages to be placed into the system and purge
|
|
// all older messages using a special msg header.
|
|
AllowRollup bool `json:"allow_rollup_hdrs"`
|
|
|
|
// The following defaults will apply to consumers when created against
|
|
// this stream, unless overridden manually.
|
|
// TODO(nat): Can/should we name these better?
|
|
ConsumerLimits StreamConsumerLimits `json:"consumer_limits"`
|
|
|
|
// AllowMsgTTL allows header initiated per-message TTLs. If disabled,
|
|
// then the `NATS-TTL` header will be ignored.
|
|
AllowMsgTTL bool `json:"allow_msg_ttl"`
|
|
|
|
// SubjectDeleteMarkerTTL sets the TTL of delete marker messages left behind by
|
|
// subject delete markers.
|
|
SubjectDeleteMarkerTTL time.Duration `json:"subject_delete_marker_ttl,omitempty"`
|
|
|
|
// AllowMsgCounter allows a stream to use (only) counter CRDTs.
|
|
AllowMsgCounter bool `json:"allow_msg_counter,omitempty"`
|
|
|
|
// AllowAtomicPublish allows atomic batch publishing into the stream.
|
|
AllowAtomicPublish bool `json:"allow_atomic,omitempty"`
|
|
|
|
// AllowMsgSchedules allows the scheduling of messages.
|
|
AllowMsgSchedules bool `json:"allow_msg_schedules,omitempty"`
|
|
|
|
// PersistMode allows to opt-in to different persistence mode settings.
|
|
PersistMode PersistModeType `json:"persist_mode,omitempty"`
|
|
|
|
// Metadata is additional metadata for the Stream.
|
|
Metadata map[string]string `json:"metadata,omitempty"`
|
|
}
|
|
|
|
// Used to guide placement of streams and meta controllers in clustered JetStream.
|
|
type Placement struct {
|
|
Cluster string `json:"cluster,omitempty"`
|
|
Tags []string `json:"tags,omitempty"`
|
|
Preferred string `json:"preferred,omitempty"`
|
|
}
|
|
|
|
// StreamSource dictates how streams can source from other streams.
|
|
type StreamSource struct {
|
|
Name string `json:"name"`
|
|
OptStartSeq uint64 `json:"opt_start_seq,omitempty"`
|
|
OptStartTime *time.Time `json:"opt_start_time,omitempty"`
|
|
FilterSubject string `json:"filter_subject,omitempty"`
|
|
SubjectTransforms []SubjectTransformConfig `json:"subject_transforms,omitempty"`
|
|
External *ExternalStream `json:"external,omitempty"`
|
|
|
|
// Internal
|
|
iname string // For indexing when stream names are the same for multiple sources.
|
|
}
|
|
|
|
// SubjectTransformConfig is for applying a subject transform (to matching messages) before doing anything else when a new message is received
|
|
type SubjectTransformConfig struct {
|
|
Source string `json:"src"`
|
|
Destination string `json:"dest"`
|
|
}
|
|
|
|
// ExternalStream allows you to qualify access to a stream source in another account or domain.
|
|
type ExternalStream struct {
|
|
ApiPrefix string `json:"api"`
|
|
DeliverPrefix string `json:"deliver"`
|
|
}
|
|
|
|
// RePublish is for republishing messages once committed to a stream.
|
|
type RePublish struct {
|
|
Source string `json:"src,omitempty"`
|
|
Destination string `json:"dest"`
|
|
HeadersOnly bool `json:"headers_only,omitempty"`
|
|
}
|
|
|
|
type StreamConsumerLimits struct {
|
|
InactiveThreshold time.Duration `json:"inactive_threshold,omitempty"`
|
|
MaxAckPending int `json:"max_ack_pending,omitempty"`
|
|
}
|
|
|
|
// PersistModeType determines what persistence mode the stream uses.
|
|
type PersistModeType int
|
|
|
|
const (
|
|
// DefaultPersistMode specifies the default persist mode. Writes to the stream will immediately be flushed.
|
|
// The publish acknowledgement will be sent after the persisting completes.
|
|
DefaultPersistMode = PersistModeType(iota)
|
|
// AsyncPersistMode specifies writes to the stream will be flushed asynchronously.
|
|
// The publish acknowledgement may be sent before the persisting completes.
|
|
// This means writes could be lost if they weren't flushed prior to a hard kill of the server.
|
|
AsyncPersistMode
|
|
)
|
|
|
|
// MarshalJSON 将 PersistModeType 序列化为字符串
|
|
func (pm PersistModeType) MarshalJSON() ([]byte, error) {
|
|
switch pm {
|
|
case DefaultPersistMode:
|
|
return []byte(`"default"`), nil
|
|
case AsyncPersistMode:
|
|
return []byte(`"async"`), nil
|
|
default:
|
|
return nil, fmt.Errorf("can not marshal %v", pm)
|
|
}
|
|
}
|
|
|
|
// UnmarshalJSON 将字符串反序列化为 PersistModeType
|
|
func (pm *PersistModeType) UnmarshalJSON(data []byte) error {
|
|
switch string(data) {
|
|
case `"default"`:
|
|
*pm = DefaultPersistMode
|
|
case `"async"`:
|
|
*pm = AsyncPersistMode
|
|
default:
|
|
return fmt.Errorf("unknown persist mode: %s", string(data))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type StoreCompression uint8
|
|
|
|
const (
|
|
NoCompression StoreCompression = iota
|
|
S2Compression
|
|
)
|
|
|
|
// MarshalJSON 将 StoreCompression 序列化为字符串
|
|
func (sc StoreCompression) MarshalJSON() ([]byte, error) {
|
|
switch sc {
|
|
case NoCompression:
|
|
return []byte(`"none"`), nil
|
|
case S2Compression:
|
|
return []byte(`"s2"`), nil
|
|
default:
|
|
return nil, fmt.Errorf("can not marshal %v", sc)
|
|
}
|
|
}
|
|
|
|
// UnmarshalJSON 将字符串反序列化为 StoreCompression
|
|
func (sc *StoreCompression) UnmarshalJSON(data []byte) error {
|
|
switch string(data) {
|
|
case `"none"`:
|
|
*sc = NoCompression
|
|
case `"s2"`:
|
|
*sc = S2Compression
|
|
default:
|
|
return fmt.Errorf("unknown store compression: %s", string(data))
|
|
}
|
|
return nil
|
|
}
|