Skip to content

Commit e5fc7ad

Browse files
Cherry-picks for 2.10.26-RC.5 (#6567)
Includes the following: - #6524 - #6525 - #6526 - #5424 - #6565 - #6532 Signed-off-by: Neil Twigg <[email protected]>
2 parents 1d72828 + 18d9129 commit e5fc7ad

20 files changed

+469
-45
lines changed

.github/workflows/cov.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ jobs:
4242

4343
- name: Coveralls
4444
# Use commit hash here to avoid a re-tagging attack, as this is a third-party action
45-
# Commit 3dfc5567390f6fa9267c0ee9c251e4c8c3f18949 = tag v2
46-
uses: coverallsapp/github-action@643bc377ffa44ace6394b2b5d0d3950076de9f63
45+
# Commit 648a8eb78e6d50909eff900e4ec85cab4524a45b = tag v2.3.6
46+
uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b
4747
with:
4848
github-token: ${{ secrets.github_token }}
4949
file: src/github.com/nats-io/nats-server/coverage.lcov

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.22.0
55
toolchain go1.22.8
66

77
require (
8-
github.com/klauspost/compress v1.17.11
8+
github.com/klauspost/compress v1.18.0
99
github.com/minio/highwayhash v1.0.3
1010
github.com/nats-io/jwt/v2 v2.7.3
1111
github.com/nats-io/nats.go v1.39.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3-
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
4-
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
3+
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
4+
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
55
github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q=
66
github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
77
github.com/nats-io/jwt/v2 v2.7.3 h1:6bNPK+FXgBeAqdj4cYQ0F8ViHRbi7woQLq4W29nUAzE=

server/accounts.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2026,7 +2026,7 @@ func (a *Account) addServiceImportSub(si *serviceImport) error {
20262026
a.mu.Unlock()
20272027

20282028
cb := func(sub *subscription, c *client, acc *Account, subject, reply string, msg []byte) {
2029-
c.processServiceImport(si, acc, msg)
2029+
c.pa.delivered = c.processServiceImport(si, acc, msg)
20302030
}
20312031
sub, err := c.processSubEx([]byte(subject), nil, []byte(sid), cb, true, true, false)
20322032
if err != nil {

server/accounts_test.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2018-2024 The NATS Authors
1+
// Copyright 2018-2025 The NATS Authors
22
// Licensed under the Apache License, Version 2.0 (the "License");
33
// you may not use this file except in compliance with the License.
44
// You may obtain a copy of the License at
@@ -3670,3 +3670,31 @@ func TestAccountServiceAndStreamExportDoubleDelivery(t *testing.T) {
36703670
time.Sleep(200 * time.Millisecond)
36713671
require_Equal(t, msgs.Load(), 1)
36723672
}
3673+
3674+
func TestAccountServiceImportNoResponders(t *testing.T) {
3675+
// Setup NATS server.
3676+
cf := createConfFile(t, []byte(`
3677+
port: -1
3678+
accounts: {
3679+
accExp: {
3680+
users: [{user: accExp, password: accExp}]
3681+
exports: [{service: "foo"}]
3682+
}
3683+
accImp: {
3684+
users: [{user: accImp, password: accImp}]
3685+
imports: [{service: {account: accExp, subject: "foo"}}]
3686+
}
3687+
}
3688+
`))
3689+
3690+
s, _ := RunServerWithConfig(cf)
3691+
defer s.Shutdown()
3692+
3693+
// Connect to the import account. We will not setup any responders, so a request should
3694+
// error out with ErrNoResponders.
3695+
nc := natsConnect(t, s.ClientURL(), nats.UserInfo("accImp", "accImp"))
3696+
defer nc.Close()
3697+
3698+
_, err := nc.Request("foo", []byte("request"), 250*time.Millisecond)
3699+
require_Error(t, err, nats.ErrNoResponders)
3700+
}

server/client.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3472,17 +3472,25 @@ func (c *client) deliverMsg(prodIsMQTT bool, sub *subscription, acc *Account, su
34723472
}
34733473
client.mu.Unlock()
34743474

3475+
// For service imports, track if we delivered.
3476+
didDeliver := true
3477+
34753478
// Internal account clients are for service imports and need the '\r\n'.
34763479
start := time.Now()
34773480
if client.kind == ACCOUNT {
34783481
sub.icb(sub, c, acc, string(subject), string(reply), msg)
3482+
// If we are a service import check to make sure we delivered the message somewhere.
3483+
if sub.si {
3484+
didDeliver = c.pa.delivered
3485+
}
34793486
} else {
34803487
sub.icb(sub, c, acc, string(subject), string(reply), msg[:msgSize])
34813488
}
34823489
if dur := time.Since(start); dur >= readLoopReportThreshold {
34833490
srv.Warnf("Internal subscription on %q took too long: %v", subject, dur)
34843491
}
3485-
return true
3492+
3493+
return didDeliver
34863494
}
34873495

34883496
// If we are a client and we detect that the consumer we are
@@ -4196,17 +4204,17 @@ var (
41964204

41974205
// processServiceImport is an internal callback when a subscription matches an imported service
41984206
// from another account. This includes response mappings as well.
4199-
func (c *client) processServiceImport(si *serviceImport, acc *Account, msg []byte) {
4207+
func (c *client) processServiceImport(si *serviceImport, acc *Account, msg []byte) bool {
42004208
// If we are a GW and this is not a direct serviceImport ignore.
42014209
isResponse := si.isRespServiceImport()
42024210
if (c.kind == GATEWAY || c.kind == ROUTER) && !isResponse {
4203-
return
4211+
return false
42044212
}
42054213
// Detect cycles and ignore (return) when we detect one.
42064214
if len(c.pa.psi) > 0 {
42074215
for i := len(c.pa.psi) - 1; i >= 0; i-- {
42084216
if psi := c.pa.psi[i]; psi.se == si.se {
4209-
return
4217+
return false
42104218
}
42114219
}
42124220
}
@@ -4227,7 +4235,7 @@ func (c *client) processServiceImport(si *serviceImport, acc *Account, msg []byt
42274235
// response service imports and rrMap entries which all will need to simply expire.
42284236
// TODO(dlc) - Come up with something better.
42294237
if shouldReturn || (checkJS && si.se != nil && si.se.acc == c.srv.SystemAccount()) {
4230-
return
4238+
return false
42314239
}
42324240

42334241
var nrr []byte
@@ -4375,6 +4383,10 @@ func (c *client) processServiceImport(si *serviceImport, acc *Account, msg []byt
43754383
c.in.rts = orts
43764384
c.pa = pacopy
43774385

4386+
// Before we undo didDeliver based on tracing and last mile, mark in the c.pa which informs us of no responders status.
4387+
// If we override due to tracing and traceOnly we do not want to send back a no responders.
4388+
c.pa.delivered = didDeliver
4389+
43784390
// Determine if we should remove this service import. This is for response service imports.
43794391
// We will remove if we did not deliver, or if we are a response service import and we are
43804392
// a singleton, or we have an EOF message.
@@ -4404,6 +4416,8 @@ func (c *client) processServiceImport(si *serviceImport, acc *Account, msg []byt
44044416
siAcc.removeRespServiceImport(rsi, reason)
44054417
}
44064418
}
4419+
4420+
return didDeliver
44074421
}
44084422

44094423
func (c *client) addSubToRouteTargets(sub *subscription) {

server/config_check_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,6 +1817,23 @@ func TestConfigCheck(t *testing.T) {
18171817
errorLine: 9,
18181818
errorPos: 9,
18191819
},
1820+
{
1821+
name: "invalid duration for remote leafnode first info timeout",
1822+
config: `
1823+
leafnodes {
1824+
port: -1
1825+
remotes [
1826+
{
1827+
url: "nats://127.0.0.1:123"
1828+
first_info_timeout: abc
1829+
}
1830+
]
1831+
}
1832+
`,
1833+
err: fmt.Errorf("error parsing first_info_timeout: time: invalid duration %q", "abc"),
1834+
errorLine: 7,
1835+
errorPos: 8,
1836+
},
18201837
{
18211838
name: "show warnings on empty configs without values",
18221839
config: ``,

server/filestore.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5308,6 +5308,7 @@ func (mb *msgBlock) writeMsgRecord(rl, seq uint64, subj string, mhdr, msg []byte
53085308
if ss, ok := mb.fss.Find(stringToBytes(subj)); ok && ss != nil {
53095309
ss.Msgs++
53105310
ss.Last = seq
5311+
ss.lastNeedsUpdate = false
53115312
} else {
53125313
mb.fss.Insert(stringToBytes(subj), SimpleState{Msgs: 1, First: seq, Last: seq})
53135314
}
@@ -6030,6 +6031,7 @@ func (mb *msgBlock) indexCacheBuf(buf []byte) error {
60306031
if ss, ok := mb.fss.Find(bsubj); ok && ss != nil {
60316032
ss.Msgs++
60326033
ss.Last = seq
6034+
ss.lastNeedsUpdate = false
60336035
} else {
60346036
mb.fss.Insert(bsubj, SimpleState{
60356037
Msgs: 1,
@@ -8057,8 +8059,11 @@ func (mb *msgBlock) recalculateForSubj(subj string, ss *SimpleState) {
80578059
}
80588060
if startSlot >= len(mb.cache.idx) {
80598061
ss.First = ss.Last
8062+
ss.firstNeedsUpdate = false
8063+
ss.lastNeedsUpdate = false
80608064
return
80618065
}
8066+
80628067
endSlot := int(ss.Last - mb.cache.fseq)
80638068
if endSlot < 0 {
80648069
endSlot = 0
@@ -8085,6 +8090,8 @@ func (mb *msgBlock) recalculateForSubj(subj string, ss *SimpleState) {
80858090
li := int(bi) - mb.cache.off
80868091
if li >= len(mb.cache.buf) {
80878092
ss.First = ss.Last
8093+
// Only need to reset ss.lastNeedsUpdate, ss.firstNeedsUpdate is already reset above.
8094+
ss.lastNeedsUpdate = false
80888095
return
80898096
}
80908097
buf := mb.cache.buf[li:]
@@ -8208,6 +8215,7 @@ func (mb *msgBlock) generatePerSubjectInfo() error {
82088215
if ss, ok := mb.fss.Find(stringToBytes(sm.subj)); ok && ss != nil {
82098216
ss.Msgs++
82108217
ss.Last = seq
8218+
ss.lastNeedsUpdate = false
82118219
} else {
82128220
mb.fss.Insert(stringToBytes(sm.subj), SimpleState{Msgs: 1, First: seq, Last: seq})
82138221
}

server/jetstream_cluster_1_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7655,7 +7655,11 @@ func TestJetStreamClusterRecreateConsumerFromMetaSnapshot(t *testing.T) {
76557655
return err
76567656
} else if o := mset.lookupConsumer("CONSUMER"); o == nil {
76577657
return errors.New("consumer doesn't exist")
7658-
} else if ccrg := o.raftNode().Group(); consumerRg == _EMPTY_ {
7658+
} else if rn := o.raftNode(); rn == nil {
7659+
return errors.New("consumer raft node doesn't exist")
7660+
} else if ccrg := rn.Group(); ccrg == _EMPTY_ {
7661+
return errors.New("consumer raft group doesn't exist")
7662+
} else if consumerRg == _EMPTY_ {
76597663
consumerRg = ccrg
76607664
} else if consumerRg != ccrg {
76617665
return errors.New("consumer raft groups don't match")

server/jetstream_cluster_2_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7051,7 +7051,7 @@ func TestJetStreamClusterStreamDirectGetNotTooSoon(t *testing.T) {
70517051
defer nc.Close()
70527052

70537053
_, err = nc.Request(getSubj, nil, time.Second)
7054-
require_Error(t, err, nats.ErrTimeout)
7054+
require_Error(t, err, nats.ErrNoResponders)
70557055

70567056
// Now start all and make sure they all eventually have subs for direct access.
70577057
c.restartAll()

0 commit comments

Comments
 (0)