mirror of
https://github.com/nats-io/nats.go.git
synced 2025-10-26 18:10:25 +08:00
Merge branch 'main' of https://github.com/nats-io/nats.go into jsv2
Improve readme Signed-off-by: Piotr Piotrowski <piotr@synadia.com> Fix msg size calculation Signed-off-by: Piotr Piotrowski <piotr@synadia.com> Add connection event listeners Signed-off-by: Piotr Piotrowski <piotr@synadia.com> Fix leaky goroutines in tests Signed-off-by: Piotr Piotrowski <piotr@synadia.com>
This commit is contained in:
1
go.mod
1
go.mod
@@ -8,6 +8,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/klauspost/compress v1.16.5 // indirect
|
||||||
golang.org/x/crypto v0.6.0 // indirect
|
golang.org/x/crypto v0.6.0 // indirect
|
||||||
golang.org/x/sys v0.5.0 // indirect
|
golang.org/x/sys v0.5.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -1,3 +1,5 @@
|
|||||||
|
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
|
||||||
|
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA=
|
github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA=
|
||||||
github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64=
|
github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64=
|
||||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||||
|
|||||||
12
go_test.mod
12
go_test.mod
@@ -4,7 +4,8 @@ go 1.19
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang/protobuf v1.4.2
|
github.com/golang/protobuf v1.4.2
|
||||||
github.com/nats-io/nats-server/v2 v2.9.6
|
github.com/klauspost/compress v1.16.5
|
||||||
|
github.com/nats-io/nats-server/v2 v2.9.16
|
||||||
github.com/nats-io/nkeys v0.4.4
|
github.com/nats-io/nkeys v0.4.4
|
||||||
github.com/nats-io/nuid v1.0.1
|
github.com/nats-io/nuid v1.0.1
|
||||||
golang.org/x/text v0.3.6
|
golang.org/x/text v0.3.6
|
||||||
@@ -12,10 +13,9 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/klauspost/compress v1.15.11 // indirect
|
|
||||||
github.com/minio/highwayhash v1.0.2 // indirect
|
github.com/minio/highwayhash v1.0.2 // indirect
|
||||||
github.com/nats-io/jwt/v2 v2.3.0 // indirect
|
github.com/nats-io/jwt/v2 v2.4.1 // indirect
|
||||||
golang.org/x/crypto v0.6.0 // indirect
|
golang.org/x/crypto v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.5.0 // indirect
|
golang.org/x/sys v0.7.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
33
go_test.sum
33
go_test.sum
@@ -9,34 +9,25 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
|
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
|
||||||
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
|
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
|
||||||
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
||||||
github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI=
|
github.com/nats-io/jwt/v2 v2.4.1 h1:Y35W1dgbbz2SQUYDPCaclXcuqleVmpbRa7646Jf2EX4=
|
||||||
github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
|
github.com/nats-io/jwt/v2 v2.4.1/go.mod h1:24BeQtRwxRV8ruvC4CojXlx/WQ/VjuwlYiH+vu/+ibI=
|
||||||
github.com/nats-io/nats-server/v2 v2.9.6 h1:RTtK+rv/4CcliOuqGsy58g7MuWkBaWmF5TUNwuUo9Uw=
|
github.com/nats-io/nats-server/v2 v2.9.16 h1:SuNe6AyCcVy0g5326wtyU8TdqYmcPqzTjhkHojAjprc=
|
||||||
github.com/nats-io/nats-server/v2 v2.9.6/go.mod h1:AB6hAnGZDlYfqb7CTAm66ZKMZy9DpfierY1/PbpvI2g=
|
github.com/nats-io/nats-server/v2 v2.9.16/go.mod h1:z1cc5Q+kqJkz9mLUdlcSsdYnId4pyImHjNgoh6zxSC0=
|
||||||
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
|
|
||||||
github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA=
|
github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA=
|
||||||
github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64=
|
github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64=
|
||||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||||
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
|
|
||||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
|||||||
60
js.go
60
js.go
@@ -1660,8 +1660,14 @@ func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we are creating or updating let's process that request.
|
// If we are creating or updating let's process that request.
|
||||||
|
consName := o.cfg.Name
|
||||||
if shouldCreate {
|
if shouldCreate {
|
||||||
info, err := js.upsertConsumer(stream, cfg.Durable, ccreq.Config)
|
if cfg.Durable != "" {
|
||||||
|
consName = cfg.Durable
|
||||||
|
} else if consName == "" {
|
||||||
|
consName = getHash(nuid.Next())
|
||||||
|
}
|
||||||
|
info, err := js.upsertConsumer(stream, consName, ccreq.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var apiErr *APIError
|
var apiErr *APIError
|
||||||
if ok := errors.As(err, &apiErr); !ok {
|
if ok := errors.As(err, &apiErr); !ok {
|
||||||
@@ -1964,40 +1970,22 @@ func (sub *Subscription) resetOrderedConsumer(sseq uint64) {
|
|||||||
cfg.DeliverPolicy = DeliverByStartSequencePolicy
|
cfg.DeliverPolicy = DeliverByStartSequencePolicy
|
||||||
cfg.OptStartSeq = sseq
|
cfg.OptStartSeq = sseq
|
||||||
|
|
||||||
ccSubj := fmt.Sprintf(apiLegacyConsumerCreateT, jsi.stream)
|
|
||||||
j, err := json.Marshal(jsi.ccreq)
|
|
||||||
js := jsi.js
|
js := jsi.js
|
||||||
sub.mu.Unlock()
|
sub.mu.Unlock()
|
||||||
|
|
||||||
|
consName := nuid.Next()
|
||||||
|
cinfo, err := js.upsertConsumer(jsi.stream, consName, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pushErr(err)
|
var apiErr *APIError
|
||||||
return
|
if errors.Is(err, ErrJetStreamNotEnabled) || errors.Is(err, ErrTimeout) {
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := nc.Request(js.apiSubj(ccSubj), j, js.opts.wait)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, ErrNoResponders) || errors.Is(err, ErrTimeout) {
|
|
||||||
// if creating consumer failed, retry
|
// if creating consumer failed, retry
|
||||||
return
|
return
|
||||||
}
|
} else if errors.As(err, &apiErr) && apiErr.ErrorCode == JSErrCodeInsufficientResourcesErr {
|
||||||
pushErr(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var cinfo consumerResponse
|
|
||||||
err = json.Unmarshal(resp.Data, &cinfo)
|
|
||||||
if err != nil {
|
|
||||||
pushErr(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if cinfo.Error != nil {
|
|
||||||
if cinfo.Error.ErrorCode == JSErrCodeInsufficientResourcesErr {
|
|
||||||
// retry for insufficient resources, as it may mean that client is connected to a running
|
// retry for insufficient resources, as it may mean that client is connected to a running
|
||||||
// server in cluster while the server hosting R1 JetStream resources is restarting
|
// server in cluster while the server hosting R1 JetStream resources is restarting
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pushErr(cinfo.Error)
|
pushErr(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2489,6 +2477,14 @@ func ConsumerMemoryStorage() SubOpt {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConsumerName sets the name for a consumer.
|
||||||
|
func ConsumerName(name string) SubOpt {
|
||||||
|
return subOptFn(func(opts *subOpts) error {
|
||||||
|
opts.cfg.Name = name
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (sub *Subscription) ConsumerInfo() (*ConsumerInfo, error) {
|
func (sub *Subscription) ConsumerInfo() (*ConsumerInfo, error) {
|
||||||
sub.mu.Lock()
|
sub.mu.Lock()
|
||||||
// TODO(dlc) - Better way to mark especially if we attach.
|
// TODO(dlc) - Better way to mark especially if we attach.
|
||||||
@@ -3586,3 +3582,17 @@ func (st *StorageType) UnmarshalJSON(data []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Length of our hash used for named consumers.
|
||||||
|
const nameHashLen = 8
|
||||||
|
|
||||||
|
// Computes a hash for the given `name`.
|
||||||
|
func getHash(name string) string {
|
||||||
|
sha := sha256.New()
|
||||||
|
sha.Write([]byte(name))
|
||||||
|
b := sha.Sum(nil)
|
||||||
|
for i := 0; i < nameHashLen; i++ {
|
||||||
|
b[i] = rdigits[int(b[i]%base)]
|
||||||
|
}
|
||||||
|
return string(b[:nameHashLen])
|
||||||
|
}
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ func TestJetStreamOrderedConsumerDeleteAssets(t *testing.T) {
|
|||||||
t.Run("remove consumer, expect it to be recreated", func(t *testing.T) {
|
t.Run("remove consumer, expect it to be recreated", func(t *testing.T) {
|
||||||
createStream()
|
createStream()
|
||||||
|
|
||||||
createConsSub, err := nc.SubscribeSync("$JS.API.CONSUMER.CREATE.OBJECT")
|
createConsSub, err := nc.SubscribeSync("$JS.API.CONSUMER.CREATE.OBJECT.*.a")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
12
object.go
12
object.go
@@ -369,13 +369,19 @@ func (obs *obs) Put(meta *ObjectMeta, r io.Reader, opts ...ObjectOpt) (*ObjectIn
|
|||||||
return perr
|
return perr
|
||||||
}
|
}
|
||||||
|
|
||||||
purgePartial := func() { obs.js.purgeStream(obs.stream, &StreamPurgeRequest{Subject: chunkSubj}) }
|
|
||||||
|
|
||||||
// Create our own JS context to handle errors etc.
|
// Create our own JS context to handle errors etc.
|
||||||
js, err := obs.js.nc.JetStream(PublishAsyncErrHandler(func(js JetStream, _ *Msg, err error) { setErr(err) }))
|
js, err := obs.js.nc.JetStream(PublishAsyncErrHandler(func(js JetStream, _ *Msg, err error) { setErr(err) }))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
purgePartial := func() {
|
||||||
|
// wait until all pubs are complete or up to default timeout before attempting purge
|
||||||
|
select {
|
||||||
|
case <-js.PublishAsyncComplete():
|
||||||
|
case <-time.After(obs.js.opts.wait):
|
||||||
|
}
|
||||||
|
obs.js.purgeStream(obs.stream, &StreamPurgeRequest{Subject: chunkSubj})
|
||||||
|
}
|
||||||
|
|
||||||
m, h := NewMsg(chunkSubj), sha256.New()
|
m, h := NewMsg(chunkSubj), sha256.New()
|
||||||
chunk, sent, total := make([]byte, meta.Opts.ChunkSize), 0, uint64(0)
|
chunk, sent, total := make([]byte, meta.Opts.ChunkSize), 0, uint64(0)
|
||||||
@@ -1208,7 +1214,7 @@ func (o *objResult) Read(p []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if o.err != nil {
|
if o.err != nil {
|
||||||
return 0, err
|
return 0, o.err
|
||||||
}
|
}
|
||||||
if o.r == nil {
|
if o.r == nil {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2012-2122 The NATS Authors
|
// Copyright 2012-2023 The NATS Authors
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
|
|||||||
@@ -8789,3 +8789,95 @@ func TestJetStreamStreamInfoAlternates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJetStreamSubscribeConsumerName(t *testing.T) {
|
||||||
|
s := RunBasicJetStreamServer()
|
||||||
|
defer shutdownJSServerAndRemoveStorage(t, s)
|
||||||
|
|
||||||
|
nc, js := jsClient(t, s)
|
||||||
|
defer nc.Close()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Create the stream using our client API.
|
||||||
|
_, err = js.AddStream(&nats.StreamConfig{
|
||||||
|
Name: "TEST",
|
||||||
|
Subjects: []string{"foo", "bar", "baz", "foo.*"},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
_, err = js.Publish("foo", []byte("first"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup the stream for testing.
|
||||||
|
_, err = js.StreamInfo("TEST")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("stream lookup failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub, err := js.SubscribeSync("foo", nats.ConsumerName("my-ephemeral"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cinfo, err := sub.ConsumerInfo()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
got := cinfo.Config.Name
|
||||||
|
expected := "my-ephemeral"
|
||||||
|
if got != expected {
|
||||||
|
t.Fatalf("Expected: %v, got: %v", expected, got)
|
||||||
|
}
|
||||||
|
// Confirm that this is a durable.
|
||||||
|
got = cinfo.Config.Durable
|
||||||
|
expected = ""
|
||||||
|
if got != expected {
|
||||||
|
t.Fatalf("Expected: %v, got: %v", expected, got)
|
||||||
|
}
|
||||||
|
_, err = sub.NextMsg(1 * time.Second)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsumerName will be ignored in case a durable name has been set.
|
||||||
|
sub, err = js.SubscribeSync("foo", nats.Durable("durable"), nats.ConsumerName("custom-name"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cinfo, err = sub.ConsumerInfo()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
got = cinfo.Config.Name
|
||||||
|
expected = "durable"
|
||||||
|
if got != expected {
|
||||||
|
t.Fatalf("Expected: %v, got: %v", expected, got)
|
||||||
|
}
|
||||||
|
got = cinfo.Config.Durable
|
||||||
|
expected = "durable"
|
||||||
|
if got != expected {
|
||||||
|
t.Fatalf("Expected: %v, got: %v", expected, got)
|
||||||
|
}
|
||||||
|
_, err = sub.NextMsg(1 * time.Second)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default Ephemeral name should be short like in the server.
|
||||||
|
sub, err = js.SubscribeSync("foo", nats.ConsumerName(""))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cinfo, err = sub.ConsumerInfo()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
expectedSize := 8
|
||||||
|
result := len(cinfo.Config.Name)
|
||||||
|
if result != expectedSize {
|
||||||
|
t.Fatalf("Expected: %v, got: %v", expectedSize, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -59,9 +59,8 @@ func TestNoRaceObjectContextOpt(t *testing.T) {
|
|||||||
expectOk(t, err)
|
expectOk(t, err)
|
||||||
|
|
||||||
ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
|
ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
|
||||||
time.AfterFunc(100*time.Millisecond, cancel)
|
time.AfterFunc(10*time.Millisecond, cancel)
|
||||||
|
|
||||||
time.AfterFunc(20*time.Millisecond, func() { shutdownJSServerAndRemoveStorage(t, s) })
|
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
_, err = obs.GetBytes("BLOB", nats.Context(ctx))
|
_, err = obs.GetBytes("BLOB", nats.Context(ctx))
|
||||||
expectErr(t, err)
|
expectErr(t, err)
|
||||||
|
|||||||
16
ws.go
16
ws.go
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2022 The NATS Authors
|
// Copyright 2021-2023 The NATS Authors
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
@@ -16,7 +16,6 @@ package nats
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/flate"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
@@ -30,6 +29,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/klauspost/compress/flate"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wsOpCode int
|
type wsOpCode int
|
||||||
@@ -448,8 +449,12 @@ func (w *websocketWriter) Write(p []byte) (int, error) {
|
|||||||
} else {
|
} else {
|
||||||
w.compressor.Reset(buf)
|
w.compressor.Reset(buf)
|
||||||
}
|
}
|
||||||
w.compressor.Write(p)
|
if n, err = w.compressor.Write(p); err != nil {
|
||||||
w.compressor.Close()
|
return n, err
|
||||||
|
}
|
||||||
|
if err = w.compressor.Flush(); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
b := buf.Bytes()
|
b := buf.Bytes()
|
||||||
p = b[:len(b)-4]
|
p = b[:len(b)-4]
|
||||||
}
|
}
|
||||||
@@ -692,6 +697,9 @@ func (nc *Conn) wsEnqueueCloseMsgLocked(status int, payload string) {
|
|||||||
wr.cm = frame
|
wr.cm = frame
|
||||||
wr.cmDone = true
|
wr.cmDone = true
|
||||||
nc.bw.flush()
|
nc.bw.flush()
|
||||||
|
if c := wr.compressor; c != nil {
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nc *Conn) wsEnqueueControlMsg(needsLock bool, frameType wsOpCode, payload []byte) {
|
func (nc *Conn) wsEnqueueControlMsg(needsLock bool, frameType wsOpCode, payload []byte) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2021-2022 The NATS Authors
|
// Copyright 2021-2023 The NATS Authors
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
@@ -15,7 +15,6 @@ package nats
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/flate"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@@ -32,6 +31,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/klauspost/compress/flate"
|
||||||
"github.com/nats-io/nats-server/v2/server"
|
"github.com/nats-io/nats-server/v2/server"
|
||||||
serverTest "github.com/nats-io/nats-server/v2/test"
|
serverTest "github.com/nats-io/nats-server/v2/test"
|
||||||
"github.com/nats-io/nuid"
|
"github.com/nats-io/nuid"
|
||||||
|
|||||||
Reference in New Issue
Block a user