• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nats-io / nats-server / 14426271004

11 Apr 2025 03:04PM UTC coverage: 85.523% (-0.03%) from 85.552%
14426271004

push

github

web-flow
Report `GOMAXPROCS` and `GOMEMLIMIT` in `ServerStats` (#6791)

Fixes #6672.

Signed-off-by: Neil Twigg <neil@nats.io>

69537 of 81308 relevant lines covered (85.52%)

357513.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.83
/server/stream.go
1
// Copyright 2019-2025 The NATS Authors
2
// Licensed under the Apache License, Version 2.0 (the "License");
3
// you may not use this file except in compliance with the License.
4
// You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software
9
// distributed under the License is distributed on an "AS IS" BASIS,
10
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
// See the License for the specific language governing permissions and
12
// limitations under the License.
13

14
package server
15

16
import (
17
        "archive/tar"
18
        "bytes"
19
        "encoding/json"
20
        "errors"
21
        "fmt"
22
        "io"
23
        "math"
24
        "math/rand"
25
        "os"
26
        "path/filepath"
27
        "reflect"
28
        "strconv"
29
        "strings"
30
        "sync"
31
        "sync/atomic"
32
        "time"
33

34
        "github.com/klauspost/compress/s2"
35
        "github.com/nats-io/nats-server/v2/server/gsl"
36
        "github.com/nats-io/nuid"
37
)
38

39
// StreamConfigRequest is used to create or update a stream.
40
type StreamConfigRequest struct {
41
        StreamConfig
42
        // This is not part of the StreamConfig, because its scoped to request,
43
        // and not to the stream itself.
44
        Pedantic bool `json:"pedantic,omitempty"`
45
}
46

47
// StreamConfig will determine the name, subjects and retention policy
48
// for a given stream. If subjects is empty the name will be used.
49
type StreamConfig struct {
50
        Name         string           `json:"name"`
51
        Description  string           `json:"description,omitempty"`
52
        Subjects     []string         `json:"subjects,omitempty"`
53
        Retention    RetentionPolicy  `json:"retention"`
54
        MaxConsumers int              `json:"max_consumers"`
55
        MaxMsgs      int64            `json:"max_msgs"`
56
        MaxBytes     int64            `json:"max_bytes"`
57
        MaxAge       time.Duration    `json:"max_age"`
58
        MaxMsgsPer   int64            `json:"max_msgs_per_subject"`
59
        MaxMsgSize   int32            `json:"max_msg_size,omitempty"`
60
        Discard      DiscardPolicy    `json:"discard"`
61
        Storage      StorageType      `json:"storage"`
62
        Replicas     int              `json:"num_replicas"`
63
        NoAck        bool             `json:"no_ack,omitempty"`
64
        Template     string           `json:"template_owner,omitempty"`
65
        Duplicates   time.Duration    `json:"duplicate_window,omitempty"`
66
        Placement    *Placement       `json:"placement,omitempty"`
67
        Mirror       *StreamSource    `json:"mirror,omitempty"`
68
        Sources      []*StreamSource  `json:"sources,omitempty"`
69
        Compression  StoreCompression `json:"compression"`
70
        FirstSeq     uint64           `json:"first_seq,omitempty"`
71

72
        // Allow applying a subject transform to incoming messages before doing anything else
73
        SubjectTransform *SubjectTransformConfig `json:"subject_transform,omitempty"`
74

75
        // Allow republish of the message after being sequenced and stored.
76
        RePublish *RePublish `json:"republish,omitempty"`
77

78
        // Allow higher performance, direct access to get individual messages. E.g. KeyValue
79
        AllowDirect bool `json:"allow_direct"`
80
        // Allow higher performance and unified direct access for mirrors as well.
81
        MirrorDirect bool `json:"mirror_direct"`
82

83
        // Allow KV like semantics to also discard new on a per subject basis
84
        DiscardNewPer bool `json:"discard_new_per_subject,omitempty"`
85

86
        // Optional qualifiers. These can not be modified after set to true.
87

88
        // Sealed will seal a stream so no messages can get out or in.
89
        Sealed bool `json:"sealed"`
90
        // DenyDelete will restrict the ability to delete messages.
91
        DenyDelete bool `json:"deny_delete"`
92
        // DenyPurge will restrict the ability to purge messages.
93
        DenyPurge bool `json:"deny_purge"`
94
        // AllowRollup allows messages to be placed into the system and purge
95
        // all older messages using a special msg header.
96
        AllowRollup bool `json:"allow_rollup_hdrs"`
97

98
        // The following defaults will apply to consumers when created against
99
        // this stream, unless overridden manually.
100
        // TODO(nat): Can/should we name these better?
101
        ConsumerLimits StreamConsumerLimits `json:"consumer_limits"`
102

103
        // AllowMsgTTL allows header initiated per-message TTLs. If disabled,
104
        // then the `NATS-TTL` header will be ignored.
105
        AllowMsgTTL bool `json:"allow_msg_ttl"`
106

107
        // SubjectDeleteMarkerTTL sets the TTL of delete marker messages left behind by
108
        // subject delete markers.
109
        SubjectDeleteMarkerTTL time.Duration `json:"subject_delete_marker_ttl,omitempty"`
110

111
        // Metadata is additional metadata for the Stream.
112
        Metadata map[string]string `json:"metadata,omitempty"`
113
}
114

115
// clone performs a deep copy of the StreamConfig struct, returning a new clone with
116
// all values copied.
117
func (cfg *StreamConfig) clone() *StreamConfig {
543✔
118
        clone := *cfg
543✔
119
        if cfg.Placement != nil {
598✔
120
                placement := *cfg.Placement
55✔
121
                clone.Placement = &placement
55✔
122
        }
55✔
123
        if cfg.Mirror != nil {
544✔
124
                mirror := *cfg.Mirror
1✔
125
                clone.Mirror = &mirror
1✔
126
        }
1✔
127
        if len(cfg.Sources) > 0 {
563✔
128
                clone.Sources = make([]*StreamSource, len(cfg.Sources))
20✔
129
                for i, cfgSource := range cfg.Sources {
123✔
130
                        source := *cfgSource
103✔
131
                        clone.Sources[i] = &source
103✔
132
                }
103✔
133
        }
134
        if cfg.SubjectTransform != nil {
544✔
135
                transform := *cfg.SubjectTransform
1✔
136
                clone.SubjectTransform = &transform
1✔
137
        }
1✔
138
        if cfg.RePublish != nil {
544✔
139
                rePublish := *cfg.RePublish
1✔
140
                clone.RePublish = &rePublish
1✔
141
        }
1✔
142
        if cfg.Metadata != nil {
1,086✔
143
                clone.Metadata = make(map[string]string, len(cfg.Metadata))
543✔
144
                for k, v := range cfg.Metadata {
1,085✔
145
                        clone.Metadata[k] = v
542✔
146
                }
542✔
147
        }
148
        return &clone
543✔
149
}
150

151
type StreamConsumerLimits struct {
152
        InactiveThreshold time.Duration `json:"inactive_threshold,omitempty"`
153
        MaxAckPending     int           `json:"max_ack_pending,omitempty"`
154
}
155

156
// SubjectTransformConfig is for applying a subject transform (to matching messages) before doing anything else when a new message is received
157
type SubjectTransformConfig struct {
158
        Source      string `json:"src"`
159
        Destination string `json:"dest"`
160
}
161

162
// RePublish is for republishing messages once committed to a stream.
163
type RePublish struct {
164
        Source      string `json:"src,omitempty"`
165
        Destination string `json:"dest"`
166
        HeadersOnly bool   `json:"headers_only,omitempty"`
167
}
168

169
// JSPubAckResponse is a formal response to a publish operation.
170
type JSPubAckResponse struct {
171
        Error *ApiError `json:"error,omitempty"`
172
        *PubAck
173
}
174

175
// ToError checks if the response has a error and if it does converts it to an error
176
// avoiding the pitfalls described by https://yourbasic.org/golang/gotcha-why-nil-error-not-equal-nil/
177
func (r *JSPubAckResponse) ToError() error {
1,097✔
178
        if r.Error == nil {
2,192✔
179
                return nil
1,095✔
180
        }
1,095✔
181
        return r.Error
2✔
182
}
183

184
// PubAck is the detail you get back from a publish to a stream that was successful.
185
// e.g. +OK {"stream": "Orders", "seq": 22}
186
type PubAck struct {
187
        Stream    string `json:"stream"`
188
        Sequence  uint64 `json:"seq"`
189
        Domain    string `json:"domain,omitempty"`
190
        Duplicate bool   `json:"duplicate,omitempty"`
191
}
192

193
// StreamInfo shows config and current state for this stream.
194
type StreamInfo struct {
195
        Config     StreamConfig        `json:"config"`
196
        Created    time.Time           `json:"created"`
197
        State      StreamState         `json:"state"`
198
        Domain     string              `json:"domain,omitempty"`
199
        Cluster    *ClusterInfo        `json:"cluster,omitempty"`
200
        Mirror     *StreamSourceInfo   `json:"mirror,omitempty"`
201
        Sources    []*StreamSourceInfo `json:"sources,omitempty"`
202
        Alternates []StreamAlternate   `json:"alternates,omitempty"`
203
        // TimeStamp indicates when the info was gathered
204
        TimeStamp time.Time `json:"ts"`
205
}
206

207
type StreamAlternate struct {
208
        Name    string `json:"name"`
209
        Domain  string `json:"domain,omitempty"`
210
        Cluster string `json:"cluster"`
211
}
212

213
// ClusterInfo shows information about the underlying set of servers
214
// that make up the stream or consumer.
215
type ClusterInfo struct {
216
        Name      string      `json:"name,omitempty"`
217
        RaftGroup string      `json:"raft_group,omitempty"`
218
        Leader    string      `json:"leader,omitempty"`
219
        Replicas  []*PeerInfo `json:"replicas,omitempty"`
220
}
221

222
// PeerInfo shows information about all the peers in the cluster that
223
// are supporting the stream or consumer.
224
type PeerInfo struct {
225
        Name    string        `json:"name"`
226
        Current bool          `json:"current"`
227
        Offline bool          `json:"offline,omitempty"`
228
        Active  time.Duration `json:"active"`
229
        Lag     uint64        `json:"lag,omitempty"`
230
        Peer    string        `json:"peer"`
231
        // For migrations.
232
        cluster string
233
}
234

235
// StreamSourceInfo shows information about an upstream stream source.
236
type StreamSourceInfo struct {
237
        Name              string                   `json:"name"`
238
        External          *ExternalStream          `json:"external,omitempty"`
239
        Lag               uint64                   `json:"lag"`
240
        Active            time.Duration            `json:"active"`
241
        Error             *ApiError                `json:"error,omitempty"`
242
        FilterSubject     string                   `json:"filter_subject,omitempty"`
243
        SubjectTransforms []SubjectTransformConfig `json:"subject_transforms,omitempty"`
244
}
245

246
// StreamSource dictates how streams can source from other streams.
247
type StreamSource struct {
248
        Name              string                   `json:"name"`
249
        OptStartSeq       uint64                   `json:"opt_start_seq,omitempty"`
250
        OptStartTime      *time.Time               `json:"opt_start_time,omitempty"`
251
        FilterSubject     string                   `json:"filter_subject,omitempty"`
252
        SubjectTransforms []SubjectTransformConfig `json:"subject_transforms,omitempty"`
253
        External          *ExternalStream          `json:"external,omitempty"`
254

255
        // Internal
256
        iname string // For indexing when stream names are the same for multiple sources.
257
}
258

259
// ExternalStream allows you to qualify access to a stream source in another account.
260
type ExternalStream struct {
261
        ApiPrefix     string `json:"api"`
262
        DeliverPrefix string `json:"deliver"`
263
}
264

265
// For managing stream ingest.
266
const (
267
        streamDefaultMaxQueueMsgs  = 10_000
268
        streamDefaultMaxQueueBytes = 1024 * 1024 * 128
269
)
270

271
// Stream is a jetstream stream of messages. When we receive a message internally destined
272
// for a Stream we will direct link from the client to this structure.
273
type stream struct {
274
        mu     sync.RWMutex // Read/write lock for the stream.
275
        js     *jetStream   // The internal *jetStream for the account.
276
        jsa    *jsAccount   // The JetStream account-level information.
277
        acc    *Account     // The account this stream is defined in.
278
        srv    *Server      // The server we are running in.
279
        client *client      // The internal JetStream client.
280
        sysc   *client      // The internal JetStream system client.
281

282
        // The current last subscription ID for the subscriptions through `client`.
283
        // Those subscriptions are for the subjects filters being listened to and captured by the stream.
284
        sid atomic.Uint64
285

286
        pubAck    []byte                  // The template (prefix) to generate the pubAck responses for this stream quickly.
287
        outq      *jsOutQ                 // Queue of *jsPubMsg for sending messages.
288
        msgs      *ipQueue[*inMsg]        // Intra-process queue for the ingress of messages.
289
        gets      *ipQueue[*directGetReq] // Intra-process queue for the direct get requests.
290
        store     StreamStore             // The storage for this stream.
291
        ackq      *ipQueue[uint64]        // Intra-process queue for acks.
292
        lseq      uint64                  // The sequence number of the last message stored in the stream.
293
        lmsgId    string                  // The de-duplication message ID of the last message stored in the stream.
294
        consumers map[string]*consumer    // The consumers for this stream.
295
        numFilter int                     // The number of filtered consumers.
296
        cfg       StreamConfig            // The stream's config.
297
        cfgMu     sync.RWMutex            // Config mutex used to solve some races with consumer code
298
        created   time.Time               // Time the stream was created.
299
        stype     StorageType             // The storage type.
300
        tier      string                  // The tier is the number of replicas for the stream (e.g. "R1" or "R3").
301
        ddmap     map[string]*ddentry     // The dedupe map.
302
        ddarr     []*ddentry              // The dedupe array.
303
        ddindex   int                     // The dedupe index.
304
        ddtmr     *time.Timer             // The dedupe timer.
305
        qch       chan struct{}           // The quit channel.
306
        mqch      chan struct{}           // The monitor's quit channel.
307
        active    bool                    // Indicates that there are active internal subscriptions (for the subject filters)
308
        // and/or mirror/sources consumers are scheduled to be established or already started.
309
        ddloaded bool        // set to true when the deduplication structures are been built.
310
        closed   atomic.Bool // Set to true when stop() is called on the stream.
311

312
        // Mirror
313
        mirror *sourceInfo
314

315
        // Sources
316
        sources              map[string]*sourceInfo
317
        sourceSetupSchedules map[string]*time.Timer
318
        sourcesConsumerSetup *time.Timer
319
        smsgs                *ipQueue[*inMsg] // Intra-process queue for all incoming sourced messages.
320

321
        // Indicates we have direct consumers.
322
        directs int
323

324
        // For input subject transform.
325
        itr *subjectTransform
326

327
        // For republishing.
328
        tr *subjectTransform
329

330
        // For processing consumers without main stream lock.
331
        clsMu sync.RWMutex
332
        cList []*consumer                    // Consumer list.
333
        sch   chan struct{}                  // Channel to signal consumers.
334
        sigq  *ipQueue[*cMsg]                // Intra-process queue for the messages to signal to the consumers.
335
        csl   *gsl.GenericSublist[*consumer] // Consumer subscription list.
336

337
        // Leader will store seq/msgTrace in clustering mode. Used in applyStreamEntries
338
        // to know if trace event should be sent after processing.
339
        mt map[uint64]*msgTrace
340

341
        // For non limits policy streams when they process an ack before the actual msg.
342
        // Can happen in stretch clusters, multi-cloud, or during catchup for a restarted server.
343
        preAcks map[uint64]map[*consumer]struct{}
344

345
        // TODO(dlc) - Hide everything below behind two pointers.
346
        // Clustered mode.
347
        sa        *streamAssignment // What the meta controller uses to assign streams to peers.
348
        node      RaftNode          // Our RAFT node for the stream's group.
349
        catchup   atomic.Bool       // Used to signal we are in catchup mode.
350
        catchups  map[string]uint64 // The number of messages that need to be caught per peer.
351
        syncSub   *subscription     // Internal subscription for sync messages (on "$JSC.SYNC").
352
        infoSub   *subscription     // Internal subscription for stream info requests.
353
        clMu      sync.Mutex        // The mutex for clseq and clfs.
354
        clseq     uint64            // The current last seq being proposed to the NRG layer.
355
        clfs      uint64            // The count (offset) of the number of failed NRG sequences used to compute clseq.
356
        inflight  map[uint64]uint64 // Inflight message sizes per clseq.
357
        lqsent    time.Time         // The time at which the last lost quorum advisory was sent. Used to rate limit.
358
        uch       chan struct{}     // The channel to signal updates to the monitor routine.
359
        inMonitor bool              // True if the monitor routine has been started.
360

361
        expectedPerSubjectSequence  map[uint64]string   // Inflight 'expected per subject' subjects per clseq.
362
        expectedPerSubjectInProcess map[string]struct{} // Current 'expected per subject' subjects in process.
363

364
        // Direct get subscription.
365
        directSub *subscription
366
        lastBySub *subscription
367

368
        monitorWg sync.WaitGroup // Wait group for the monitor routine.
369
}
370

371
type sourceInfo struct {
372
        name  string        // The name of the stream being sourced.
373
        iname string        // The unique index name of this particular source.
374
        cname string        // The name of the current consumer for this source.
375
        sub   *subscription // The subscription to the consumer.
376

377
        // (mirrors only) The subscription to the direct get request subject for
378
        // the source stream's name on the `_sys_` queue group.
379
        dsub *subscription
380

381
        // (mirrors only) The subscription to the direct get last per subject request subject for
382
        // the source stream's name on the `_sys_` queue group.
383
        lbsub *subscription
384

385
        msgs  *ipQueue[*inMsg]    // Intra-process queue for incoming messages.
386
        sseq  uint64              // Last stream message sequence number seen from the source.
387
        dseq  uint64              // Last delivery (i.e. consumer's) sequence number.
388
        lag   uint64              // 0 or number of messages pending (as last reported by the consumer) - 1.
389
        err   *ApiError           // The API error that caused the last consumer setup to fail.
390
        fails int                 // The number of times trying to setup the consumer failed.
391
        last  atomic.Int64        // Time the consumer was created or of last message it received.
392
        lreq  time.Time           // The last time setupMirrorConsumer/setupSourceConsumer was called.
393
        qch   chan struct{}       // Quit channel.
394
        sip   bool                // Setup in progress.
395
        wg    sync.WaitGroup      // WaitGroup for the consumer's go routine.
396
        sf    string              // The subject filter.
397
        sfs   []string            // The subject filters.
398
        trs   []*subjectTransform // The subject transforms.
399
}
400

401
// For mirrors and direct get
402
const (
403
        dgetGroup          = sysGroup
404
        dgetCaughtUpThresh = 10
405
)
406

407
// Headers for published messages.
408
const (
409
        JSMsgId                   = "Nats-Msg-Id"
410
        JSExpectedStream          = "Nats-Expected-Stream"
411
        JSExpectedLastSeq         = "Nats-Expected-Last-Sequence"
412
        JSExpectedLastSubjSeq     = "Nats-Expected-Last-Subject-Sequence"
413
        JSExpectedLastSubjSeqSubj = "Nats-Expected-Last-Subject-Sequence-Subject"
414
        JSExpectedLastMsgId       = "Nats-Expected-Last-Msg-Id"
415
        JSStreamSource            = "Nats-Stream-Source"
416
        JSLastConsumerSeq         = "Nats-Last-Consumer"
417
        JSLastStreamSeq           = "Nats-Last-Stream"
418
        JSConsumerStalled         = "Nats-Consumer-Stalled"
419
        JSMsgRollup               = "Nats-Rollup"
420
        JSMsgSize                 = "Nats-Msg-Size"
421
        JSResponseType            = "Nats-Response-Type"
422
        JSMessageTTL              = "Nats-TTL"
423
        JSMarkerReason            = "Nats-Marker-Reason"
424
)
425

426
// Headers for republished messages and direct gets.
427
const (
428
        JSStream       = "Nats-Stream"
429
        JSSequence     = "Nats-Sequence"
430
        JSTimeStamp    = "Nats-Time-Stamp"
431
        JSSubject      = "Nats-Subject"
432
        JSLastSequence = "Nats-Last-Sequence"
433
        JSNumPending   = "Nats-Num-Pending"
434
        JSUpToSequence = "Nats-UpTo-Sequence"
435
)
436

437
// Rollups, can be subject only or all messages.
438
const (
439
        JSMsgRollupSubject = "sub"
440
        JSMsgRollupAll     = "all"
441
)
442

443
// Applied limits in the Nats-Applied-Limit header.
444
const (
445
        JSMarkerReasonMaxAge = "MaxAge"
446
        JSMarkerReasonPurge  = "Purge"
447
        JSMarkerReasonRemove = "Remove"
448
)
449

450
const (
451
        jsCreateResponse = "create"
452
)
453

454
// Dedupe entry
455
type ddentry struct {
456
        id  string // The unique message ID provided by the client.
457
        seq uint64 // The sequence number of the message.
458
        ts  int64  // The timestamp of the message.
459
}
460

461
// Replicas Range
462
const StreamMaxReplicas = 5
463

464
// AddStream adds a stream for the given account.
465
func (a *Account) addStream(config *StreamConfig) (*stream, error) {
965✔
466
        return a.addStreamWithAssignment(config, nil, nil, false)
965✔
467
}
965✔
468

469
// AddStreamWithStore adds a stream for the given account with custome store config options.
470
func (a *Account) addStreamWithStore(config *StreamConfig, fsConfig *FileStoreConfig) (*stream, error) {
5✔
471
        return a.addStreamWithAssignment(config, fsConfig, nil, false)
5✔
472
}
5✔
473

474
func (a *Account) addStreamPedantic(config *StreamConfig, pedantic bool) (*stream, error) {
1,105✔
475
        return a.addStreamWithAssignment(config, nil, nil, pedantic)
1,105✔
476
}
1,105✔
477

478
func (a *Account) addStreamWithAssignment(config *StreamConfig, fsConfig *FileStoreConfig, sa *streamAssignment, pedantic bool) (*stream, error) {
5,525✔
479
        s, jsa, err := a.checkForJetStream()
5,525✔
480
        if err != nil {
5,525✔
481
                return nil, err
×
482
        }
×
483

484
        // If we do not have the stream currently assigned to us in cluster mode we will proceed but warn.
485
        // This can happen on startup with restored state where on meta replay we still do not have
486
        // the assignment. Running in single server mode this always returns true.
487
        if !jsa.streamAssigned(config.Name) {
5,525✔
488
                s.Debugf("Stream '%s > %s' does not seem to be assigned to this server", a.Name, config.Name)
×
489
        }
×
490

491
        // Sensible defaults.
492
        ccfg, apiErr := s.checkStreamCfg(config, a, pedantic)
5,525✔
493
        if apiErr != nil {
5,580✔
494
                return nil, apiErr
55✔
495
        }
55✔
496
        cfg := &ccfg
5,470✔
497

5,470✔
498
        singleServerMode := !s.JetStreamIsClustered() && s.standAloneMode()
5,470✔
499
        if singleServerMode && cfg.Replicas > 1 {
5,472✔
500
                return nil, ApiErrors[JSStreamReplicasNotSupportedErr]
2✔
501
        }
2✔
502

503
        // Make sure we are ok when these are done in parallel.
504
        // We used to call Add(1) in the "else" clause of the "if loaded"
505
        // statement. This caused a data race because it was possible
506
        // that one go routine stores (with count==0) and another routine
507
        // gets "loaded==true" and calls wg.Wait() while the other routine
508
        // then calls wg.Add(1). It also could mean that two routines execute
509
        // the rest of the code concurrently.
510
        swg := &sync.WaitGroup{}
5,468✔
511
        swg.Add(1)
5,468✔
512
        v, loaded := jsa.inflight.LoadOrStore(cfg.Name, swg)
5,468✔
513
        wg := v.(*sync.WaitGroup)
5,468✔
514
        if loaded {
5,468✔
515
                wg.Wait()
×
516
                // This waitgroup is "thrown away" (since there was an existing one).
×
517
                swg.Done()
×
518
        } else {
5,468✔
519
                defer func() {
10,936✔
520
                        jsa.inflight.Delete(cfg.Name)
5,468✔
521
                        wg.Done()
5,468✔
522
                }()
5,468✔
523
        }
524

525
        js, isClustered := jsa.jetStreamAndClustered()
5,468✔
526
        jsa.mu.Lock()
5,468✔
527
        if mset, ok := jsa.streams[cfg.Name]; ok {
5,485✔
528
                jsa.mu.Unlock()
17✔
529
                // Check to see if configs are same.
17✔
530
                ocfg := mset.config()
17✔
531

17✔
532
                // set the index name on cfg since it would not contain a value for iname while the return from mset.config() does to ensure the DeepEqual works
17✔
533
                for _, s := range cfg.Sources {
17✔
534
                        s.setIndexName()
×
535
                }
×
536

537
                copyStreamMetadata(cfg, &ocfg)
17✔
538
                if reflect.DeepEqual(cfg, &ocfg) {
34✔
539
                        if sa != nil {
17✔
540
                                mset.setStreamAssignment(sa)
×
541
                        }
×
542
                        return mset, nil
17✔
543
                } else {
×
544
                        return nil, ApiErrors[JSStreamNameExistErr]
×
545
                }
×
546
        }
547
        jsa.usageMu.RLock()
5,451✔
548
        selected, tier, hasTier := jsa.selectLimits(cfg.Replicas)
5,451✔
549
        jsa.usageMu.RUnlock()
5,451✔
550
        reserved := int64(0)
5,451✔
551
        if !isClustered {
7,444✔
552
                reserved = jsa.tieredReservation(tier, cfg)
1,993✔
553
        }
1,993✔
554
        jsa.mu.Unlock()
5,451✔
555

5,451✔
556
        if !hasTier {
5,452✔
557
                return nil, NewJSNoLimitsError()
1✔
558
        }
1✔
559
        js.mu.RLock()
5,450✔
560
        if isClustered {
8,908✔
561
                _, reserved = tieredStreamAndReservationCount(js.cluster.streams[a.Name], tier, cfg)
3,458✔
562
        }
3,458✔
563
        if err := js.checkAllLimits(&selected, cfg, reserved, 0); err != nil {
5,459✔
564
                js.mu.RUnlock()
9✔
565
                return nil, err
9✔
566
        }
9✔
567
        js.mu.RUnlock()
5,441✔
568
        jsa.mu.Lock()
5,441✔
569
        // Check for template ownership if present.
5,441✔
570
        if cfg.Template != _EMPTY_ && jsa.account != nil {
5,647✔
571
                if !jsa.checkTemplateOwnership(cfg.Template, cfg.Name) {
207✔
572
                        jsa.mu.Unlock()
1✔
573
                        return nil, fmt.Errorf("stream not owned by template")
1✔
574
                }
1✔
575
        }
576

577
        // If mirror, check if the transforms (if any) are valid.
578
        if cfg.Mirror != nil {
5,527✔
579
                if len(cfg.Mirror.SubjectTransforms) == 0 {
168✔
580
                        if cfg.Mirror.FilterSubject != _EMPTY_ && !IsValidSubject(cfg.Mirror.FilterSubject) {
81✔
581
                                jsa.mu.Unlock()
×
582
                                return nil, fmt.Errorf("subject filter '%s' for the mirror %w", cfg.Mirror.FilterSubject, ErrBadSubject)
×
583
                        }
×
584
                } else {
6✔
585
                        for _, st := range cfg.Mirror.SubjectTransforms {
13✔
586
                                if st.Source != _EMPTY_ && !IsValidSubject(st.Source) {
7✔
587
                                        jsa.mu.Unlock()
×
588
                                        return nil, fmt.Errorf("invalid subject transform source '%s' for the mirror: %w", st.Source, ErrBadSubject)
×
589
                                }
×
590
                                // check the transform, if any, is valid
591
                                if st.Destination != _EMPTY_ {
12✔
592
                                        if _, err = NewSubjectTransform(st.Source, st.Destination); err != nil {
5✔
593
                                                jsa.mu.Unlock()
×
594
                                                return nil, fmt.Errorf("subject transform from '%s' to '%s' for the mirror: %w", st.Source, st.Destination, err)
×
595
                                        }
×
596
                                }
597
                        }
598
                }
599
        }
600

601
        // Setup our internal indexed names here for sources and check if the transforms (if any) are valid.
602
        for _, ssi := range cfg.Sources {
5,594✔
603
                if len(ssi.SubjectTransforms) == 0 {
303✔
604
                        // check the filter, if any, is valid
149✔
605
                        if ssi.FilterSubject != _EMPTY_ && !IsValidSubject(ssi.FilterSubject) {
149✔
606
                                jsa.mu.Unlock()
×
607
                                return nil, fmt.Errorf("subject filter '%s' for the source: %w", ssi.FilterSubject, ErrBadSubject)
×
608
                        }
×
609
                } else {
5✔
610
                        for _, st := range ssi.SubjectTransforms {
12✔
611
                                if st.Source != _EMPTY_ && !IsValidSubject(st.Source) {
7✔
612
                                        jsa.mu.Unlock()
×
613
                                        return nil, fmt.Errorf("subject filter '%s' for the source: %w", st.Source, ErrBadSubject)
×
614
                                }
×
615
                                // check the transform, if any, is valid
616
                                if st.Destination != _EMPTY_ {
13✔
617
                                        if _, err = NewSubjectTransform(st.Source, st.Destination); err != nil {
6✔
618
                                                jsa.mu.Unlock()
×
619
                                                return nil, fmt.Errorf("subject transform from '%s' to '%s' for the source: %w", st.Source, st.Destination, err)
×
620
                                        }
×
621
                                }
622
                        }
623
                }
624
        }
625

626
        // Check for overlapping subjects with other streams.
627
        // These are not allowed for now.
628
        if jsa.subjectsOverlap(cfg.Subjects, nil) {
5,463✔
629
                jsa.mu.Unlock()
23✔
630
                return nil, NewJSStreamSubjectOverlapError()
23✔
631
        }
23✔
632

633
        if !hasTier {
5,417✔
634
                jsa.mu.Unlock()
×
635
                return nil, fmt.Errorf("no applicable tier found")
×
636
        }
×
637

638
        // Setup the internal clients.
639
        c := s.createInternalJetStreamClient()
5,417✔
640
        ic := s.createInternalJetStreamClient()
5,417✔
641

5,417✔
642
        // Work out the stream ingest limits.
5,417✔
643
        mlen := s.opts.StreamMaxBufferedMsgs
5,417✔
644
        msz := uint64(s.opts.StreamMaxBufferedSize)
5,417✔
645
        if mlen == 0 {
10,833✔
646
                mlen = streamDefaultMaxQueueMsgs
5,416✔
647
        }
5,416✔
648
        if msz == 0 {
10,833✔
649
                msz = streamDefaultMaxQueueBytes
5,416✔
650
        }
5,416✔
651

652
        qpfx := fmt.Sprintf("[ACC:%s] stream '%s' ", a.Name, config.Name)
5,417✔
653
        mset := &stream{
5,417✔
654
                acc:       a,
5,417✔
655
                jsa:       jsa,
5,417✔
656
                cfg:       *cfg,
5,417✔
657
                js:        js,
5,417✔
658
                srv:       s,
5,417✔
659
                client:    c,
5,417✔
660
                sysc:      ic,
5,417✔
661
                tier:      tier,
5,417✔
662
                stype:     cfg.Storage,
5,417✔
663
                consumers: make(map[string]*consumer),
5,417✔
664
                msgs: newIPQueue[*inMsg](s, qpfx+"messages",
5,417✔
665
                        ipqSizeCalculation(func(msg *inMsg) uint64 {
708,276✔
666
                                return uint64(len(msg.hdr) + len(msg.msg) + len(msg.rply) + len(msg.subj))
702,859✔
667
                        }),
702,859✔
668
                        ipqLimitByLen[*inMsg](mlen),
669
                        ipqLimitBySize[*inMsg](msz),
670
                ),
671
                gets: newIPQueue[*directGetReq](s, qpfx+"direct gets"),
672
                qch:  make(chan struct{}),
673
                mqch: make(chan struct{}),
674
                uch:  make(chan struct{}, 4),
675
                sch:  make(chan struct{}, 1),
676
        }
677

678
        // Start our signaling routine to process consumers.
679
        mset.sigq = newIPQueue[*cMsg](s, qpfx+"obs") // of *cMsg
5,417✔
680
        go mset.signalConsumersLoop()
5,417✔
681

5,417✔
682
        // For no-ack consumers when we are interest retention.
5,417✔
683
        if cfg.Retention != LimitsPolicy {
6,923✔
684
                mset.ackq = newIPQueue[uint64](s, qpfx+"acks")
1,506✔
685
        }
1,506✔
686

687
        // Check for input subject transform
688
        if cfg.SubjectTransform != nil {
5,420✔
689
                tr, err := NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination)
3✔
690
                if err != nil {
3✔
691
                        jsa.mu.Unlock()
×
692
                        return nil, fmt.Errorf("stream subject transform from '%s' to '%s': %w", cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination, err)
×
693
                }
×
694
                mset.itr = tr
3✔
695
        }
696

697
        // Check for RePublish.
698
        if cfg.RePublish != nil {
5,427✔
699
                tr, err := NewSubjectTransform(cfg.RePublish.Source, cfg.RePublish.Destination)
10✔
700
                if err != nil {
10✔
701
                        jsa.mu.Unlock()
×
702
                        return nil, fmt.Errorf("stream republish transform from '%s' to '%s': %w", cfg.RePublish.Source, cfg.RePublish.Destination, err)
×
703
                }
×
704
                // Assign our transform for republishing.
705
                mset.tr = tr
10✔
706
        }
707
        storeDir := filepath.Join(jsa.storeDir, streamsDir, cfg.Name)
5,417✔
708
        jsa.mu.Unlock()
5,417✔
709

5,417✔
710
        // Bind to the user account.
5,417✔
711
        c.registerWithAccount(a)
5,417✔
712
        // Bind to the system account.
5,417✔
713
        ic.registerWithAccount(s.SystemAccount())
5,417✔
714

5,417✔
715
        // Create the appropriate storage
5,417✔
716
        fsCfg := fsConfig
5,417✔
717
        if fsCfg == nil {
10,829✔
718
                fsCfg = &FileStoreConfig{}
5,412✔
719
                // If we are file based and not explicitly configured
5,412✔
720
                // we may be able to auto-tune based on max msgs or bytes.
5,412✔
721
                if cfg.Storage == FileStorage {
10,503✔
722
                        mset.autoTuneFileStorageBlockSize(fsCfg)
5,091✔
723
                }
5,091✔
724
        }
725
        fsCfg.StoreDir = storeDir
5,417✔
726
        fsCfg.AsyncFlush = false
5,417✔
727
        // Grab configured sync interval.
5,417✔
728
        fsCfg.SyncInterval = s.getOpts().SyncInterval
5,417✔
729
        fsCfg.SyncAlways = s.getOpts().SyncAlways
5,417✔
730
        fsCfg.Compression = config.Compression
5,417✔
731

5,417✔
732
        if err := mset.setupStore(fsCfg); err != nil {
5,418✔
733
                mset.stop(true, false)
1✔
734
                return nil, NewJSStreamStoreFailedError(err)
1✔
735
        }
1✔
736

737
        // Create our pubAck template here. Better than json marshal each time on success.
738
        if domain := s.getOpts().JetStreamDomain; domain != _EMPTY_ {
5,630✔
739
                mset.pubAck = []byte(fmt.Sprintf("{%q:%q, %q:%q, %q:", "stream", cfg.Name, "domain", domain, "seq"))
214✔
740
        } else {
5,416✔
741
                mset.pubAck = []byte(fmt.Sprintf("{%q:%q, %q:", "stream", cfg.Name, "seq"))
5,202✔
742
        }
5,202✔
743
        end := len(mset.pubAck)
5,416✔
744
        mset.pubAck = mset.pubAck[:end:end]
5,416✔
745

5,416✔
746
        // Set our known last sequence.
5,416✔
747
        var state StreamState
5,416✔
748
        mset.store.FastState(&state)
5,416✔
749

5,416✔
750
        // Possible race with consumer.setLeader during recovery.
5,416✔
751
        mset.mu.Lock()
5,416✔
752
        mset.lseq = state.LastSeq
5,416✔
753
        mset.mu.Unlock()
5,416✔
754

5,416✔
755
        // If no msgs (new stream), set dedupe state loaded to true.
5,416✔
756
        if state.Msgs == 0 {
10,382✔
757
                mset.ddloaded = true
4,966✔
758
        }
4,966✔
759

760
        // Set our stream assignment if in clustered mode.
761
        reserveResources := true
5,416✔
762
        if sa != nil {
8,845✔
763
                mset.setStreamAssignment(sa)
3,429✔
764

3,429✔
765
                // If the stream is resetting we must not double-account resources, they were already accounted for.
3,429✔
766
                js.mu.Lock()
3,429✔
767
                if sa.resetting {
3,443✔
768
                        reserveResources, sa.resetting = false, false
14✔
769
                }
14✔
770
                js.mu.Unlock()
3,429✔
771
        }
772

773
        // Setup our internal send go routine.
774
        mset.setupSendCapabilities()
5,416✔
775

5,416✔
776
        // Reserve resources if MaxBytes present.
5,416✔
777
        if reserveResources {
10,818✔
778
                mset.js.reserveStreamResources(&mset.cfg)
5,402✔
779
        }
5,402✔
780

781
        // Call directly to set leader if not in clustered mode.
782
        // This can be called though before we actually setup clustering, so check both.
783
        if singleServerMode {
7,074✔
784
                if err := mset.setLeader(true); err != nil {
1,658✔
785
                        mset.stop(true, false)
×
786
                        return nil, err
×
787
                }
×
788
        }
789

790
        // This is always true in single server mode.
791
        if mset.IsLeader() {
8,065✔
792
                // Send advisory.
2,649✔
793
                var suppress bool
2,649✔
794
                if !s.standAloneMode() && sa == nil {
2,978✔
795
                        if cfg.Replicas > 1 {
544✔
796
                                suppress = true
215✔
797
                        }
215✔
798
                } else if sa != nil {
2,982✔
799
                        suppress = sa.responded
662✔
800
                }
662✔
801
                if !suppress {
5,083✔
802
                        mset.sendCreateAdvisory()
2,434✔
803
                }
2,434✔
804
        }
805

806
        // Register with our account last.
807
        jsa.mu.Lock()
5,416✔
808
        jsa.streams[cfg.Name] = mset
5,416✔
809
        jsa.mu.Unlock()
5,416✔
810

5,416✔
811
        return mset, nil
5,416✔
812
}
813

814
// Composes the index name. Contains the stream name, subject filter, and transform destination
815
// when the stream is external we will use the api prefix as part of the index name
816
// (as the same stream name could be used in multiple JS domains)
817
func (ssi *StreamSource) composeIName() string {
630✔
818
        var iName = ssi.Name
630✔
819

630✔
820
        if ssi.External != nil {
708✔
821
                iName = iName + ":" + getHash(ssi.External.ApiPrefix)
78✔
822
        }
78✔
823

824
        source := ssi.FilterSubject
630✔
825
        destination := fwcs
630✔
826

630✔
827
        if len(ssi.SubjectTransforms) == 0 {
1,241✔
828
                // normalize filter and destination in case they are empty
611✔
829
                if source == _EMPTY_ {
1,112✔
830
                        source = fwcs
501✔
831
                }
501✔
832
                if destination == _EMPTY_ {
611✔
833
                        destination = fwcs
×
834
                }
×
835
        } else {
19✔
836
                var sources, destinations []string
19✔
837

19✔
838
                for _, tr := range ssi.SubjectTransforms {
44✔
839
                        trsrc, trdest := tr.Source, tr.Destination
25✔
840
                        if trsrc == _EMPTY_ {
25✔
841
                                trsrc = fwcs
×
842
                        }
×
843
                        if trdest == _EMPTY_ {
28✔
844
                                trdest = fwcs
3✔
845
                        }
3✔
846
                        sources = append(sources, trsrc)
25✔
847
                        destinations = append(destinations, trdest)
25✔
848
                }
849
                source = strings.Join(sources, "\f")
19✔
850
                destination = strings.Join(destinations, "\f")
19✔
851
        }
852

853
        return strings.Join([]string{iName, source, destination}, " ")
630✔
854
}
855

856
// Sets the index name.
857
func (ssi *StreamSource) setIndexName() {
122✔
858
        ssi.iname = ssi.composeIName()
122✔
859
}
122✔
860

861
func (mset *stream) streamAssignment() *streamAssignment {
11,318✔
862
        mset.mu.RLock()
11,318✔
863
        defer mset.mu.RUnlock()
11,318✔
864
        return mset.sa
11,318✔
865
}
11,318✔
866

867
func (mset *stream) setStreamAssignment(sa *streamAssignment) {
4,193✔
868
        var node RaftNode
4,193✔
869
        var peers []string
4,193✔
870

4,193✔
871
        mset.mu.RLock()
4,193✔
872
        js := mset.js
4,193✔
873
        mset.mu.RUnlock()
4,193✔
874

4,193✔
875
        if js != nil {
8,386✔
876
                js.mu.RLock()
4,193✔
877
                if sa.Group != nil {
8,386✔
878
                        node = sa.Group.node
4,193✔
879
                        peers = sa.Group.Peers
4,193✔
880
                }
4,193✔
881
                js.mu.RUnlock()
4,193✔
882
        }
883

884
        mset.mu.Lock()
4,193✔
885
        defer mset.mu.Unlock()
4,193✔
886

4,193✔
887
        mset.sa = sa
4,193✔
888
        if sa == nil {
4,193✔
889
                return
×
890
        }
×
891

892
        // Set our node.
893
        mset.node = node
4,193✔
894
        if mset.node != nil {
7,580✔
895
                mset.node.UpdateKnownPeers(peers)
3,387✔
896
        }
3,387✔
897

898
        // Setup our info sub here as well for all stream members. This is now by design.
899
        if mset.infoSub == nil {
7,949✔
900
                isubj := fmt.Sprintf(clusterStreamInfoT, mset.jsa.acc(), mset.cfg.Name)
3,756✔
901
                // Note below the way we subscribe here is so that we can send requests to ourselves.
3,756✔
902
                mset.infoSub, _ = mset.srv.systemSubscribe(isubj, _EMPTY_, false, mset.sysc, mset.handleClusterStreamInfoRequest)
3,756✔
903
        }
3,756✔
904

905
        // Trigger update chan.
906
        select {
4,193✔
907
        case mset.uch <- struct{}{}:
4,193✔
908
        default:
×
909
        }
910
}
911

912
func (mset *stream) monitorQuitC() <-chan struct{} {
3,025✔
913
        if mset == nil {
3,032✔
914
                return nil
7✔
915
        }
7✔
916
        mset.mu.RLock()
3,018✔
917
        defer mset.mu.RUnlock()
3,018✔
918
        return mset.mqch
3,018✔
919
}
920

921
func (mset *stream) updateC() <-chan struct{} {
3,022✔
922
        if mset == nil {
3,029✔
923
                return nil
7✔
924
        }
7✔
925
        mset.mu.RLock()
3,015✔
926
        defer mset.mu.RUnlock()
3,015✔
927
        return mset.uch
3,015✔
928
}
929

930
// IsLeader will return if we are the current leader.
931
func (mset *stream) IsLeader() bool {
6,973✔
932
        mset.mu.RLock()
6,973✔
933
        defer mset.mu.RUnlock()
6,973✔
934
        return mset.isLeader()
6,973✔
935
}
6,973✔
936

937
// Lock should be held.
938
func (mset *stream) isLeader() bool {
472,420✔
939
        if mset.isClustered() {
932,083✔
940
                return mset.node.Leader()
459,663✔
941
        }
459,663✔
942
        return true
12,757✔
943
}
944

945
// isLeaderNodeState should NOT be used normally, use isLeader instead.
946
// Returns whether the node thinks it is the leader, regardless of whether applies are up-to-date yet
947
// (unlike isLeader, which requires applies to be caught up).
948
// May be used to respond to clients after a leader change, when applying entries from a former leader.
949
// Lock should be held.
950
func (mset *stream) isLeaderNodeState() bool {
1,375,285✔
951
        if mset.isClustered() {
2,486,397✔
952
                return mset.node.State() == Leader
1,111,112✔
953
        }
1,111,112✔
954
        return true
264,173✔
955
}
956

957
// TODO(dlc) - Check to see if we can accept being the leader or we should step down.
958
func (mset *stream) setLeader(isLeader bool) error {
8,648✔
959
        mset.mu.Lock()
8,648✔
960
        // If we are here we have a change in leader status.
8,648✔
961
        if isLeader {
12,515✔
962
                // Make sure we are listening for sync requests.
3,867✔
963
                // TODO(dlc) - Original design was that all in sync members of the group would do DQ.
3,867✔
964
                if mset.isClustered() {
5,300✔
965
                        mset.startClusterSubs()
1,433✔
966
                }
1,433✔
967

968
                // Setup subscriptions if we were not already the leader.
969
                if err := mset.subscribeToStream(); err != nil {
3,867✔
970
                        if mset.isClustered() {
×
971
                                // Stepdown since we have an error.
×
972
                                mset.node.StepDown()
×
973
                        }
×
974
                        mset.mu.Unlock()
×
975
                        return err
×
976
                }
977
        } else {
4,781✔
978
                // cancel timer to create the source consumers if not fired yet
4,781✔
979
                if mset.sourcesConsumerSetup != nil {
4,809✔
980
                        mset.sourcesConsumerSetup.Stop()
28✔
981
                        mset.sourcesConsumerSetup = nil
28✔
982
                } else {
4,781✔
983
                        // Stop any source consumers
4,753✔
984
                        mset.stopSourceConsumers()
4,753✔
985
                }
4,753✔
986

987
                // Stop responding to sync requests.
988
                mset.stopClusterSubs()
4,781✔
989
                // Unsubscribe from direct stream.
4,781✔
990
                mset.unsubscribeToStream(false)
4,781✔
991
                // Clear catchup state
4,781✔
992
                mset.clearAllCatchupPeers()
4,781✔
993
        }
994
        mset.mu.Unlock()
8,648✔
995

8,648✔
996
        // If we are interest based make sure to check consumers.
8,648✔
997
        // This is to make sure we process any outstanding acks.
8,648✔
998
        mset.checkInterestState()
8,648✔
999

8,648✔
1000
        return nil
8,648✔
1001
}
1002

1003
// Lock should be held.
1004
func (mset *stream) startClusterSubs() {
1,471✔
1005
        if mset.syncSub == nil {
2,908✔
1006
                mset.syncSub, _ = mset.srv.systemSubscribe(mset.sa.Sync, _EMPTY_, false, mset.sysc, mset.handleClusterSyncRequest)
1,437✔
1007
        }
1,437✔
1008
}
1009

1010
// Lock should be held.
1011
func (mset *stream) stopClusterSubs() {
10,234✔
1012
        if mset.syncSub != nil {
11,670✔
1013
                mset.srv.sysUnsubscribe(mset.syncSub)
1,436✔
1014
                mset.syncSub = nil
1,436✔
1015
        }
1,436✔
1016
}
1017

1018
// account gets the account for this stream.
1019
func (mset *stream) account() *Account {
77,187✔
1020
        mset.mu.RLock()
77,187✔
1021
        jsa := mset.jsa
77,187✔
1022
        mset.mu.RUnlock()
77,187✔
1023
        if jsa == nil {
77,187✔
1024
                return nil
×
1025
        }
×
1026
        return jsa.acc()
77,187✔
1027
}
1028

1029
// Helper to determine the max msg size for this stream if file based.
1030
func (mset *stream) maxMsgSize() uint64 {
271✔
1031
        maxMsgSize := mset.cfg.MaxMsgSize
271✔
1032
        if maxMsgSize <= 0 {
537✔
1033
                // Pull from the account.
266✔
1034
                if mset.jsa != nil {
532✔
1035
                        if acc := mset.jsa.acc(); acc != nil {
532✔
1036
                                acc.mu.RLock()
266✔
1037
                                maxMsgSize = acc.mpay
266✔
1038
                                acc.mu.RUnlock()
266✔
1039
                        }
266✔
1040
                }
1041
                // If all else fails use default.
1042
                if maxMsgSize <= 0 {
532✔
1043
                        maxMsgSize = MAX_PAYLOAD_SIZE
266✔
1044
                }
266✔
1045
        }
1046
        // Now determine an estimation for the subjects etc.
1047
        maxSubject := -1
271✔
1048
        for _, subj := range mset.cfg.Subjects {
594✔
1049
                if subjectIsLiteral(subj) {
629✔
1050
                        if len(subj) > maxSubject {
556✔
1051
                                maxSubject = len(subj)
250✔
1052
                        }
250✔
1053
                }
1054
        }
1055
        if maxSubject < 0 {
292✔
1056
                const defaultMaxSubject = 256
21✔
1057
                maxSubject = defaultMaxSubject
21✔
1058
        }
21✔
1059
        // filestore will add in estimates for record headers, etc.
1060
        return fileStoreMsgSizeEstimate(maxSubject, int(maxMsgSize))
271✔
1061
}
1062

1063
// If we are file based and the file storage config was not explicitly set
1064
// we can autotune block sizes to better match. Our target will be to store 125%
1065
// of the theoretical limit. We will round up to nearest 100 bytes as well.
1066
func (mset *stream) autoTuneFileStorageBlockSize(fsCfg *FileStoreConfig) {
5,091✔
1067
        var totalEstSize uint64
5,091✔
1068

5,091✔
1069
        // MaxBytes will take precedence for now.
5,091✔
1070
        if mset.cfg.MaxBytes > 0 {
5,233✔
1071
                totalEstSize = uint64(mset.cfg.MaxBytes)
142✔
1072
        } else if mset.cfg.MaxMsgs > 0 {
5,362✔
1073
                // Determine max message size to estimate.
271✔
1074
                totalEstSize = mset.maxMsgSize() * uint64(mset.cfg.MaxMsgs)
271✔
1075
        } else if mset.cfg.MaxMsgsPer > 0 {
5,623✔
1076
                fsCfg.BlockSize = uint64(defaultKVBlockSize)
674✔
1077
                return
674✔
1078
        } else {
4,678✔
1079
                // If nothing set will let underlying filestore determine blkSize.
4,004✔
1080
                return
4,004✔
1081
        }
4,004✔
1082

1083
        blkSize := (totalEstSize / 4) + 1 // (25% overhead)
413✔
1084
        // Round up to nearest 100
413✔
1085
        if m := blkSize % 100; m != 0 {
826✔
1086
                blkSize += 100 - m
413✔
1087
        }
413✔
1088
        if blkSize <= FileStoreMinBlkSize {
454✔
1089
                blkSize = FileStoreMinBlkSize
41✔
1090
        } else if blkSize >= FileStoreMaxBlkSize {
724✔
1091
                blkSize = FileStoreMaxBlkSize
311✔
1092
        } else {
372✔
1093
                blkSize = defaultMediumBlockSize
61✔
1094
        }
61✔
1095
        fsCfg.BlockSize = uint64(blkSize)
413✔
1096
}
1097

1098
// rebuildDedupe will rebuild any dedupe structures needed after recovery of a stream.
1099
// Will be called lazily to avoid penalizing startup times.
1100
// TODO(dlc) - Might be good to know if this should be checked at all for streams with no
1101
// headers and msgId in them. Would need signaling from the storage layer.
1102
// Lock should be held.
1103
func (mset *stream) rebuildDedupe() {
7✔
1104
        if mset.ddloaded {
7✔
1105
                return
×
1106
        }
×
1107

1108
        mset.ddloaded = true
7✔
1109

7✔
1110
        // We have some messages. Lookup starting sequence by duplicate time window.
7✔
1111
        sseq := mset.store.GetSeqFromTime(time.Now().Add(-mset.cfg.Duplicates))
7✔
1112
        if sseq == 0 {
7✔
1113
                return
×
1114
        }
×
1115

1116
        var smv StoreMsg
7✔
1117
        var state StreamState
7✔
1118
        mset.store.FastState(&state)
7✔
1119

7✔
1120
        for seq := sseq; seq <= state.LastSeq; seq++ {
307,427✔
1121
                sm, err := mset.store.LoadMsg(seq, &smv)
307,420✔
1122
                if err != nil {
307,420✔
1123
                        continue
×
1124
                }
1125
                var msgId string
307,420✔
1126
                if len(sm.hdr) > 0 {
614,840✔
1127
                        if msgId = getMsgId(sm.hdr); msgId != _EMPTY_ {
614,839✔
1128
                                mset.storeMsgIdLocked(&ddentry{msgId, sm.seq, sm.ts})
307,419✔
1129
                        }
307,419✔
1130
                }
1131
                if seq == state.LastSeq {
307,427✔
1132
                        mset.lmsgId = msgId
7✔
1133
                }
7✔
1134
        }
1135
}
1136

1137
func (mset *stream) lastSeqAndCLFS() (uint64, uint64) {
1,185,271✔
1138
        return mset.lastSeq(), mset.getCLFS()
1,185,271✔
1139
}
1,185,271✔
1140

1141
func (mset *stream) getCLFS() uint64 {
2,690,406✔
1142
        if mset == nil {
2,690,434✔
1143
                return 0
28✔
1144
        }
28✔
1145
        mset.clMu.Lock()
2,690,378✔
1146
        defer mset.clMu.Unlock()
2,690,378✔
1147
        return mset.clfs
2,690,378✔
1148
}
1149

1150
func (mset *stream) setCLFS(clfs uint64) {
844✔
1151
        mset.clMu.Lock()
844✔
1152
        mset.clfs = clfs
844✔
1153
        mset.clMu.Unlock()
844✔
1154
}
844✔
1155

1156
func (mset *stream) lastSeq() uint64 {
1,185,707✔
1157
        mset.mu.RLock()
1,185,707✔
1158
        defer mset.mu.RUnlock()
1,185,707✔
1159
        return mset.lseq
1,185,707✔
1160
}
1,185,707✔
1161

1162
// Set last seq.
1163
// Write lock should be held.
1164
func (mset *stream) setLastSeq(lseq uint64) {
273,401✔
1165
        mset.lseq = lseq
273,401✔
1166
}
273,401✔
1167

1168
func (mset *stream) sendCreateAdvisory() {
3,093✔
1169
        mset.mu.RLock()
3,093✔
1170
        name := mset.cfg.Name
3,093✔
1171
        template := mset.cfg.Template
3,093✔
1172
        outq := mset.outq
3,093✔
1173
        srv := mset.srv
3,093✔
1174
        mset.mu.RUnlock()
3,093✔
1175

3,093✔
1176
        if outq == nil {
3,093✔
1177
                return
×
1178
        }
×
1179

1180
        // finally send an event that this stream was created
1181
        m := JSStreamActionAdvisory{
3,093✔
1182
                TypedEvent: TypedEvent{
3,093✔
1183
                        Type: JSStreamActionAdvisoryType,
3,093✔
1184
                        ID:   nuid.Next(),
3,093✔
1185
                        Time: time.Now().UTC(),
3,093✔
1186
                },
3,093✔
1187
                Stream:   name,
3,093✔
1188
                Action:   CreateEvent,
3,093✔
1189
                Template: template,
3,093✔
1190
                Domain:   srv.getOpts().JetStreamDomain,
3,093✔
1191
        }
3,093✔
1192

3,093✔
1193
        j, err := json.Marshal(m)
3,093✔
1194
        if err != nil {
3,093✔
1195
                return
×
1196
        }
×
1197

1198
        subj := JSAdvisoryStreamCreatedPre + "." + name
3,093✔
1199
        outq.sendMsg(subj, j)
3,093✔
1200
}
1201

1202
func (mset *stream) sendDeleteAdvisoryLocked() {
406✔
1203
        if mset.outq == nil {
406✔
1204
                return
×
1205
        }
×
1206

1207
        m := JSStreamActionAdvisory{
406✔
1208
                TypedEvent: TypedEvent{
406✔
1209
                        Type: JSStreamActionAdvisoryType,
406✔
1210
                        ID:   nuid.Next(),
406✔
1211
                        Time: time.Now().UTC(),
406✔
1212
                },
406✔
1213
                Stream:   mset.cfg.Name,
406✔
1214
                Action:   DeleteEvent,
406✔
1215
                Template: mset.cfg.Template,
406✔
1216
                Domain:   mset.srv.getOpts().JetStreamDomain,
406✔
1217
        }
406✔
1218

406✔
1219
        j, err := json.Marshal(m)
406✔
1220
        if err == nil {
812✔
1221
                subj := JSAdvisoryStreamDeletedPre + "." + mset.cfg.Name
406✔
1222
                mset.outq.sendMsg(subj, j)
406✔
1223
        }
406✔
1224
}
1225

1226
func (mset *stream) sendUpdateAdvisoryLocked() {
205✔
1227
        if mset.outq == nil {
205✔
1228
                return
×
1229
        }
×
1230

1231
        m := JSStreamActionAdvisory{
205✔
1232
                TypedEvent: TypedEvent{
205✔
1233
                        Type: JSStreamActionAdvisoryType,
205✔
1234
                        ID:   nuid.Next(),
205✔
1235
                        Time: time.Now().UTC(),
205✔
1236
                },
205✔
1237
                Stream: mset.cfg.Name,
205✔
1238
                Action: ModifyEvent,
205✔
1239
                Domain: mset.srv.getOpts().JetStreamDomain,
205✔
1240
        }
205✔
1241

205✔
1242
        j, err := json.Marshal(m)
205✔
1243
        if err == nil {
410✔
1244
                subj := JSAdvisoryStreamUpdatedPre + "." + mset.cfg.Name
205✔
1245
                mset.outq.sendMsg(subj, j)
205✔
1246
        }
205✔
1247
}
1248

1249
// Created returns created time.
1250
func (mset *stream) createdTime() time.Time {
17,533✔
1251
        mset.mu.RLock()
17,533✔
1252
        created := mset.created
17,533✔
1253
        mset.mu.RUnlock()
17,533✔
1254
        return created
17,533✔
1255
}
17,533✔
1256

1257
// Internal to allow creation time to be restored.
1258
func (mset *stream) setCreatedTime(created time.Time) {
4,374✔
1259
        mset.mu.Lock()
4,374✔
1260
        mset.created = created
4,374✔
1261
        mset.mu.Unlock()
4,374✔
1262
}
4,374✔
1263

1264
// subjectsOverlap to see if these subjects overlap with existing subjects.
1265
// Use only for non-clustered JetStream
1266
// RLock minimum should be held.
1267
func (jsa *jsAccount) subjectsOverlap(subjects []string, self *stream) bool {
5,917✔
1268
        for _, mset := range jsa.streams {
61,885✔
1269
                if self != nil && mset == self {
56,444✔
1270
                        continue
476✔
1271
                }
1272
                for _, subj := range mset.cfg.Subjects {
111,136✔
1273
                        for _, tsubj := range subjects {
111,720✔
1274
                                if SubjectsCollide(tsubj, subj) {
56,100✔
1275
                                        return true
24✔
1276
                                }
24✔
1277
                        }
1278
                }
1279
        }
1280
        return false
5,893✔
1281
}
1282

1283
// StreamDefaultDuplicatesWindow default duplicates window.
1284
const StreamDefaultDuplicatesWindow = 2 * time.Minute
1285

1286
func (s *Server) checkStreamCfg(config *StreamConfig, acc *Account, pedantic bool) (StreamConfig, *ApiError) {
7,982✔
1287
        lim := &s.getOpts().JetStreamLimits
7,982✔
1288

7,982✔
1289
        if config == nil {
7,982✔
1290
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration invalid"))
×
1291
        }
×
1292
        if !isValidName(config.Name) {
7,989✔
1293
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream name is required and can not contain '.', '*', '>'"))
7✔
1294
        }
7✔
1295
        if len(config.Name) > JSMaxNameLen {
7,975✔
1296
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream name is too long, maximum allowed is %d", JSMaxNameLen))
×
1297
        }
×
1298
        if len(config.Description) > JSMaxDescriptionLen {
7,976✔
1299
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream description is too long, maximum allowed is %d", JSMaxDescriptionLen))
1✔
1300
        }
1✔
1301

1302
        var metadataLen int
7,974✔
1303
        for k, v := range config.Metadata {
15,315✔
1304
                metadataLen += len(k) + len(v)
7,341✔
1305
        }
7,341✔
1306
        if metadataLen > JSMaxMetadataLen {
7,975✔
1307
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream metadata exceeds maximum size of %d bytes", JSMaxMetadataLen))
1✔
1308
        }
1✔
1309

1310
        cfg := *config
7,973✔
1311

7,973✔
1312
        // Make file the default.
7,973✔
1313
        if cfg.Storage == 0 {
8,041✔
1314
                cfg.Storage = FileStorage
68✔
1315
        }
68✔
1316
        if cfg.Replicas == 0 {
8,983✔
1317
                cfg.Replicas = 1
1,010✔
1318
        }
1,010✔
1319
        if cfg.Replicas > StreamMaxReplicas {
7,978✔
1320
                return cfg, NewJSStreamInvalidConfigError(fmt.Errorf("maximum replicas is %d", StreamMaxReplicas))
5✔
1321
        }
5✔
1322
        if cfg.Replicas < 0 {
7,972✔
1323
                return cfg, NewJSReplicasCountCannotBeNegativeError()
4✔
1324
        }
4✔
1325
        if cfg.MaxMsgs == 0 {
11,015✔
1326
                cfg.MaxMsgs = -1
3,051✔
1327
        }
3,051✔
1328
        if cfg.MaxMsgsPer == 0 {
10,579✔
1329
                cfg.MaxMsgsPer = -1
2,615✔
1330
        }
2,615✔
1331
        if cfg.MaxBytes == 0 {
10,947✔
1332
                cfg.MaxBytes = -1
2,983✔
1333
        }
2,983✔
1334
        if cfg.MaxMsgSize == 0 {
11,069✔
1335
                cfg.MaxMsgSize = -1
3,105✔
1336
        }
3,105✔
1337
        if cfg.MaxConsumers == 0 {
11,078✔
1338
                cfg.MaxConsumers = -1
3,114✔
1339
        }
3,114✔
1340
        if cfg.Duplicates == 0 && cfg.Mirror == nil {
10,993✔
1341
                maxWindow := StreamDefaultDuplicatesWindow
3,029✔
1342
                if lim.Duplicates > 0 && maxWindow > lim.Duplicates {
3,033✔
1343
                        if pedantic {
4✔
1344
                                return StreamConfig{}, NewJSPedanticError(fmt.Errorf("pedantic mode: duplicate window limits are higher than current limits"))
×
1345
                        }
×
1346
                        maxWindow = lim.Duplicates
4✔
1347
                }
1348
                if cfg.MaxAge != 0 && cfg.MaxAge < maxWindow {
3,092✔
1349
                        if pedantic {
63✔
1350
                                return StreamConfig{}, NewJSPedanticError(fmt.Errorf("pedantic mode: duplicate window cannot be bigger than max age"))
×
1351
                        }
×
1352
                        cfg.Duplicates = cfg.MaxAge
63✔
1353
                } else {
2,966✔
1354
                        cfg.Duplicates = maxWindow
2,966✔
1355
                }
2,966✔
1356
        }
1357
        if cfg.MaxAge > 0 && cfg.MaxAge < 100*time.Millisecond {
7,964✔
1358
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("max age needs to be >= 100ms"))
×
1359
        }
×
1360
        if cfg.Duplicates < 0 {
7,966✔
1361
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicates window can not be negative"))
2✔
1362
        }
2✔
1363
        // Check that duplicates is not larger then age if set.
1364
        if cfg.MaxAge != 0 && cfg.Duplicates > cfg.MaxAge {
7,965✔
1365
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicates window can not be larger then max age"))
3✔
1366
        }
3✔
1367
        if lim.Duplicates > 0 && cfg.Duplicates > lim.Duplicates {
7,968✔
1368
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicates window can not be larger then server limit of %v",
9✔
1369
                        lim.Duplicates.String()))
9✔
1370
        }
9✔
1371
        if cfg.Duplicates > 0 && cfg.Duplicates < 100*time.Millisecond {
7,950✔
1372
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicates window needs to be >= 100ms"))
×
1373
        }
×
1374

1375
        if cfg.DenyPurge && cfg.AllowRollup {
7,952✔
1376
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("roll-ups require the purge permission"))
2✔
1377
        }
2✔
1378

1379
        // Check for new discard new per subject, we require the discard policy to also be new.
1380
        if cfg.DiscardNewPer {
8,188✔
1381
                if cfg.Discard != DiscardNew {
244✔
1382
                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("discard new per subject requires discard new policy to be set"))
4✔
1383
                }
4✔
1384
                if cfg.MaxMsgsPer <= 0 {
240✔
1385
                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("discard new per subject requires max msgs per subject > 0"))
4✔
1386
                }
4✔
1387
        }
1388

1389
        if cfg.SubjectDeleteMarkerTTL > 0 {
8,093✔
1390
                if cfg.SubjectDeleteMarkerTTL < time.Second {
154✔
1391
                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete marker TTL must be at least 1 second"))
1✔
1392
                }
1✔
1393
                if !cfg.AllowMsgTTL {
174✔
1394
                        if pedantic {
23✔
1395
                                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete marker cannot be set if message TTLs are disabled"))
1✔
1396
                        }
1✔
1397
                        cfg.AllowMsgTTL = true
21✔
1398
                }
1399
                if !cfg.AllowRollup {
189✔
1400
                        if pedantic {
39✔
1401
                                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete marker cannot be set if roll-ups are disabled"))
1✔
1402
                        }
1✔
1403
                        cfg.AllowRollup, cfg.DenyPurge = true, false
37✔
1404
                }
1405
        } else if cfg.SubjectDeleteMarkerTTL < 0 {
7,788✔
1406
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete marker TTL must not be negative"))
1✔
1407
        }
1✔
1408

1409
        getStream := func(streamName string) (bool, StreamConfig) {
8,708✔
1410
                var exists bool
772✔
1411
                var cfg StreamConfig
772✔
1412
                if s.JetStreamIsClustered() {
1,328✔
1413
                        if js, _ := s.getJetStreamCluster(); js != nil {
1,112✔
1414
                                js.mu.RLock()
556✔
1415
                                if sa := js.streamAssignment(acc.Name, streamName); sa != nil {
1,061✔
1416
                                        cfg = *sa.Config.clone()
505✔
1417
                                        exists = true
505✔
1418
                                }
505✔
1419
                                js.mu.RUnlock()
556✔
1420
                        }
1421
                } else if mset, err := acc.lookupStream(streamName); err == nil {
332✔
1422
                        cfg = mset.cfg
116✔
1423
                        exists = true
116✔
1424
                }
116✔
1425
                return exists, cfg
772✔
1426
        }
1427

1428
        hasStream := func(streamName string) (bool, int32, []string) {
8,256✔
1429
                exists, cfg := getStream(streamName)
320✔
1430
                return exists, cfg.MaxMsgSize, cfg.Subjects
320✔
1431
        }
320✔
1432

1433
        var streamSubs []string
7,936✔
1434
        var deliveryPrefixes []string
7,936✔
1435
        var apiPrefixes []string
7,936✔
1436

7,936✔
1437
        // Do some pre-checking for mirror config to avoid cycles in clustered mode.
7,936✔
1438
        if cfg.Mirror != nil {
8,063✔
1439
                if cfg.FirstSeq > 0 {
128✔
1440
                        return StreamConfig{}, NewJSMirrorWithFirstSeqError()
1✔
1441
                }
1✔
1442
                if len(cfg.Subjects) > 0 {
128✔
1443
                        return StreamConfig{}, NewJSMirrorWithSubjectsError()
2✔
1444
                }
2✔
1445
                if len(cfg.Sources) > 0 {
124✔
1446
                        return StreamConfig{}, NewJSMirrorWithSourcesError()
×
1447
                }
×
1448
                if cfg.Mirror.FilterSubject != _EMPTY_ && len(cfg.Mirror.SubjectTransforms) != 0 {
125✔
1449
                        return StreamConfig{}, NewJSMirrorMultipleFiltersNotAllowedError()
1✔
1450
                }
1✔
1451
                if cfg.SubjectDeleteMarkerTTL > 0 {
124✔
1452
                        // Delete markers cannot be configured on a mirror as it would result in new
1✔
1453
                        // tombstones which would use up sequence numbers, diverging from the origin
1✔
1454
                        // stream.
1✔
1455
                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete markers forbidden on mirrors"))
1✔
1456
                }
1✔
1457
                // Check subject filters overlap.
1458
                for outer, tr := range cfg.Mirror.SubjectTransforms {
135✔
1459
                        if tr.Source != _EMPTY_ && !IsValidSubject(tr.Source) {
15✔
1460
                                return StreamConfig{}, NewJSMirrorInvalidSubjectFilterError(fmt.Errorf("%w %s", ErrBadSubject, tr.Source))
2✔
1461
                        }
2✔
1462

1463
                        err := ValidateMapping(tr.Source, tr.Destination)
11✔
1464
                        if err != nil {
13✔
1465
                                return StreamConfig{}, NewJSMirrorInvalidTransformDestinationError(err)
2✔
1466
                        }
2✔
1467

1468
                        for inner, innertr := range cfg.Mirror.SubjectTransforms {
22✔
1469
                                if inner != outer && SubjectsCollide(tr.Source, innertr.Source) {
15✔
1470
                                        return StreamConfig{}, NewJSMirrorOverlappingSubjectFiltersError()
2✔
1471
                                }
2✔
1472
                        }
1473
                }
1474
                // Do not perform checks if External is provided, as it could lead to
1475
                // checking against itself (if sourced stream name is the same on different JetStream)
1476
                if cfg.Mirror.External == nil {
213✔
1477
                        if !isValidName(cfg.Mirror.Name) {
97✔
1478
                                return StreamConfig{}, NewJSMirrorInvalidStreamNameError()
×
1479
                        }
×
1480
                        // We do not require other stream to exist anymore, but if we can see it check payloads.
1481
                        exists, maxMsgSize, subs := hasStream(cfg.Mirror.Name)
97✔
1482
                        if len(subs) > 0 {
171✔
1483
                                streamSubs = append(streamSubs, subs...)
74✔
1484
                        }
74✔
1485
                        if exists {
175✔
1486
                                if cfg.MaxMsgSize > 0 && maxMsgSize > 0 && cfg.MaxMsgSize < maxMsgSize {
78✔
1487
                                        return StreamConfig{}, NewJSMirrorMaxMessageSizeTooBigError()
×
1488
                                }
×
1489
                        }
1490
                        // Determine if we are inheriting direct gets.
1491
                        if exists, ocfg := getStream(cfg.Mirror.Name); exists {
175✔
1492
                                if pedantic && cfg.MirrorDirect != ocfg.AllowDirect {
78✔
1493
                                        return StreamConfig{}, NewJSPedanticError(fmt.Errorf("origin stream has direct get set, mirror has it disabled"))
×
1494
                                }
×
1495
                                cfg.MirrorDirect = ocfg.AllowDirect
78✔
1496
                        } else if js := s.getJetStream(); js != nil && js.isClustered() {
25✔
1497
                                // Could not find it here. If we are clustered we can look it up.
6✔
1498
                                js.mu.RLock()
6✔
1499
                                if cc := js.cluster; cc != nil {
12✔
1500
                                        if as := cc.streams[acc.Name]; as != nil {
12✔
1501
                                                if sa := as[cfg.Mirror.Name]; sa != nil {
6✔
1502
                                                        if pedantic && cfg.MirrorDirect != sa.Config.AllowDirect {
×
1503
                                                                js.mu.RUnlock()
×
1504
                                                                return StreamConfig{}, NewJSPedanticError(fmt.Errorf("origin stream has direct get set, mirror has it disabled"))
×
1505
                                                        }
×
1506
                                                        cfg.MirrorDirect = sa.Config.AllowDirect
×
1507
                                                }
1508
                                        }
1509
                                }
1510
                                js.mu.RUnlock()
6✔
1511
                        }
1512
                } else {
19✔
1513
                        if cfg.Mirror.External.DeliverPrefix != _EMPTY_ {
30✔
1514
                                deliveryPrefixes = append(deliveryPrefixes, cfg.Mirror.External.DeliverPrefix)
11✔
1515
                        }
11✔
1516

1517
                        if cfg.Mirror.External.ApiPrefix != _EMPTY_ {
38✔
1518
                                apiPrefixes = append(apiPrefixes, cfg.Mirror.External.ApiPrefix)
19✔
1519
                        }
19✔
1520
                }
1521
        }
1522

1523
        // check for duplicates
1524
        var iNames = make(map[string]struct{})
7,925✔
1525
        for _, src := range cfg.Sources {
8,180✔
1526
                if !isValidName(src.Name) {
256✔
1527
                        return StreamConfig{}, NewJSSourceInvalidStreamNameError()
1✔
1528
                }
1✔
1529
                if _, ok := iNames[src.composeIName()]; !ok {
508✔
1530
                        iNames[src.composeIName()] = struct{}{}
254✔
1531
                } else {
254✔
1532
                        return StreamConfig{}, NewJSSourceDuplicateDetectedError()
×
1533
                }
×
1534
                // Do not perform checks if External is provided, as it could lead to
1535
                // checking against itself (if sourced stream name is the same on different JetStream)
1536
                if src.External == nil {
477✔
1537
                        exists, maxMsgSize, subs := hasStream(src.Name)
223✔
1538
                        if len(subs) > 0 {
399✔
1539
                                streamSubs = append(streamSubs, subs...)
176✔
1540
                        }
176✔
1541
                        if exists {
399✔
1542
                                if cfg.MaxMsgSize > 0 && maxMsgSize > 0 && cfg.MaxMsgSize < maxMsgSize {
176✔
1543
                                        return StreamConfig{}, NewJSSourceMaxMessageSizeTooBigError()
×
1544
                                }
×
1545
                        }
1546

1547
                        if src.FilterSubject != _EMPTY_ && len(src.SubjectTransforms) != 0 {
223✔
1548
                                return StreamConfig{}, NewJSSourceMultipleFiltersNotAllowedError()
×
1549
                        }
×
1550

1551
                        for _, tr := range src.SubjectTransforms {
232✔
1552
                                if tr.Source != _EMPTY_ && !IsValidSubject(tr.Source) {
10✔
1553
                                        return StreamConfig{}, NewJSSourceInvalidSubjectFilterError(fmt.Errorf("%w %s", ErrBadSubject, tr.Source))
1✔
1554
                                }
1✔
1555

1556
                                err := ValidateMapping(tr.Source, tr.Destination)
8✔
1557
                                if err != nil {
9✔
1558
                                        return StreamConfig{}, NewJSSourceInvalidTransformDestinationError(err)
1✔
1559
                                }
1✔
1560
                        }
1561

1562
                        // Check subject filters overlap.
1563
                        for outer, tr := range src.SubjectTransforms {
228✔
1564
                                for inner, innertr := range src.SubjectTransforms {
18✔
1565
                                        if inner != outer && subjectIsSubsetMatch(tr.Source, innertr.Source) {
11✔
1566
                                                return StreamConfig{}, NewJSSourceOverlappingSubjectFiltersError()
×
1567
                                        }
×
1568
                                }
1569
                        }
1570
                        continue
221✔
1571
                } else {
31✔
1572
                        if src.External.DeliverPrefix != _EMPTY_ {
36✔
1573
                                deliveryPrefixes = append(deliveryPrefixes, src.External.DeliverPrefix)
5✔
1574
                        }
5✔
1575
                        if src.External.ApiPrefix != _EMPTY_ {
62✔
1576
                                apiPrefixes = append(apiPrefixes, src.External.ApiPrefix)
31✔
1577
                        }
31✔
1578
                }
1579
        }
1580

1581
        // check prefix overlap with subjects
1582
        for _, pfx := range deliveryPrefixes {
7,938✔
1583
                if !IsValidPublishSubject(pfx) {
16✔
1584
                        return StreamConfig{}, NewJSStreamInvalidExternalDeliverySubjError(pfx)
×
1585
                }
×
1586
                for _, sub := range streamSubs {
16✔
1587
                        if SubjectsCollide(sub, fmt.Sprintf("%s.%s", pfx, sub)) {
×
1588
                                return StreamConfig{}, NewJSStreamExternalDelPrefixOverlapsError(pfx, sub)
×
1589
                        }
×
1590
                }
1591
        }
1592
        // check if api prefixes overlap
1593
        for _, apiPfx := range apiPrefixes {
7,972✔
1594
                if !IsValidPublishSubject(apiPfx) {
50✔
1595
                        return StreamConfig{}, NewJSStreamInvalidConfigError(
×
1596
                                fmt.Errorf("stream external api prefix %q must be a valid subject without wildcards", apiPfx))
×
1597
                }
×
1598
                if SubjectsCollide(apiPfx, JSApiPrefix) {
52✔
1599
                        return StreamConfig{}, NewJSStreamExternalApiOverlapError(apiPfx, JSApiPrefix)
2✔
1600
                }
2✔
1601
        }
1602

1603
        // cycle check for source cycle
1604
        toVisit := []*StreamConfig{&cfg}
7,920✔
1605
        visited := make(map[string]struct{})
7,920✔
1606
        overlaps := func(subjects []string, filter string) bool {
7,925✔
1607
                if filter == _EMPTY_ {
7✔
1608
                        return true
2✔
1609
                }
2✔
1610
                for _, subject := range subjects {
6✔
1611
                        if SubjectsCollide(subject, filter) {
3✔
1612
                                return true
×
1613
                        }
×
1614
                }
1615
                return false
3✔
1616
        }
1617

1618
        for len(toVisit) > 0 {
16,129✔
1619
                cfg := toVisit[0]
8,209✔
1620
                toVisit = toVisit[1:]
8,209✔
1621
                visited[cfg.Name] = struct{}{}
8,209✔
1622
                for _, src := range cfg.Sources {
8,501✔
1623
                        if src.External != nil {
322✔
1624
                                continue
30✔
1625
                        }
1626
                        // We can detect a cycle between streams, but let's double check that the
1627
                        // subjects actually form a cycle.
1628
                        if _, ok := visited[src.Name]; ok {
267✔
1629
                                if overlaps(cfg.Subjects, src.FilterSubject) {
7✔
1630
                                        return StreamConfig{}, NewJSStreamInvalidConfigError(errors.New("detected cycle"))
2✔
1631
                                }
2✔
1632
                        } else if exists, cfg := getStream(src.Name); exists {
467✔
1633
                                toVisit = append(toVisit, &cfg)
210✔
1634
                        }
210✔
1635
                }
1636
                // Avoid cycles hiding behind mirrors
1637
                if m := cfg.Mirror; m != nil {
8,323✔
1638
                        if m.External == nil {
214✔
1639
                                if _, ok := visited[m.Name]; ok {
98✔
1640
                                        return StreamConfig{}, NewJSStreamInvalidConfigError(errors.New("detected cycle"))
×
1641
                                }
×
1642
                                if exists, cfg := getStream(m.Name); exists {
177✔
1643
                                        toVisit = append(toVisit, &cfg)
79✔
1644
                                }
79✔
1645
                        }
1646
                }
1647
        }
1648

1649
        if len(cfg.Subjects) == 0 {
8,718✔
1650
                if cfg.Mirror == nil && len(cfg.Sources) == 0 {
1,357✔
1651
                        cfg.Subjects = append(cfg.Subjects, cfg.Name)
557✔
1652
                }
557✔
1653
        } else {
7,118✔
1654
                if cfg.Mirror != nil {
7,118✔
1655
                        return StreamConfig{}, NewJSMirrorWithSubjectsError()
×
1656
                }
×
1657

1658
                // Check for literal duplication of subject interest in config
1659
                // and no overlap with any JS or SYS API subject space.
1660
                dset := make(map[string]struct{}, len(cfg.Subjects))
7,118✔
1661
                for _, subj := range cfg.Subjects {
14,860✔
1662
                        // Make sure the subject is valid. Check this first.
7,742✔
1663
                        if !IsValidSubject(subj) {
7,749✔
1664
                                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("invalid subject"))
7✔
1665
                        }
7✔
1666
                        if _, ok := dset[subj]; ok {
7,735✔
1667
                                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicate subjects detected"))
×
1668
                        }
×
1669
                        // Check for trying to capture everything.
1670
                        if subj == fwcs {
7,743✔
1671
                                if !cfg.NoAck {
11✔
1672
                                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("capturing all subjects requires no-ack to be true"))
3✔
1673
                                }
3✔
1674
                                // Capturing everything also will require R1.
1675
                                if cfg.Replicas != 1 {
6✔
1676
                                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("capturing all subjects requires replicas of 1"))
1✔
1677
                                }
1✔
1678
                        }
1679
                        // Also check to make sure we do not overlap with our $JS API subjects.
1680
                        if !cfg.NoAck {
15,451✔
1681
                                for _, namespace := range []string{"$JS.>", "$JSC.>", "$NRG.>"} {
30,865✔
1682
                                        if SubjectsCollide(subj, namespace) {
23,155✔
1683
                                                // We allow an exception for $JS.EVENT.> since these could have been created in the past.
10✔
1684
                                                if !subjectIsSubsetMatch(subj, "$JS.EVENT.>") {
18✔
1685
                                                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subjects that overlap with jetstream api require no-ack to be true"))
8✔
1686
                                                }
8✔
1687
                                        }
1688
                                }
1689
                                if SubjectsCollide(subj, "$SYS.>") {
7,716✔
1690
                                        if !subjectIsSubsetMatch(subj, "$SYS.ACCOUNT.>") {
6✔
1691
                                                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subjects that overlap with system api require no-ack to be true"))
2✔
1692
                                        }
2✔
1693
                                }
1694
                        }
1695
                        // Mark for duplicate check.
1696
                        dset[subj] = struct{}{}
7,721✔
1697
                }
1698
        }
1699

1700
        if len(cfg.Subjects) == 0 && len(cfg.Sources) == 0 && cfg.Mirror == nil {
7,897✔
1701
                return StreamConfig{}, NewJSStreamInvalidConfigError(
×
1702
                        fmt.Errorf("stream needs at least one configured subject or be a source/mirror"))
×
1703
        }
×
1704

1705
        // Check for MaxBytes required and it's limit
1706
        if required, limit := acc.maxBytesLimits(&cfg); required && cfg.MaxBytes <= 0 {
7,899✔
1707
                return StreamConfig{}, NewJSStreamMaxBytesRequiredError()
2✔
1708
        } else if limit > 0 && cfg.MaxBytes > limit {
7,899✔
1709
                return StreamConfig{}, NewJSStreamMaxStreamBytesExceededError()
2✔
1710
        }
2✔
1711

1712
        // Now check if we have multiple subjects they we do not overlap ourselves
1713
        // which would cause duplicate entries (assuming no MsgID).
1714
        if len(cfg.Subjects) > 1 {
8,305✔
1715
                for _, subj := range cfg.Subjects {
1,445✔
1716
                        for _, tsubj := range cfg.Subjects {
4,005✔
1717
                                if tsubj != subj && SubjectsCollide(tsubj, subj) {
2,975✔
1718
                                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject %q overlaps with %q", subj, tsubj))
3✔
1719
                                }
3✔
1720
                        }
1721
                }
1722
        }
1723

1724
        // If we have a republish directive check if we can create a transform here.
1725
        if cfg.RePublish != nil {
7,911✔
1726
                // Check to make sure source is a valid subset of the subjects we have.
21✔
1727
                // Also make sure it does not form a cycle.
21✔
1728
                // Empty same as all.
21✔
1729
                if cfg.RePublish.Source == _EMPTY_ {
23✔
1730
                        if pedantic {
2✔
1731
                                return StreamConfig{}, NewJSPedanticError(fmt.Errorf("pedantic mode: republish source can not be empty"))
×
1732
                        }
×
1733
                        cfg.RePublish.Source = fwcs
2✔
1734
                }
1735
                var formsCycle bool
21✔
1736
                for _, subj := range cfg.Subjects {
58✔
1737
                        if SubjectsCollide(cfg.RePublish.Destination, subj) {
40✔
1738
                                formsCycle = true
3✔
1739
                                break
3✔
1740
                        }
1741
                }
1742
                if formsCycle {
24✔
1743
                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration for republish destination forms a cycle"))
3✔
1744
                }
3✔
1745
                if _, err := NewSubjectTransform(cfg.RePublish.Source, cfg.RePublish.Destination); err != nil {
18✔
1746
                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration for republish with transform from '%s' to '%s' not valid", cfg.RePublish.Source, cfg.RePublish.Destination))
×
1747
                }
×
1748
        }
1749

1750
        // Check the subject transform if any
1751
        if cfg.SubjectTransform != nil {
7,896✔
1752
                if cfg.SubjectTransform.Source != _EMPTY_ && !IsValidSubject(cfg.SubjectTransform.Source) {
10✔
1753
                        return StreamConfig{}, NewJSStreamTransformInvalidSourceError(fmt.Errorf("%w %s", ErrBadSubject, cfg.SubjectTransform.Source))
1✔
1754
                }
1✔
1755

1756
                err := ValidateMapping(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination)
8✔
1757
                if err != nil {
9✔
1758
                        return StreamConfig{}, NewJSStreamTransformInvalidDestinationError(err)
1✔
1759
                }
1✔
1760
        }
1761

1762
        // For now don't allow preferred server in placement.
1763
        if cfg.Placement != nil && cfg.Placement.Preferred != _EMPTY_ {
7,885✔
1764
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("preferred server not permitted in placement"))
×
1765
        }
×
1766

1767
        return cfg, nil
7,885✔
1768
}
1769

1770
// Config returns the stream's configuration.
1771
func (mset *stream) config() StreamConfig {
41,111✔
1772
        mset.cfgMu.RLock()
41,111✔
1773
        defer mset.cfgMu.RUnlock()
41,111✔
1774
        return mset.cfg
41,111✔
1775
}
41,111✔
1776

1777
func (mset *stream) fileStoreConfig() (FileStoreConfig, error) {
5✔
1778
        mset.mu.Lock()
5✔
1779
        defer mset.mu.Unlock()
5✔
1780
        fs, ok := mset.store.(*fileStore)
5✔
1781
        if !ok {
5✔
1782
                return FileStoreConfig{}, ErrStoreWrongType
×
1783
        }
×
1784
        return fs.fileStoreConfig(), nil
5✔
1785
}
1786

1787
// Do not hold jsAccount or jetStream lock
1788
func (jsa *jsAccount) configUpdateCheck(old, new *StreamConfig, s *Server, pedantic bool) (*StreamConfig, error) {
657✔
1789
        cfg, apiErr := s.checkStreamCfg(new, jsa.acc(), pedantic)
657✔
1790
        if apiErr != nil {
661✔
1791
                return nil, apiErr
4✔
1792
        }
4✔
1793

1794
        // Name must match.
1795
        if cfg.Name != old.Name {
655✔
1796
                return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration name must match original"))
2✔
1797
        }
2✔
1798
        // Can't change MaxConsumers for now.
1799
        if cfg.MaxConsumers != old.MaxConsumers {
653✔
1800
                return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not change MaxConsumers"))
2✔
1801
        }
2✔
1802
        // Can't change storage types.
1803
        if cfg.Storage != old.Storage {
651✔
1804
                return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not change storage type"))
2✔
1805
        }
2✔
1806
        // Can only change retention from limits to interest or back, not to/from work queue for now.
1807
        if cfg.Retention != old.Retention {
662✔
1808
                if old.Retention == WorkQueuePolicy || cfg.Retention == WorkQueuePolicy {
17✔
1809
                        return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not change retention policy to/from workqueue"))
2✔
1810
                }
2✔
1811
        }
1812
        // Can not have a template owner for now.
1813
        if old.Template != _EMPTY_ {
645✔
1814
                return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update not allowed on template owned stream"))
×
1815
        }
×
1816
        if cfg.Template != _EMPTY_ {
647✔
1817
                return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not be owned by a template"))
2✔
1818
        }
2✔
1819
        // Can not change from true to false.
1820
        if !cfg.Sealed && old.Sealed {
645✔
1821
                return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not unseal a sealed stream"))
2✔
1822
        }
2✔
1823
        // Can not change from true to false.
1824
        if !cfg.DenyDelete && old.DenyDelete {
642✔
1825
                return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not cancel deny message deletes"))
1✔
1826
        }
1✔
1827
        // Can not change from true to false.
1828
        if !cfg.DenyPurge && old.DenyPurge {
640✔
1829
                return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not cancel deny purge"))
×
1830
        }
×
1831
        // Check for mirror changes which are not allowed.
1832
        if !reflect.DeepEqual(cfg.Mirror, old.Mirror) {
642✔
1833
                return nil, NewJSStreamMirrorNotUpdatableError()
2✔
1834
        }
2✔
1835

1836
        // Check on new discard new per subject.
1837
        if cfg.DiscardNewPer {
638✔
1838
                if cfg.Discard != DiscardNew {
×
1839
                        return nil, NewJSStreamInvalidConfigError(fmt.Errorf("discard new per subject requires discard new policy to be set"))
×
1840
                }
×
1841
                if cfg.MaxMsgsPer <= 0 {
×
1842
                        return nil, NewJSStreamInvalidConfigError(fmt.Errorf("discard new per subject requires max msgs per subject > 0"))
×
1843
                }
×
1844
        }
1845

1846
        // Check on the allowed message TTL status.
1847
        if old.AllowMsgTTL && !cfg.AllowMsgTTL {
640✔
1848
                return nil, NewJSStreamInvalidConfigError(fmt.Errorf("message TTL status can not be disabled"))
2✔
1849
        }
2✔
1850

1851
        // Do some adjustments for being sealed.
1852
        // Pedantic mode will allow those changes to be made, as they are deterministic and important to get a sealed stream.
1853
        if cfg.Sealed {
655✔
1854
                cfg.MaxAge = 0
19✔
1855
                cfg.Discard = DiscardNew
19✔
1856
                cfg.DenyDelete, cfg.DenyPurge = true, true
19✔
1857
                cfg.AllowRollup = false
19✔
1858
        }
19✔
1859

1860
        // Check limits. We need some extra handling to allow updating MaxBytes.
1861

1862
        // First, let's calculate the difference between the new and old MaxBytes.
1863
        maxBytesDiff := cfg.MaxBytes - old.MaxBytes
636✔
1864
        if maxBytesDiff < 0 {
654✔
1865
                // If we're updating to a lower MaxBytes (maxBytesDiff is negative),
18✔
1866
                // then set to zero so checkBytesLimits doesn't set addBytes to 1.
18✔
1867
                maxBytesDiff = 0
18✔
1868
        }
18✔
1869
        // If maxBytesDiff == 0, then that means MaxBytes didn't change.
1870
        // If maxBytesDiff > 0, then we want to reserve additional bytes.
1871

1872
        // Save the user configured MaxBytes.
1873
        newMaxBytes := cfg.MaxBytes
636✔
1874
        maxBytesOffset := int64(0)
636✔
1875

636✔
1876
        // We temporarily set cfg.MaxBytes to maxBytesDiff because checkAllLimits
636✔
1877
        // adds cfg.MaxBytes to the current reserved limit and checks if we've gone
636✔
1878
        // over. However, we don't want an addition cfg.MaxBytes, we only want to
636✔
1879
        // reserve the difference between the new and the old values.
636✔
1880
        cfg.MaxBytes = maxBytesDiff
636✔
1881

636✔
1882
        // Check limits.
636✔
1883
        js, isClustered := jsa.jetStreamAndClustered()
636✔
1884
        jsa.mu.RLock()
636✔
1885
        acc := jsa.account
636✔
1886
        jsa.usageMu.RLock()
636✔
1887
        selected, tier, hasTier := jsa.selectLimits(cfg.Replicas)
636✔
1888
        if !hasTier && old.Replicas != cfg.Replicas {
636✔
1889
                selected, tier, hasTier = jsa.selectLimits(old.Replicas)
×
1890
        }
×
1891
        jsa.usageMu.RUnlock()
636✔
1892
        reserved := int64(0)
636✔
1893
        if !isClustered {
703✔
1894
                reserved = jsa.tieredReservation(tier, &cfg)
67✔
1895
        }
67✔
1896
        jsa.mu.RUnlock()
636✔
1897
        if !hasTier {
636✔
1898
                return nil, NewJSNoLimitsError()
×
1899
        }
×
1900
        js.mu.RLock()
636✔
1901
        defer js.mu.RUnlock()
636✔
1902
        if isClustered {
1,205✔
1903
                _, reserved = tieredStreamAndReservationCount(js.cluster.streams[acc.Name], tier, &cfg)
569✔
1904
        }
569✔
1905
        // reservation does not account for this stream, hence add the old value
1906
        if tier == _EMPTY_ && old.Replicas > 1 {
1,078✔
1907
                reserved += old.MaxBytes * int64(old.Replicas)
442✔
1908
        } else {
636✔
1909
                reserved += old.MaxBytes
194✔
1910
        }
194✔
1911
        if err := js.checkAllLimits(&selected, &cfg, reserved, maxBytesOffset); err != nil {
643✔
1912
                return nil, err
7✔
1913
        }
7✔
1914
        // Restore the user configured MaxBytes.
1915
        cfg.MaxBytes = newMaxBytes
629✔
1916
        return &cfg, nil
629✔
1917
}
1918

1919
// Update will allow certain configuration properties of an existing stream to be updated.
1920
func (mset *stream) update(config *StreamConfig) error {
38✔
1921
        return mset.updateWithAdvisory(config, true, false)
38✔
1922
}
38✔
1923

1924
func (mset *stream) updatePedantic(config *StreamConfig, pedantic bool) error {
51✔
1925
        return mset.updateWithAdvisory(config, true, pedantic)
51✔
1926
}
51✔
1927

1928
// Update will allow certain configuration properties of an existing stream to be updated.
1929
func (mset *stream) updateWithAdvisory(config *StreamConfig, sendAdvisory bool, pedantic bool) error {
503✔
1930
        _, jsa, err := mset.acc.checkForJetStream()
503✔
1931
        if err != nil {
503✔
1932
                return err
×
1933
        }
×
1934

1935
        mset.mu.RLock()
503✔
1936
        ocfg := mset.cfg
503✔
1937
        s := mset.srv
503✔
1938
        mset.mu.RUnlock()
503✔
1939

503✔
1940
        cfg, err := mset.jsa.configUpdateCheck(&ocfg, config, s, pedantic)
503✔
1941
        if err != nil {
525✔
1942
                return NewJSStreamInvalidConfigError(err, Unless(err))
22✔
1943
        }
22✔
1944

1945
        // In the event that some of the stream-level limits have changed, yell appropriately
1946
        // if any of the consumers exceed that limit.
1947
        updateLimits := ocfg.ConsumerLimits.InactiveThreshold != cfg.ConsumerLimits.InactiveThreshold ||
481✔
1948
                ocfg.ConsumerLimits.MaxAckPending != cfg.ConsumerLimits.MaxAckPending
481✔
1949
        if updateLimits {
485✔
1950
                var errorConsumers []string
4✔
1951
                consumers := map[string]*ConsumerConfig{}
4✔
1952
                if mset.js.isClustered() {
6✔
1953
                        for _, c := range mset.sa.consumers {
7✔
1954
                                consumers[c.Name] = c.Config
5✔
1955
                        }
5✔
1956
                } else {
2✔
1957
                        for _, c := range mset.consumers {
7✔
1958
                                consumers[c.name] = &c.cfg
5✔
1959
                        }
5✔
1960
                }
1961
                for name, ccfg := range consumers {
14✔
1962
                        if ccfg.InactiveThreshold > cfg.ConsumerLimits.InactiveThreshold ||
10✔
1963
                                ccfg.MaxAckPending > cfg.ConsumerLimits.MaxAckPending {
20✔
1964
                                errorConsumers = append(errorConsumers, name)
10✔
1965
                        }
10✔
1966
                }
1967
                if len(errorConsumers) > 0 {
8✔
1968
                        // TODO(nat): Return a parsable error so that we can surface something
4✔
1969
                        // sensible through the JS API.
4✔
1970
                        return fmt.Errorf("change to limits violates consumers: %s", strings.Join(errorConsumers, ", "))
4✔
1971
                }
4✔
1972
        }
1973

1974
        jsa.mu.RLock()
477✔
1975
        if jsa.subjectsOverlap(cfg.Subjects, mset) {
478✔
1976
                jsa.mu.RUnlock()
1✔
1977
                return NewJSStreamSubjectOverlapError()
1✔
1978
        }
1✔
1979
        jsa.mu.RUnlock()
476✔
1980

476✔
1981
        mset.mu.Lock()
476✔
1982
        if mset.isLeader() {
684✔
1983
                // Now check for subject interest differences.
208✔
1984
                current := make(map[string]struct{}, len(ocfg.Subjects))
208✔
1985
                for _, s := range ocfg.Subjects {
423✔
1986
                        current[s] = struct{}{}
215✔
1987
                }
215✔
1988
                // Update config with new values. The store update will enforce any stricter limits.
1989

1990
                // Now walk new subjects. All of these need to be added, but we will check
1991
                // the originals first, since if it is in there we can skip, already added.
1992
                for _, s := range cfg.Subjects {
429✔
1993
                        if _, ok := current[s]; !ok {
239✔
1994
                                if _, err := mset.subscribeInternal(s, mset.processInboundJetStreamMsg); err != nil {
18✔
1995
                                        mset.mu.Unlock()
×
1996
                                        return err
×
1997
                                }
×
1998
                        }
1999
                        delete(current, s)
221✔
2000
                }
2001
                // What is left in current needs to be deleted.
2002
                for s := range current {
220✔
2003
                        if err := mset.unsubscribeInternal(s); err != nil {
12✔
2004
                                mset.mu.Unlock()
×
2005
                                return err
×
2006
                        }
×
2007
                }
2008

2009
                // Check for the Duplicates
2010
                if cfg.Duplicates != ocfg.Duplicates && mset.ddtmr != nil {
209✔
2011
                        // Let it fire right away, it will adjust properly on purge.
1✔
2012
                        mset.ddtmr.Reset(time.Microsecond)
1✔
2013
                }
1✔
2014

2015
                // Check for Sources.
2016
                if len(cfg.Sources) > 0 || len(ocfg.Sources) > 0 {
223✔
2017
                        currentIName := make(map[string]struct{})
15✔
2018
                        needsStartingSeqNum := make(map[string]struct{})
15✔
2019

15✔
2020
                        for _, s := range ocfg.Sources {
25✔
2021
                                currentIName[s.iname] = struct{}{}
10✔
2022
                        }
10✔
2023
                        for _, s := range cfg.Sources {
32✔
2024
                                s.setIndexName()
17✔
2025
                                if _, ok := currentIName[s.iname]; !ok {
30✔
2026
                                        // new source
13✔
2027
                                        if mset.sources == nil {
19✔
2028
                                                mset.sources = make(map[string]*sourceInfo)
6✔
2029
                                        }
6✔
2030
                                        mset.cfg.Sources = append(mset.cfg.Sources, s)
13✔
2031

13✔
2032
                                        var si *sourceInfo
13✔
2033

13✔
2034
                                        if len(s.SubjectTransforms) == 0 {
26✔
2035
                                                si = &sourceInfo{name: s.Name, iname: s.iname, sf: s.FilterSubject}
13✔
2036
                                        } else {
13✔
2037
                                                si = &sourceInfo{name: s.Name, iname: s.iname}
×
2038
                                                si.trs = make([]*subjectTransform, len(s.SubjectTransforms))
×
2039
                                                si.sfs = make([]string, len(s.SubjectTransforms))
×
2040
                                                for i := range s.SubjectTransforms {
×
2041
                                                        // err can be ignored as already validated in config check
×
2042
                                                        si.sfs[i] = s.SubjectTransforms[i].Source
×
2043
                                                        var err error
×
2044
                                                        si.trs[i], err = NewSubjectTransform(s.SubjectTransforms[i].Source, s.SubjectTransforms[i].Destination)
×
2045
                                                        if err != nil {
×
2046
                                                                mset.mu.Unlock()
×
2047
                                                                return fmt.Errorf("unable to get subject transform for source: %v", err)
×
2048
                                                        }
×
2049
                                                }
2050
                                        }
2051

2052
                                        mset.sources[s.iname] = si
13✔
2053
                                        needsStartingSeqNum[s.iname] = struct{}{}
13✔
2054
                                } else {
4✔
2055
                                        // source already exists
4✔
2056
                                        delete(currentIName, s.iname)
4✔
2057
                                }
4✔
2058
                        }
2059
                        // What is left in currentIName needs to be deleted.
2060
                        for iName := range currentIName {
21✔
2061
                                mset.cancelSourceConsumer(iName)
6✔
2062
                                delete(mset.sources, iName)
6✔
2063
                        }
6✔
2064
                        neededCopy := make(map[string]struct{}, len(needsStartingSeqNum))
15✔
2065
                        for iName := range needsStartingSeqNum {
28✔
2066
                                neededCopy[iName] = struct{}{}
13✔
2067
                        }
13✔
2068
                        mset.setStartingSequenceForSources(needsStartingSeqNum)
15✔
2069
                        for iName := range neededCopy {
28✔
2070
                                mset.setupSourceConsumer(iName, mset.sources[iName].sseq+1, time.Time{})
13✔
2071
                        }
13✔
2072
                }
2073
        }
2074

2075
        // Check for a change in allow direct status.
2076
        // These will run on all members, so just update as appropriate here.
2077
        // We do make sure we are caught up under monitorStream() during initial startup.
2078
        if cfg.AllowDirect != ocfg.AllowDirect {
483✔
2079
                if cfg.AllowDirect {
12✔
2080
                        mset.subscribeToDirect()
5✔
2081
                } else {
7✔
2082
                        mset.unsubscribeToDirect()
2✔
2083
                }
2✔
2084
        }
2085

2086
        // Check for changes to RePublish.
2087
        if cfg.RePublish != nil {
480✔
2088
                // Empty same as all.
4✔
2089
                if cfg.RePublish.Source == _EMPTY_ {
4✔
2090
                        cfg.RePublish.Source = fwcs
×
2091
                }
×
2092
                if cfg.RePublish.Destination == _EMPTY_ {
4✔
2093
                        cfg.RePublish.Destination = fwcs
×
2094
                }
×
2095
                tr, err := NewSubjectTransform(cfg.RePublish.Source, cfg.RePublish.Destination)
4✔
2096
                if err != nil {
4✔
2097
                        mset.mu.Unlock()
×
2098
                        return fmt.Errorf("stream configuration for republish from '%s' to '%s': %w", cfg.RePublish.Source, cfg.RePublish.Destination, err)
×
2099
                }
×
2100
                // Assign our transform for republishing.
2101
                mset.tr = tr
4✔
2102
        } else {
472✔
2103
                mset.tr = nil
472✔
2104
        }
472✔
2105

2106
        // Check for changes to subject transform
2107
        if ocfg.SubjectTransform == nil && cfg.SubjectTransform != nil {
476✔
2108
                tr, err := NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination)
×
2109
                if err != nil {
×
2110
                        mset.mu.Unlock()
×
2111
                        return fmt.Errorf("stream configuration for subject transform from '%s' to '%s': %w", cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination, err)
×
2112
                }
×
2113
                mset.itr = tr
×
2114
        } else if ocfg.SubjectTransform != nil && cfg.SubjectTransform != nil &&
476✔
2115
                (ocfg.SubjectTransform.Source != cfg.SubjectTransform.Source || ocfg.SubjectTransform.Destination != cfg.SubjectTransform.Destination) {
476✔
2116
                tr, err := NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination)
×
2117
                if err != nil {
×
2118
                        mset.mu.Unlock()
×
2119
                        return fmt.Errorf("stream configuration for subject transform from '%s' to '%s': %w", cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination, err)
×
2120
                }
×
2121
                mset.itr = tr
×
2122
        } else if ocfg.SubjectTransform != nil && cfg.SubjectTransform == nil {
476✔
2123
                mset.itr = nil
×
2124
        }
×
2125

2126
        js := mset.js
476✔
2127

476✔
2128
        if targetTier := tierName(cfg.Replicas); mset.tier != targetTier {
938✔
2129
                // In cases such as R1->R3, only one update is needed
462✔
2130
                jsa.usageMu.RLock()
462✔
2131
                _, ok := jsa.limits[targetTier]
462✔
2132
                jsa.usageMu.RUnlock()
462✔
2133
                if ok {
467✔
2134
                        // error never set
5✔
2135
                        _, reported, _ := mset.store.Utilization()
5✔
2136
                        jsa.updateUsage(mset.tier, mset.stype, -int64(reported))
5✔
2137
                        jsa.updateUsage(targetTier, mset.stype, int64(reported))
5✔
2138
                        mset.tier = targetTier
5✔
2139
                }
5✔
2140
                // else in case the new tier does not exist (say on move), keep the old tier around
2141
                // a subsequent update to an existing tier will then move from existing past tier to existing new tier
2142
        }
2143

2144
        if mset.isLeader() && mset.sa != nil && ocfg.Retention != cfg.Retention && cfg.Retention == InterestPolicy {
480✔
2145
                // Before we can update the retention policy for the consumer, we need
4✔
2146
                // the replica count of all consumers to match the stream.
4✔
2147
                for _, c := range mset.sa.consumers {
31✔
2148
                        if c.Config.Replicas > 0 && c.Config.Replicas != cfg.Replicas {
28✔
2149
                                mset.mu.Unlock()
1✔
2150
                                return fmt.Errorf("consumer %q replica count must be %d", c.Name, cfg.Replicas)
1✔
2151
                        }
1✔
2152
                }
2153
        }
2154

2155
        // Now update config and store's version of our config.
2156
        // Although we are under the stream write lock, we will also assign the new
2157
        // configuration under mset.cfgMu lock. This is so that in places where
2158
        // mset.mu cannot be acquired (like many cases in consumer.go where code
2159
        // is under the consumer's lock), and the stream's configuration needs to
2160
        // be inspected, one can use mset.cfgMu's read lock to do that safely.
2161
        mset.cfgMu.Lock()
475✔
2162
        mset.cfg = *cfg
475✔
2163
        mset.cfgMu.Unlock()
475✔
2164

475✔
2165
        // If we're changing retention and haven't errored because of consumer
475✔
2166
        // replicas by now, whip through and update the consumer retention.
475✔
2167
        if ocfg.Retention != cfg.Retention && cfg.Retention == InterestPolicy {
484✔
2168
                toUpdate := make([]*consumer, 0, len(mset.consumers))
9✔
2169
                for _, c := range mset.consumers {
67✔
2170
                        toUpdate = append(toUpdate, c)
58✔
2171
                }
58✔
2172
                var ss StreamState
9✔
2173
                mset.store.FastState(&ss)
9✔
2174
                mset.mu.Unlock()
9✔
2175
                for _, c := range toUpdate {
67✔
2176
                        c.mu.Lock()
58✔
2177
                        c.retention = cfg.Retention
58✔
2178
                        c.mu.Unlock()
58✔
2179
                        if c.retention == InterestPolicy {
116✔
2180
                                // If we're switching to interest, force a check of the
58✔
2181
                                // interest of existing stream messages.
58✔
2182
                                c.checkStateForInterestStream(&ss)
58✔
2183
                        }
58✔
2184
                }
2185
                mset.mu.Lock()
9✔
2186
        }
2187

2188
        // If we are the leader never suppress update advisory, simply send.
2189
        if mset.isLeader() && sendAdvisory {
680✔
2190
                mset.sendUpdateAdvisoryLocked()
205✔
2191
        }
205✔
2192
        mset.mu.Unlock()
475✔
2193

475✔
2194
        if js != nil {
950✔
2195
                maxBytesDiff := cfg.MaxBytes - ocfg.MaxBytes
475✔
2196
                if maxBytesDiff > 0 {
487✔
2197
                        // Reserve the difference
12✔
2198
                        js.reserveStreamResources(&StreamConfig{
12✔
2199
                                MaxBytes: maxBytesDiff,
12✔
2200
                                Storage:  cfg.Storage,
12✔
2201
                        })
12✔
2202
                } else if maxBytesDiff < 0 {
489✔
2203
                        // Release the difference
14✔
2204
                        js.releaseStreamResources(&StreamConfig{
14✔
2205
                                MaxBytes: -maxBytesDiff,
14✔
2206
                                Storage:  ocfg.Storage,
14✔
2207
                        })
14✔
2208
                }
14✔
2209
        }
2210

2211
        mset.store.UpdateConfig(cfg)
475✔
2212

475✔
2213
        return nil
475✔
2214
}
2215

2216
// Small helper to return the Name field from mset.cfg, protected by
2217
// the mset.cfgMu mutex. This is simply because we have several places
2218
// in consumer.go where we need it.
2219
func (mset *stream) getCfgName() string {
4,646✔
2220
        mset.cfgMu.RLock()
4,646✔
2221
        defer mset.cfgMu.RUnlock()
4,646✔
2222
        return mset.cfg.Name
4,646✔
2223
}
4,646✔
2224

2225
// Purge will remove all messages from the stream and underlying store based on the request.
2226
func (mset *stream) purge(preq *JSApiStreamPurgeRequest) (purged uint64, err error) {
280✔
2227
        mset.mu.RLock()
280✔
2228
        if mset.closed.Load() {
280✔
2229
                mset.mu.RUnlock()
×
2230
                return 0, errStreamClosed
×
2231
        }
×
2232
        if mset.cfg.Sealed {
280✔
2233
                mset.mu.RUnlock()
×
2234
                return 0, errors.New("sealed stream")
×
2235
        }
×
2236
        store, mlseq := mset.store, mset.lseq
280✔
2237
        mset.mu.RUnlock()
280✔
2238

280✔
2239
        if preq != nil {
519✔
2240
                purged, err = mset.store.PurgeEx(preq.Subject, preq.Sequence, preq.Keep)
239✔
2241
        } else {
280✔
2242
                purged, err = mset.store.Purge()
41✔
2243
        }
41✔
2244
        if err != nil {
280✔
2245
                return purged, err
×
2246
        }
×
2247

2248
        // Grab our stream state.
2249
        var state StreamState
280✔
2250
        store.FastState(&state)
280✔
2251
        fseq, lseq := state.FirstSeq, state.LastSeq
280✔
2252

280✔
2253
        mset.mu.Lock()
280✔
2254
        // Check if our last has moved past what our original last sequence was, if so reset.
280✔
2255
        if lseq > mlseq {
301✔
2256
                mset.setLastSeq(lseq)
21✔
2257
        }
21✔
2258

2259
        // Clear any pending acks below first seq.
2260
        mset.clearAllPreAcksBelowFloor(fseq)
280✔
2261
        mset.mu.Unlock()
280✔
2262

280✔
2263
        // Purge consumers.
280✔
2264
        // Check for filtered purge.
280✔
2265
        if preq != nil && preq.Subject != _EMPTY_ {
435✔
2266
                ss := store.FilteredState(fseq, preq.Subject)
155✔
2267
                fseq = ss.First
155✔
2268
        }
155✔
2269

2270
        mset.clsMu.RLock()
280✔
2271
        for _, o := range mset.cList {
346✔
2272
                start := fseq
66✔
2273
                o.mu.RLock()
66✔
2274
                // we update consumer sequences if:
66✔
2275
                // no subject was specified, we can purge all consumers sequences
66✔
2276
                doPurge := preq == nil ||
66✔
2277
                        preq.Subject == _EMPTY_ ||
66✔
2278
                        // consumer filter subject is equal to purged subject
66✔
2279
                        // or consumer filter subject is subset of purged subject,
66✔
2280
                        // but not the other way around.
66✔
2281
                        o.isEqualOrSubsetMatch(preq.Subject)
66✔
2282
                // Check if a consumer has a wider subject space then what we purged
66✔
2283
                var isWider bool
66✔
2284
                if !doPurge && preq != nil && o.isFilteredMatch(preq.Subject) {
77✔
2285
                        doPurge, isWider = true, true
11✔
2286
                        start = state.FirstSeq
11✔
2287
                }
11✔
2288
                o.mu.RUnlock()
66✔
2289
                if doPurge {
131✔
2290
                        o.purge(start, lseq, isWider)
65✔
2291
                }
65✔
2292
        }
2293
        mset.clsMu.RUnlock()
280✔
2294

280✔
2295
        return purged, nil
280✔
2296
}
2297

2298
// RemoveMsg will remove a message from a stream.
2299
// FIXME(dlc) - Should pick one and be consistent.
2300
func (mset *stream) removeMsg(seq uint64) (bool, error) {
67,078✔
2301
        return mset.deleteMsg(seq)
67,078✔
2302
}
67,078✔
2303

2304
// DeleteMsg will remove a message from a stream.
2305
func (mset *stream) deleteMsg(seq uint64) (bool, error) {
67,096✔
2306
        if mset.closed.Load() {
67,097✔
2307
                return false, errStreamClosed
1✔
2308
        }
1✔
2309
        removed, err := mset.store.RemoveMsg(seq)
67,095✔
2310
        if err != nil {
71,960✔
2311
                return removed, err
4,865✔
2312
        }
4,865✔
2313
        mset.mu.Lock()
62,230✔
2314
        mset.clearAllPreAcks(seq)
62,230✔
2315
        mset.mu.Unlock()
62,230✔
2316
        return removed, err
62,230✔
2317
}
2318

2319
// EraseMsg will securely remove a message and rewrite the data with random data.
2320
func (mset *stream) eraseMsg(seq uint64) (bool, error) {
7✔
2321
        if mset.closed.Load() {
7✔
2322
                return false, errStreamClosed
×
2323
        }
×
2324
        removed, err := mset.store.EraseMsg(seq)
7✔
2325
        if err != nil {
7✔
2326
                return removed, err
×
2327
        }
×
2328
        mset.mu.Lock()
7✔
2329
        mset.clearAllPreAcks(seq)
7✔
2330
        mset.mu.Unlock()
7✔
2331
        return removed, err
7✔
2332
}
2333

2334
// Are we a mirror?
2335
func (mset *stream) isMirror() bool {
9✔
2336
        mset.mu.RLock()
9✔
2337
        defer mset.mu.RUnlock()
9✔
2338
        return mset.cfg.Mirror != nil
9✔
2339
}
9✔
2340

2341
func (mset *stream) sourcesInfo() (sis []*StreamSourceInfo) {
17,519✔
2342
        mset.mu.RLock()
17,519✔
2343
        defer mset.mu.RUnlock()
17,519✔
2344
        for _, si := range mset.sources {
18,033✔
2345
                sis = append(sis, mset.sourceInfo(si))
514✔
2346
        }
514✔
2347
        return sis
17,519✔
2348
}
2349

2350
// Lock should be held
2351
func (mset *stream) sourceInfo(si *sourceInfo) *StreamSourceInfo {
18,033✔
2352
        if si == nil {
35,103✔
2353
                return nil
17,070✔
2354
        }
17,070✔
2355

2356
        var ssi = StreamSourceInfo{Name: si.name, Lag: si.lag, Error: si.err, FilterSubject: si.sf}
963✔
2357

963✔
2358
        trConfigs := make([]SubjectTransformConfig, len(si.sfs))
963✔
2359
        for i := range si.sfs {
1,020✔
2360
                destination := _EMPTY_
57✔
2361
                if si.trs[i] != nil {
94✔
2362
                        destination = si.trs[i].dest
37✔
2363
                }
37✔
2364
                trConfigs[i] = SubjectTransformConfig{si.sfs[i], destination}
57✔
2365
        }
2366

2367
        ssi.SubjectTransforms = trConfigs
963✔
2368

963✔
2369
        // If we have not heard from the source, set Active to -1.
963✔
2370
        if last := si.last.Load(); last == 0 {
1,292✔
2371
                ssi.Active = -1
329✔
2372
        } else {
963✔
2373
                ssi.Active = time.Since(time.Unix(0, last))
634✔
2374
        }
634✔
2375

2376
        var ext *ExternalStream
963✔
2377
        if mset.cfg.Mirror != nil {
1,412✔
2378
                ext = mset.cfg.Mirror.External
449✔
2379
        } else if ss := mset.streamSource(si.iname); ss != nil && ss.External != nil {
1,016✔
2380
                ext = ss.External
53✔
2381
        }
53✔
2382
        if ext != nil {
1,095✔
2383
                ssi.External = &ExternalStream{
132✔
2384
                        ApiPrefix:     ext.ApiPrefix,
132✔
2385
                        DeliverPrefix: ext.DeliverPrefix,
132✔
2386
                }
132✔
2387
        }
132✔
2388
        return &ssi
963✔
2389
}
2390

2391
// Return our source info for our mirror.
2392
func (mset *stream) mirrorInfo() *StreamSourceInfo {
17,519✔
2393
        mset.mu.RLock()
17,519✔
2394
        defer mset.mu.RUnlock()
17,519✔
2395
        return mset.sourceInfo(mset.mirror)
17,519✔
2396
}
17,519✔
2397

2398
const (
2399
        // Our consumer HB interval.
2400
        sourceHealthHB = 1 * time.Second
2401
        // How often we check and our stalled interval.
2402
        sourceHealthCheckInterval = 10 * time.Second
2403
)
2404

2405
// Will run as a Go routine to process mirror consumer messages.
2406
func (mset *stream) processMirrorMsgs(mirror *sourceInfo, ready *sync.WaitGroup) {
49✔
2407
        s := mset.srv
49✔
2408
        defer func() {
98✔
2409
                mirror.wg.Done()
49✔
2410
                s.grWG.Done()
49✔
2411
        }()
49✔
2412

2413
        // Grab stream quit channel.
2414
        mset.mu.Lock()
49✔
2415
        msgs, qch, siqch := mirror.msgs, mset.qch, mirror.qch
49✔
2416
        // Set the last seen as now so that we don't fail at the first check.
49✔
2417
        mirror.last.Store(time.Now().UnixNano())
49✔
2418
        mset.mu.Unlock()
49✔
2419

49✔
2420
        // Signal the caller that we have captured the above fields.
49✔
2421
        ready.Done()
49✔
2422

49✔
2423
        // Make sure we have valid ipq for msgs.
49✔
2424
        if msgs == nil {
49✔
2425
                mset.mu.Lock()
×
2426
                mset.cancelMirrorConsumer()
×
2427
                mset.mu.Unlock()
×
2428
                return
×
2429
        }
×
2430

2431
        t := time.NewTicker(sourceHealthCheckInterval)
49✔
2432
        defer t.Stop()
49✔
2433

49✔
2434
        for {
1,604✔
2435
                select {
1,555✔
2436
                case <-s.quitCh:
×
2437
                        return
×
2438
                case <-qch:
×
2439
                        return
×
2440
                case <-siqch:
49✔
2441
                        return
49✔
2442
                case <-msgs.ch:
1,502✔
2443
                        ims := msgs.pop()
1,502✔
2444
                        for _, im := range ims {
8,485✔
2445
                                if !mset.processInboundMirrorMsg(im) {
6,983✔
2446
                                        break
×
2447
                                }
2448
                                im.returnToPool()
6,983✔
2449
                        }
2450
                        msgs.recycle(&ims)
1,502✔
2451
                case <-t.C:
4✔
2452
                        mset.mu.RLock()
4✔
2453
                        var stalled bool
4✔
2454
                        if mset.mirror != nil {
8✔
2455
                                stalled = time.Since(time.Unix(0, mset.mirror.last.Load())) > sourceHealthCheckInterval
4✔
2456
                        }
4✔
2457
                        isLeader := mset.isLeader()
4✔
2458
                        mset.mu.RUnlock()
4✔
2459
                        // No longer leader.
4✔
2460
                        if !isLeader {
4✔
2461
                                mset.mu.Lock()
×
2462
                                mset.cancelMirrorConsumer()
×
2463
                                mset.mu.Unlock()
×
2464
                                return
×
2465
                        }
×
2466
                        // We are stalled.
2467
                        if stalled {
6✔
2468
                                mset.retryMirrorConsumer()
2✔
2469
                        }
2✔
2470
                }
2471
        }
2472
}
2473

2474
// Checks that the message is from our current direct consumer. We can not depend on sub comparison
2475
// since cross account imports break.
2476
func (si *sourceInfo) isCurrentSub(reply string) bool {
13,221✔
2477
        return si.cname != _EMPTY_ && strings.HasPrefix(reply, jsAckPre) && si.cname == tokenAt(reply, 4)
13,221✔
2478
}
13,221✔
2479

2480
// processInboundMirrorMsg handles processing messages bound for a stream.
2481
func (mset *stream) processInboundMirrorMsg(m *inMsg) bool {
6,983✔
2482
        mset.mu.Lock()
6,983✔
2483
        if mset.mirror == nil {
6,983✔
2484
                mset.mu.Unlock()
×
2485
                return false
×
2486
        }
×
2487
        if !mset.isLeader() {
6,983✔
2488
                mset.cancelMirrorConsumer()
×
2489
                mset.mu.Unlock()
×
2490
                return false
×
2491
        }
×
2492

2493
        isControl := m.isControlMsg()
6,983✔
2494

6,983✔
2495
        // Ignore from old subscriptions.
6,983✔
2496
        // The reason we can not just compare subs is that on cross account imports they will not match.
6,983✔
2497
        if !mset.mirror.isCurrentSub(m.rply) && !isControl {
6,983✔
2498
                mset.mu.Unlock()
×
2499
                return false
×
2500
        }
×
2501

2502
        // Check for heartbeats and flow control messages.
2503
        if isControl {
7,004✔
2504
                var needsRetry bool
21✔
2505
                // Flow controls have reply subjects.
21✔
2506
                if m.rply != _EMPTY_ {
21✔
2507
                        mset.handleFlowControl(m)
×
2508
                } else {
21✔
2509
                        // For idle heartbeats make sure we did not miss anything and check if we are considered stalled.
21✔
2510
                        if ldseq := parseInt64(getHeader(JSLastConsumerSeq, m.hdr)); ldseq > 0 && uint64(ldseq) != mset.mirror.dseq {
21✔
2511
                                needsRetry = true
×
2512
                        } else if fcReply := getHeader(JSConsumerStalled, m.hdr); len(fcReply) > 0 {
21✔
2513
                                // Other side thinks we are stalled, so send flow control reply.
×
2514
                                mset.outq.sendMsg(string(fcReply), nil)
×
2515
                        }
×
2516
                }
2517
                mset.mu.Unlock()
21✔
2518
                if needsRetry {
21✔
2519
                        mset.retryMirrorConsumer()
×
2520
                }
×
2521
                return !needsRetry
21✔
2522
        }
2523

2524
        sseq, dseq, dc, ts, pending := replyInfo(m.rply)
6,962✔
2525

6,962✔
2526
        if dc > 1 {
6,962✔
2527
                mset.mu.Unlock()
×
2528
                return false
×
2529
        }
×
2530

2531
        // Mirror info tracking.
2532
        olag, osseq, odseq := mset.mirror.lag, mset.mirror.sseq, mset.mirror.dseq
6,962✔
2533
        if sseq == mset.mirror.sseq+1 {
13,818✔
2534
                mset.mirror.dseq = dseq
6,856✔
2535
                mset.mirror.sseq++
6,856✔
2536
        } else if sseq <= mset.mirror.sseq {
6,962✔
2537
                // Ignore older messages.
×
2538
                mset.mu.Unlock()
×
2539
                return true
×
2540
        } else if mset.mirror.cname == _EMPTY_ {
106✔
2541
                mset.mirror.cname = tokenAt(m.rply, 4)
×
2542
                mset.mirror.dseq, mset.mirror.sseq = dseq, sseq
×
2543
        } else {
106✔
2544
                // If the deliver sequence matches then the upstream stream has expired or deleted messages.
106✔
2545
                if dseq == mset.mirror.dseq+1 {
212✔
2546
                        mset.skipMsgs(mset.mirror.sseq+1, sseq-1)
106✔
2547
                        mset.mirror.dseq++
106✔
2548
                        mset.mirror.sseq = sseq
106✔
2549
                } else {
106✔
2550
                        mset.mu.Unlock()
×
2551
                        mset.retryMirrorConsumer()
×
2552
                        return false
×
2553
                }
×
2554
        }
2555

2556
        if pending == 0 {
8,370✔
2557
                mset.mirror.lag = 0
1,408✔
2558
        } else {
6,962✔
2559
                mset.mirror.lag = pending - 1
5,554✔
2560
        }
5,554✔
2561

2562
        // Check if we allow mirror direct here. If so check they we have mostly caught up.
2563
        // The reason we do not require 0 is if the source is active we may always be slightly behind.
2564
        if mset.cfg.MirrorDirect && mset.mirror.dsub == nil && pending < dgetCaughtUpThresh {
6,966✔
2565
                if err := mset.subscribeToMirrorDirect(); err != nil {
4✔
2566
                        // Disable since we had problems above.
×
2567
                        mset.cfg.MirrorDirect = false
×
2568
                }
×
2569
        }
2570

2571
        // Do the subject transform if there's one
2572
        if len(mset.mirror.trs) > 0 {
7,216✔
2573
                for _, tr := range mset.mirror.trs {
608✔
2574
                        if tr == nil {
356✔
2575
                                continue
2✔
2576
                        } else {
352✔
2577
                                tsubj, err := tr.Match(m.subj)
352✔
2578
                                if err == nil {
604✔
2579
                                        m.subj = tsubj
252✔
2580
                                        break
252✔
2581
                                }
2582
                        }
2583
                }
2584
        }
2585

2586
        s, js, stype := mset.srv, mset.js, mset.cfg.Storage
6,962✔
2587
        node := mset.node
6,962✔
2588
        mset.mu.Unlock()
6,962✔
2589

6,962✔
2590
        var err error
6,962✔
2591
        if node != nil {
8,078✔
2592
                if js.limitsExceeded(stype) {
1,116✔
2593
                        s.resourcesExceededError()
×
2594
                        err = ApiErrors[JSInsufficientResourcesErr]
×
2595
                } else {
1,116✔
2596
                        err = node.Propose(encodeStreamMsg(m.subj, _EMPTY_, m.hdr, m.msg, sseq-1, ts, true))
1,116✔
2597
                }
1,116✔
2598
        } else {
5,846✔
2599
                err = mset.processJetStreamMsg(m.subj, _EMPTY_, m.hdr, m.msg, sseq-1, ts, nil, true)
5,846✔
2600
        }
5,846✔
2601
        if err != nil {
6,962✔
2602
                if strings.Contains(err.Error(), "no space left") {
×
2603
                        s.Errorf("JetStream out of space, will be DISABLED")
×
2604
                        s.DisableJetStream()
×
2605
                        return false
×
2606
                }
×
2607
                if err != errLastSeqMismatch {
×
2608
                        mset.mu.RLock()
×
2609
                        accName, sname := mset.acc.Name, mset.cfg.Name
×
2610
                        mset.mu.RUnlock()
×
2611
                        s.RateLimitWarnf("Error processing inbound mirror message for '%s' > '%s': %v",
×
2612
                                accName, sname, err)
×
2613
                } else {
×
2614
                        // We may have missed messages, restart.
×
2615
                        if sseq <= mset.lastSeq() {
×
2616
                                mset.mu.Lock()
×
2617
                                mset.mirror.lag = olag
×
2618
                                mset.mirror.sseq = osseq
×
2619
                                mset.mirror.dseq = odseq
×
2620
                                mset.mu.Unlock()
×
2621
                                return false
×
2622
                        } else {
×
2623
                                mset.mu.Lock()
×
2624
                                mset.mirror.dseq = odseq
×
2625
                                mset.mirror.sseq = osseq
×
2626
                                mset.mu.Unlock()
×
2627
                                mset.retryMirrorConsumer()
×
2628
                        }
×
2629
                }
2630
        }
2631
        return err == nil
6,962✔
2632
}
2633

2634
func (mset *stream) setMirrorErr(err *ApiError) {
×
2635
        mset.mu.Lock()
×
2636
        if mset.mirror != nil {
×
2637
                mset.mirror.err = err
×
2638
        }
×
2639
        mset.mu.Unlock()
×
2640
}
2641

2642
// Cancels a mirror consumer.
2643
//
2644
// Lock held on entry
2645
func (mset *stream) cancelMirrorConsumer() {
2✔
2646
        if mset.mirror == nil {
2✔
2647
                return
×
2648
        }
×
2649
        mset.cancelSourceInfo(mset.mirror)
2✔
2650
}
2651

2652
// Similar to setupMirrorConsumer except that it will print a debug statement
2653
// indicating that there is a retry.
2654
//
2655
// Lock is acquired in this function
2656
func (mset *stream) retryMirrorConsumer() error {
2✔
2657
        mset.mu.Lock()
2✔
2658
        defer mset.mu.Unlock()
2✔
2659
        mset.srv.Debugf("Retrying mirror consumer for '%s > %s'", mset.acc.Name, mset.cfg.Name)
2✔
2660
        mset.cancelMirrorConsumer()
2✔
2661
        return mset.setupMirrorConsumer()
2✔
2662
}
2✔
2663

2664
// Lock should be held.
2665
func (mset *stream) skipMsgs(start, end uint64) {
106✔
2666
        node, store := mset.node, mset.store
106✔
2667
        // If we are not clustered we can short circuit now with store.SkipMsgs
106✔
2668
        if node == nil {
211✔
2669
                store.SkipMsgs(start, end-start+1)
105✔
2670
                mset.lseq = end
105✔
2671
                return
105✔
2672
        }
105✔
2673

2674
        // FIXME (dlc) - We should allow proposals of DeleteRange, but would need to make sure all peers support.
2675
        // With syncRequest was easy to add bool into request.
2676
        var entries []*Entry
1✔
2677
        for seq := start; seq <= end; seq++ {
101✔
2678
                entries = append(entries, newEntry(EntryNormal, encodeStreamMsg(_EMPTY_, _EMPTY_, nil, nil, seq-1, 0, false)))
100✔
2679
                // So a single message does not get too big.
100✔
2680
                if len(entries) > 10_000 {
100✔
2681
                        node.ProposeMulti(entries)
×
2682
                        // We need to re-create `entries` because there is a reference
×
2683
                        // to it in the node's pae map.
×
2684
                        entries = entries[:0]
×
2685
                }
×
2686
        }
2687
        // Send all at once.
2688
        if len(entries) > 0 {
2✔
2689
                node.ProposeMulti(entries)
1✔
2690
        }
1✔
2691
}
2692

2693
const (
2694
        // Base retry backoff duration.
2695
        retryBackOff = 5 * time.Second
2696
        // Maximum amount we will wait.
2697
        retryMaximum = 2 * time.Minute
2698
)
2699

2700
// Calculate our backoff based on number of failures.
2701
func calculateRetryBackoff(fails int) time.Duration {
71✔
2702
        backoff := time.Duration(retryBackOff) * time.Duration(fails*2)
71✔
2703
        if backoff > retryMaximum {
71✔
2704
                backoff = retryMaximum
×
2705
        }
×
2706
        return backoff
71✔
2707
}
2708

2709
// This will schedule a call to setupMirrorConsumer, taking into account the last
2710
// time it was retried and determine the soonest setupMirrorConsumer can be called
2711
// without tripping the sourceConsumerRetryThreshold. We will also take into account
2712
// number of failures and will back off our retries.
2713
// The mset.mirror pointer has been verified to be not nil by the caller.
2714
//
2715
// Lock held on entry
2716
func (mset *stream) scheduleSetupMirrorConsumerRetry() {
62✔
2717
        // We are trying to figure out how soon we can retry. setupMirrorConsumer will reject
62✔
2718
        // a retry if last was done less than "sourceConsumerRetryThreshold" ago.
62✔
2719
        next := sourceConsumerRetryThreshold - time.Since(mset.mirror.lreq)
62✔
2720
        if next < 0 {
124✔
2721
                // It means that we have passed the threshold and so we are ready to go.
62✔
2722
                next = 0
62✔
2723
        }
62✔
2724
        // Take into account failures here.
2725
        next += calculateRetryBackoff(mset.mirror.fails)
62✔
2726

62✔
2727
        // Add some jitter.
62✔
2728
        next += time.Duration(rand.Intn(int(100*time.Millisecond))) + 100*time.Millisecond
62✔
2729

62✔
2730
        time.AfterFunc(next, func() {
124✔
2731
                mset.mu.Lock()
62✔
2732
                mset.setupMirrorConsumer()
62✔
2733
                mset.mu.Unlock()
62✔
2734
        })
62✔
2735
}
2736

2737
// How long we wait for a response from a consumer create request for a source or mirror.
2738
var srcConsumerWaitTime = 30 * time.Second
2739

2740
// Setup our mirror consumer.
2741
// Lock should be held.
2742
func (mset *stream) setupMirrorConsumer() error {
64✔
2743
        if mset.closed.Load() {
78✔
2744
                return errStreamClosed
14✔
2745
        }
14✔
2746
        if mset.outq == nil {
50✔
2747
                return errors.New("outq required")
×
2748
        }
×
2749
        // We use to prevent update of a mirror configuration in cluster
2750
        // mode but not in standalone. This is now fixed. However, without
2751
        // rejecting the update, it could be that if the source stream was
2752
        // removed and then later the mirrored stream config changed to
2753
        // remove mirror configuration, this function would panic when
2754
        // accessing mset.cfg.Mirror fields. Adding this protection in case
2755
        // we allow in the future the mirror config to be changed (removed).
2756
        if mset.cfg.Mirror == nil {
50✔
2757
                return errors.New("invalid mirror configuration")
×
2758
        }
×
2759

2760
        // If this is the first time
2761
        if mset.mirror == nil {
51✔
2762
                mset.mirror = &sourceInfo{name: mset.cfg.Mirror.Name}
1✔
2763
        } else {
50✔
2764
                mset.cancelSourceInfo(mset.mirror)
49✔
2765
                mset.mirror.sseq = mset.lseq
49✔
2766
        }
49✔
2767

2768
        // If we are no longer the leader stop trying.
2769
        if !mset.isLeader() {
51✔
2770
                return nil
1✔
2771
        }
1✔
2772

2773
        mirror := mset.mirror
49✔
2774

49✔
2775
        // We want to throttle here in terms of how fast we request new consumers,
49✔
2776
        // or if the previous is still in progress.
49✔
2777
        if last := time.Since(mirror.lreq); last < sourceConsumerRetryThreshold || mirror.sip {
49✔
2778
                mset.scheduleSetupMirrorConsumerRetry()
×
2779
                return nil
×
2780
        }
×
2781
        mirror.lreq = time.Now()
49✔
2782

49✔
2783
        // Determine subjects etc.
49✔
2784
        var deliverSubject string
49✔
2785
        ext := mset.cfg.Mirror.External
49✔
2786

49✔
2787
        if ext != nil && ext.DeliverPrefix != _EMPTY_ {
57✔
2788
                deliverSubject = strings.ReplaceAll(ext.DeliverPrefix+syncSubject(".M"), "..", ".")
8✔
2789
        } else {
49✔
2790
                deliverSubject = syncSubject("$JS.M")
41✔
2791
        }
41✔
2792

2793
        // Now send off request to create/update our consumer. This will be all API based even in single server mode.
2794
        // We calculate durable names apriori so we do not need to save them off.
2795

2796
        var state StreamState
49✔
2797
        mset.store.FastState(&state)
49✔
2798

49✔
2799
        req := &CreateConsumerRequest{
49✔
2800
                Stream: mset.cfg.Mirror.Name,
49✔
2801
                Config: ConsumerConfig{
49✔
2802
                        DeliverSubject:    deliverSubject,
49✔
2803
                        DeliverPolicy:     DeliverByStartSequence,
49✔
2804
                        OptStartSeq:       state.LastSeq + 1,
49✔
2805
                        AckPolicy:         AckNone,
49✔
2806
                        AckWait:           22 * time.Hour,
49✔
2807
                        MaxDeliver:        1,
49✔
2808
                        Heartbeat:         sourceHealthHB,
49✔
2809
                        FlowControl:       true,
49✔
2810
                        Direct:            true,
49✔
2811
                        InactiveThreshold: sourceHealthCheckInterval,
49✔
2812
                },
49✔
2813
        }
49✔
2814

49✔
2815
        // Only use start optionals on first time.
49✔
2816
        if state.Msgs == 0 && state.FirstSeq == 0 {
88✔
2817
                req.Config.OptStartSeq = 0
39✔
2818
                if mset.cfg.Mirror.OptStartSeq > 0 {
41✔
2819
                        req.Config.OptStartSeq = mset.cfg.Mirror.OptStartSeq
2✔
2820
                } else if mset.cfg.Mirror.OptStartTime != nil {
42✔
2821
                        req.Config.OptStartTime = mset.cfg.Mirror.OptStartTime
3✔
2822
                        req.Config.DeliverPolicy = DeliverByStartTime
3✔
2823
                }
3✔
2824
        }
2825
        if req.Config.OptStartSeq == 0 && req.Config.OptStartTime == nil {
83✔
2826
                // If starting out and lastSeq is 0.
34✔
2827
                req.Config.DeliverPolicy = DeliverAll
34✔
2828
        }
34✔
2829

2830
        // Filters
2831
        if mset.cfg.Mirror.FilterSubject != _EMPTY_ {
54✔
2832
                req.Config.FilterSubject = mset.cfg.Mirror.FilterSubject
5✔
2833
                mirror.sf = mset.cfg.Mirror.FilterSubject
5✔
2834
        }
5✔
2835

2836
        if lst := len(mset.cfg.Mirror.SubjectTransforms); lst > 0 {
55✔
2837
                sfs := make([]string, lst)
6✔
2838
                trs := make([]*subjectTransform, lst)
6✔
2839

6✔
2840
                for i, tr := range mset.cfg.Mirror.SubjectTransforms {
13✔
2841
                        // will not fail as already checked before that the transform will work
7✔
2842
                        subjectTransform, err := NewSubjectTransform(tr.Source, tr.Destination)
7✔
2843
                        if err != nil {
7✔
2844
                                mset.srv.Errorf("Unable to get transform for mirror consumer: %v", err)
×
2845
                        }
×
2846
                        sfs[i] = tr.Source
7✔
2847
                        trs[i] = subjectTransform
7✔
2848
                }
2849
                mirror.sfs = sfs
6✔
2850
                mirror.trs = trs
6✔
2851
                // If there was no explicit FilterSubject defined and we have a single
6✔
2852
                // subject transform, use Config.FilterSubject instead of FilterSubjects
6✔
2853
                // so that we can use the extended consumer create API down below.
6✔
2854
                if req.Config.FilterSubject == _EMPTY_ && len(sfs) == 1 {
11✔
2855
                        req.Config.FilterSubject = sfs[0]
5✔
2856
                } else {
6✔
2857
                        req.Config.FilterSubjects = sfs
1✔
2858
                }
1✔
2859
        }
2860

2861
        respCh := make(chan *JSApiConsumerCreateResponse, 1)
49✔
2862
        reply := infoReplySubject()
49✔
2863
        crSub, err := mset.subscribeInternal(reply, func(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
98✔
2864
                mset.unsubscribe(sub)
49✔
2865
                _, msg := c.msgParts(rmsg)
49✔
2866

49✔
2867
                var ccr JSApiConsumerCreateResponse
49✔
2868
                if err := json.Unmarshal(msg, &ccr); err != nil {
49✔
2869
                        c.Warnf("JetStream bad mirror consumer create response: %q", msg)
×
2870
                        mset.setMirrorErr(ApiErrors[JSInvalidJSONErr])
×
2871
                        return
×
2872
                }
×
2873
                select {
49✔
2874
                case respCh <- &ccr:
49✔
2875
                default:
×
2876
                }
2877
        })
2878
        if err != nil {
49✔
2879
                mirror.err = NewJSMirrorConsumerSetupFailedError(err, Unless(err))
×
2880
                mset.scheduleSetupMirrorConsumerRetry()
×
2881
                return nil
×
2882
        }
×
2883

2884
        var subject string
49✔
2885
        if req.Config.FilterSubject != _EMPTY_ {
59✔
2886
                req.Config.Name = fmt.Sprintf("mirror-%s", createConsumerName())
10✔
2887
                subject = fmt.Sprintf(JSApiConsumerCreateExT, mset.cfg.Mirror.Name, req.Config.Name, req.Config.FilterSubject)
10✔
2888
        } else {
49✔
2889
                subject = fmt.Sprintf(JSApiConsumerCreateT, mset.cfg.Mirror.Name)
39✔
2890
        }
39✔
2891
        if ext != nil {
62✔
2892
                subject = strings.Replace(subject, JSApiPrefix, ext.ApiPrefix, 1)
13✔
2893
                subject = strings.ReplaceAll(subject, "..", ".")
13✔
2894
        }
13✔
2895

2896
        // Marshal now that we are done with `req`.
2897
        b, _ := json.Marshal(req)
49✔
2898

49✔
2899
        // Reset
49✔
2900
        mirror.msgs = nil
49✔
2901
        mirror.err = nil
49✔
2902
        mirror.sip = true
49✔
2903

49✔
2904
        // Send the consumer create request
49✔
2905
        mset.outq.send(newJSPubMsg(subject, _EMPTY_, reply, nil, b, nil, 0))
49✔
2906

49✔
2907
        go func() {
98✔
2908

49✔
2909
                var retry bool
49✔
2910
                defer func() {
98✔
2911
                        mset.mu.Lock()
49✔
2912
                        // Check that this is still valid and if so, clear the "setup in progress" flag.
49✔
2913
                        if mset.mirror != nil {
98✔
2914
                                mset.mirror.sip = false
49✔
2915
                                // If we need to retry, schedule now
49✔
2916
                                if retry {
49✔
2917
                                        mset.mirror.fails++
×
2918
                                        // Cancel here since we can not do anything with this consumer at this point.
×
2919
                                        mset.cancelSourceInfo(mset.mirror)
×
2920
                                        mset.scheduleSetupMirrorConsumerRetry()
×
2921
                                } else {
49✔
2922
                                        // Clear on success.
49✔
2923
                                        mset.mirror.fails = 0
49✔
2924
                                }
49✔
2925
                        }
2926
                        mset.mu.Unlock()
49✔
2927
                }()
2928

2929
                // Wait for previous processMirrorMsgs go routine to be completely done.
2930
                // If none is running, this will not block.
2931
                mirror.wg.Wait()
49✔
2932

49✔
2933
                select {
49✔
2934
                case ccr := <-respCh:
49✔
2935
                        mset.mu.Lock()
49✔
2936
                        // Mirror config has been removed.
49✔
2937
                        if mset.mirror == nil {
49✔
2938
                                mset.mu.Unlock()
×
2939
                                return
×
2940
                        }
×
2941
                        ready := sync.WaitGroup{}
49✔
2942
                        mirror := mset.mirror
49✔
2943
                        mirror.err = nil
49✔
2944
                        if ccr.Error != nil || ccr.ConsumerInfo == nil {
49✔
2945
                                mset.srv.Warnf("JetStream error response for create mirror consumer: %+v", ccr.Error)
×
2946
                                mirror.err = ccr.Error
×
2947
                                // Let's retry as soon as possible, but we are gated by sourceConsumerRetryThreshold
×
2948
                                retry = true
×
2949
                                mset.mu.Unlock()
×
2950
                                return
×
2951
                        } else {
49✔
2952
                                // Setup actual subscription to process messages from our source.
49✔
2953
                                qname := fmt.Sprintf("[ACC:%s] stream mirror '%s' of '%s' msgs", mset.acc.Name, mset.cfg.Name, mset.cfg.Mirror.Name)
49✔
2954
                                // Create a new queue each time
49✔
2955
                                mirror.msgs = newIPQueue[*inMsg](mset.srv, qname)
49✔
2956
                                msgs := mirror.msgs
49✔
2957
                                sub, err := mset.subscribeInternal(deliverSubject, func(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
7,032✔
2958
                                        hdr, msg := c.msgParts(copyBytes(rmsg)) // Need to copy.
6,983✔
2959
                                        mset.queueInbound(msgs, subject, reply, hdr, msg, nil, nil)
6,983✔
2960
                                        mirror.last.Store(time.Now().UnixNano())
6,983✔
2961
                                })
6,983✔
2962
                                if err != nil {
49✔
2963
                                        mirror.err = NewJSMirrorConsumerSetupFailedError(err, Unless(err))
×
2964
                                        retry = true
×
2965
                                        mset.mu.Unlock()
×
2966
                                        return
×
2967
                                }
×
2968
                                // Save our sub.
2969
                                mirror.sub = sub
49✔
2970

49✔
2971
                                // When an upstream stream expires messages or in general has messages that we want
49✔
2972
                                // that are no longer available we need to adjust here.
49✔
2973
                                var state StreamState
49✔
2974
                                mset.store.FastState(&state)
49✔
2975

49✔
2976
                                // Check if we need to skip messages.
49✔
2977
                                if state.LastSeq != ccr.ConsumerInfo.Delivered.Stream {
56✔
2978
                                        // Check to see if delivered is past our last and we have no msgs. This will help the
7✔
2979
                                        // case when mirroring a stream that has a very high starting sequence number.
7✔
2980
                                        if state.Msgs == 0 && ccr.ConsumerInfo.Delivered.Stream > state.LastSeq {
14✔
2981
                                                mset.store.PurgeEx(_EMPTY_, ccr.ConsumerInfo.Delivered.Stream+1, 0)
7✔
2982
                                                mset.lseq = ccr.ConsumerInfo.Delivered.Stream
7✔
2983
                                        } else {
7✔
2984
                                                mset.skipMsgs(state.LastSeq+1, ccr.ConsumerInfo.Delivered.Stream)
×
2985
                                        }
×
2986
                                }
2987

2988
                                // Capture consumer name.
2989
                                mirror.cname = ccr.ConsumerInfo.Name
49✔
2990
                                mirror.dseq = 0
49✔
2991
                                mirror.sseq = ccr.ConsumerInfo.Delivered.Stream
49✔
2992
                                mirror.qch = make(chan struct{})
49✔
2993
                                mirror.wg.Add(1)
49✔
2994
                                ready.Add(1)
49✔
2995
                                if !mset.srv.startGoRoutine(
49✔
2996
                                        func() { mset.processMirrorMsgs(mirror, &ready) },
98✔
2997
                                        pprofLabels{
2998
                                                "type":     "mirror",
2999
                                                "account":  mset.acc.Name,
3000
                                                "stream":   mset.cfg.Name,
3001
                                                "consumer": mirror.cname,
3002
                                        },
3003
                                ) {
×
3004
                                        ready.Done()
×
3005
                                }
×
3006
                        }
3007
                        mset.mu.Unlock()
49✔
3008
                        ready.Wait()
49✔
3009
                case <-time.After(srcConsumerWaitTime):
×
3010
                        mset.unsubscribe(crSub)
×
3011
                        // We already waited 30 seconds, let's retry now.
×
3012
                        retry = true
×
3013
                }
3014
        }()
3015

3016
        return nil
49✔
3017
}
3018

3019
func (mset *stream) streamSource(iname string) *StreamSource {
603✔
3020
        for _, ssi := range mset.cfg.Sources {
1,404✔
3021
                if ssi.iname == iname {
1,404✔
3022
                        return ssi
603✔
3023
                }
603✔
3024
        }
3025
        return nil
×
3026
}
3027

3028
// Lock should be held.
3029
func (mset *stream) retrySourceConsumerAtSeq(iName string, seq uint64) {
96✔
3030
        s := mset.srv
96✔
3031

96✔
3032
        s.Debugf("Retrying source consumer for '%s > %s'", mset.acc.Name, mset.cfg.Name)
96✔
3033

96✔
3034
        // setupSourceConsumer will check that the source is still configured.
96✔
3035
        mset.setupSourceConsumer(iName, seq, time.Time{})
96✔
3036
}
96✔
3037

3038
// Lock should be held.
3039
func (mset *stream) cancelSourceConsumer(iname string) {
118✔
3040
        if si := mset.sources[iname]; si != nil {
236✔
3041
                mset.cancelSourceInfo(si)
118✔
3042
                si.sseq, si.dseq = 0, 0
118✔
3043
        }
118✔
3044
}
3045

3046
// The `si` has been verified to be not nil. The sourceInfo's sub will
3047
// be unsubscribed and set to nil (if not already done) and the
3048
// cname will be reset. The message processing's go routine quit channel
3049
// will be closed if still opened.
3050
//
3051
// Lock should be held
3052
func (mset *stream) cancelSourceInfo(si *sourceInfo) {
630✔
3053
        if si.sub != nil {
759✔
3054
                mset.unsubscribe(si.sub)
129✔
3055
                si.sub = nil
129✔
3056
        }
129✔
3057
        // In case we had a mirror direct subscription.
3058
        if si.dsub != nil {
634✔
3059
                mset.unsubscribe(si.dsub)
4✔
3060
                si.dsub = nil
4✔
3061
        }
4✔
3062
        mset.removeInternalConsumer(si)
630✔
3063
        if si.qch != nil {
759✔
3064
                close(si.qch)
129✔
3065
                si.qch = nil
129✔
3066
        }
129✔
3067
        if si.msgs != nil {
681✔
3068
                si.msgs.drain()
51✔
3069
                si.msgs.unregister()
51✔
3070
        }
51✔
3071
        // If we have a schedule setup go ahead and delete that.
3072
        if t := mset.sourceSetupSchedules[si.iname]; t != nil {
655✔
3073
                t.Stop()
25✔
3074
                delete(mset.sourceSetupSchedules, si.iname)
25✔
3075
        }
25✔
3076
}
3077

3078
const sourceConsumerRetryThreshold = 2 * time.Second
3079

3080
// This is the main function to call when needing to setup a new consumer for the source.
3081
// It actually only does the scheduling of the execution of trySetupSourceConsumer in order to implement retry backoff
3082
// and throttle the number of requests.
3083
// Lock should be held.
3084
func (mset *stream) setupSourceConsumer(iname string, seq uint64, startTime time.Time) {
198✔
3085
        if mset.sourceSetupSchedules == nil {
262✔
3086
                mset.sourceSetupSchedules = map[string]*time.Timer{}
64✔
3087
        }
64✔
3088

3089
        if _, ok := mset.sourceSetupSchedules[iname]; ok {
282✔
3090
                // If there is already a timer scheduled, we don't need to do anything.
84✔
3091
                return
84✔
3092
        }
84✔
3093

3094
        si := mset.sources[iname]
114✔
3095
        if si == nil || si.sip { // if sourceInfo was removed or setup is in progress, nothing to do
114✔
3096
                return
×
3097
        }
×
3098

3099
        // First calculate the delay until the next time we can
3100
        var scheduleDelay time.Duration
114✔
3101

114✔
3102
        if !si.lreq.IsZero() { // it's not the very first time we are called, compute the delay
136✔
3103
                // We want to throttle here in terms of how fast we request new consumers
22✔
3104
                if sinceLast := time.Since(si.lreq); sinceLast < sourceConsumerRetryThreshold {
37✔
3105
                        scheduleDelay = sourceConsumerRetryThreshold - sinceLast
15✔
3106
                }
15✔
3107
                // Is it a retry? If so, add a backoff
3108
                if si.fails > 0 {
31✔
3109
                        scheduleDelay += calculateRetryBackoff(si.fails)
9✔
3110
                }
9✔
3111
        }
3112

3113
        // Always add some jitter
3114
        scheduleDelay += time.Duration(rand.Intn(int(100*time.Millisecond))) + 100*time.Millisecond
114✔
3115

114✔
3116
        // Schedule the call to trySetupSourceConsumer
114✔
3117
        mset.sourceSetupSchedules[iname] = time.AfterFunc(scheduleDelay, func() {
203✔
3118
                mset.mu.Lock()
89✔
3119
                defer mset.mu.Unlock()
89✔
3120

89✔
3121
                delete(mset.sourceSetupSchedules, iname)
89✔
3122
                mset.trySetupSourceConsumer(iname, seq, startTime)
89✔
3123
        })
89✔
3124
}
3125

3126
// This is where we will actually try to create a new consumer for the source
3127
// Lock should be held.
3128
func (mset *stream) trySetupSourceConsumer(iname string, seq uint64, startTime time.Time) {
89✔
3129
        // Ignore if closed or not leader.
89✔
3130
        if mset.closed.Load() || !mset.isLeader() {
89✔
3131
                return
×
3132
        }
×
3133

3134
        si := mset.sources[iname]
89✔
3135
        if si == nil {
89✔
3136
                return
×
3137
        }
×
3138

3139
        // Cancel previous instance if applicable
3140
        mset.cancelSourceInfo(si)
89✔
3141

89✔
3142
        ssi := mset.streamSource(iname)
89✔
3143
        if ssi == nil {
89✔
3144
                return
×
3145
        }
×
3146

3147
        si.lreq = time.Now()
89✔
3148

89✔
3149
        // Determine subjects etc.
89✔
3150
        var deliverSubject string
89✔
3151
        ext := ssi.External
89✔
3152

89✔
3153
        if ext != nil && ext.DeliverPrefix != _EMPTY_ {
90✔
3154
                deliverSubject = strings.ReplaceAll(ext.DeliverPrefix+syncSubject(".S"), "..", ".")
1✔
3155
        } else {
89✔
3156
                deliverSubject = syncSubject("$JS.S")
88✔
3157
        }
88✔
3158

3159
        req := &CreateConsumerRequest{
89✔
3160
                Stream: si.name,
89✔
3161
                Config: ConsumerConfig{
89✔
3162
                        DeliverSubject:    deliverSubject,
89✔
3163
                        AckPolicy:         AckNone,
89✔
3164
                        AckWait:           22 * time.Hour,
89✔
3165
                        MaxDeliver:        1,
89✔
3166
                        Heartbeat:         sourceHealthHB,
89✔
3167
                        FlowControl:       true,
89✔
3168
                        Direct:            true,
89✔
3169
                        InactiveThreshold: sourceHealthCheckInterval,
89✔
3170
                },
89✔
3171
        }
89✔
3172

89✔
3173
        // If starting, check any configs.
89✔
3174
        if !startTime.IsZero() && seq > 1 {
89✔
3175
                req.Config.OptStartTime = &startTime
×
3176
                req.Config.DeliverPolicy = DeliverByStartTime
×
3177
        } else if seq <= 1 {
154✔
3178
                if ssi.OptStartSeq > 0 {
68✔
3179
                        req.Config.OptStartSeq = ssi.OptStartSeq
3✔
3180
                        req.Config.DeliverPolicy = DeliverByStartSequence
3✔
3181
                } else {
65✔
3182
                        // We have not recovered state so check that configured time is less that our first seq time.
62✔
3183
                        var state StreamState
62✔
3184
                        mset.store.FastState(&state)
62✔
3185
                        if ssi.OptStartTime != nil {
66✔
3186
                                if !state.LastTime.IsZero() && ssi.OptStartTime.Before(state.LastTime) {
6✔
3187
                                        req.Config.OptStartTime = &state.LastTime
2✔
3188
                                } else {
4✔
3189
                                        req.Config.OptStartTime = ssi.OptStartTime
2✔
3190
                                }
2✔
3191
                                req.Config.DeliverPolicy = DeliverByStartTime
4✔
3192
                        } else if state.FirstSeq > 1 && !state.LastTime.IsZero() {
61✔
3193
                                req.Config.OptStartTime = &state.LastTime
3✔
3194
                                req.Config.DeliverPolicy = DeliverByStartTime
3✔
3195
                        }
3✔
3196
                }
3197

3198
        } else {
24✔
3199
                req.Config.OptStartSeq = seq
24✔
3200
                req.Config.DeliverPolicy = DeliverByStartSequence
24✔
3201
        }
24✔
3202
        // Filters
3203
        if ssi.FilterSubject != _EMPTY_ {
103✔
3204
                req.Config.FilterSubject = ssi.FilterSubject
14✔
3205
        }
14✔
3206

3207
        var filterSubjects []string
89✔
3208
        for _, tr := range ssi.SubjectTransforms {
96✔
3209
                filterSubjects = append(filterSubjects, tr.Source)
7✔
3210
        }
7✔
3211
        req.Config.FilterSubjects = filterSubjects
89✔
3212

89✔
3213
        respCh := make(chan *JSApiConsumerCreateResponse, 1)
89✔
3214
        reply := infoReplySubject()
89✔
3215
        crSub, err := mset.subscribeInternal(reply, func(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
173✔
3216
                mset.unsubscribe(sub)
84✔
3217
                _, msg := c.msgParts(rmsg)
84✔
3218
                var ccr JSApiConsumerCreateResponse
84✔
3219
                if err := json.Unmarshal(msg, &ccr); err != nil {
84✔
3220
                        c.Warnf("JetStream bad source consumer create response: %q", msg)
×
3221
                        return
×
3222
                }
×
3223
                select {
84✔
3224
                case respCh <- &ccr:
84✔
3225
                default:
×
3226
                }
3227
        })
3228
        if err != nil {
89✔
3229
                si.err = NewJSSourceConsumerSetupFailedError(err, Unless(err))
×
3230
                mset.setupSourceConsumer(iname, seq, startTime)
×
3231
                return
×
3232
        }
×
3233

3234
        var subject string
89✔
3235
        if req.Config.FilterSubject != _EMPTY_ {
103✔
3236
                req.Config.Name = fmt.Sprintf("src-%s", createConsumerName())
14✔
3237
                subject = fmt.Sprintf(JSApiConsumerCreateExT, si.name, req.Config.Name, req.Config.FilterSubject)
14✔
3238
        } else if len(req.Config.FilterSubjects) == 1 {
92✔
3239
                req.Config.Name = fmt.Sprintf("src-%s", createConsumerName())
3✔
3240
                // It is necessary to switch to using FilterSubject here as the extended consumer
3✔
3241
                // create API checks for it, so as to not accidentally allow multiple filtered subjects.
3✔
3242
                req.Config.FilterSubject = req.Config.FilterSubjects[0]
3✔
3243
                req.Config.FilterSubjects = nil
3✔
3244
                subject = fmt.Sprintf(JSApiConsumerCreateExT, si.name, req.Config.Name, req.Config.FilterSubject)
3✔
3245
        } else {
75✔
3246
                subject = fmt.Sprintf(JSApiConsumerCreateT, si.name)
72✔
3247
        }
72✔
3248
        if ext != nil {
99✔
3249
                subject = strings.Replace(subject, JSApiPrefix, ext.ApiPrefix, 1)
10✔
3250
                subject = strings.ReplaceAll(subject, "..", ".")
10✔
3251
        }
10✔
3252

3253
        // Marshal request.
3254
        b, _ := json.Marshal(req)
89✔
3255

89✔
3256
        // Reset
89✔
3257
        si.msgs = nil
89✔
3258
        si.err = nil
89✔
3259
        si.sip = true
89✔
3260

89✔
3261
        // Send the consumer create request
89✔
3262
        mset.outq.send(newJSPubMsg(subject, _EMPTY_, reply, nil, b, nil, 0))
89✔
3263

89✔
3264
        go func() {
178✔
3265

89✔
3266
                var retry bool
89✔
3267
                defer func() {
178✔
3268
                        mset.mu.Lock()
89✔
3269
                        // Check that this is still valid and if so, clear the "setup in progress" flag.
89✔
3270
                        if si := mset.sources[iname]; si != nil {
178✔
3271
                                si.sip = false
89✔
3272
                                // If we need to retry, schedule now
89✔
3273
                                if retry {
98✔
3274
                                        si.fails++
9✔
3275
                                        // Cancel here since we can not do anything with this consumer at this point.
9✔
3276
                                        mset.cancelSourceInfo(si)
9✔
3277
                                        mset.setupSourceConsumer(iname, seq, startTime)
9✔
3278
                                } else {
89✔
3279
                                        // Clear on success.
80✔
3280
                                        si.fails = 0
80✔
3281
                                }
80✔
3282
                        }
3283
                        mset.mu.Unlock()
89✔
3284
                }()
3285

3286
                select {
89✔
3287
                case ccr := <-respCh:
84✔
3288
                        mset.mu.Lock()
84✔
3289
                        // Check that it has not been removed or canceled (si.sub would be nil)
84✔
3290
                        if si := mset.sources[iname]; si != nil {
168✔
3291
                                si.err = nil
84✔
3292
                                if ccr.Error != nil || ccr.ConsumerInfo == nil {
88✔
3293
                                        // Note: this warning can happen a few times when starting up the server when sourcing streams are
4✔
3294
                                        // defined, this is normal as the streams are re-created in no particular order and it is possible
4✔
3295
                                        // that a stream sourcing another could come up before all of its sources have been recreated.
4✔
3296
                                        mset.srv.Warnf("JetStream error response for stream %s create source consumer %s: %+v", mset.cfg.Name, si.name, ccr.Error)
4✔
3297
                                        si.err = ccr.Error
4✔
3298
                                        // Let's retry as soon as possible, but we are gated by sourceConsumerRetryThreshold
4✔
3299
                                        retry = true
4✔
3300
                                        mset.mu.Unlock()
4✔
3301
                                        return
4✔
3302
                                } else {
84✔
3303
                                        // Check if our shared msg queue and go routine is running or not.
80✔
3304
                                        if mset.smsgs == nil {
128✔
3305
                                                qname := fmt.Sprintf("[ACC:%s] stream sources '%s' msgs", mset.acc.Name, mset.cfg.Name)
48✔
3306
                                                mset.smsgs = newIPQueue[*inMsg](mset.srv, qname)
48✔
3307
                                                mset.srv.startGoRoutine(func() { mset.processAllSourceMsgs() },
96✔
3308
                                                        pprofLabels{
3309
                                                                "type":    "source",
3310
                                                                "account": mset.acc.Name,
3311
                                                                "stream":  mset.cfg.Name,
3312
                                                        },
3313
                                                )
3314
                                        }
3315

3316
                                        // Setup actual subscription to process messages from our source.
3317
                                        if si.sseq != ccr.ConsumerInfo.Delivered.Stream {
97✔
3318
                                                si.sseq = ccr.ConsumerInfo.Delivered.Stream + 1
17✔
3319
                                        }
17✔
3320
                                        // Capture consumer name.
3321
                                        si.cname = ccr.ConsumerInfo.Name
80✔
3322

80✔
3323
                                        // Do not set si.sseq to seq here. si.sseq will be set in processInboundSourceMsg
80✔
3324
                                        si.dseq = 0
80✔
3325
                                        si.qch = make(chan struct{})
80✔
3326
                                        // Set the last seen as now so that we don't fail at the first check.
80✔
3327
                                        si.last.Store(time.Now().UnixNano())
80✔
3328

80✔
3329
                                        msgs := mset.smsgs
80✔
3330
                                        sub, err := mset.subscribeInternal(deliverSubject, func(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
8,074✔
3331
                                                hdr, msg := c.msgParts(copyBytes(rmsg)) // Need to copy.
7,994✔
3332
                                                mset.queueInbound(msgs, subject, reply, hdr, msg, si, nil)
7,994✔
3333
                                                si.last.Store(time.Now().UnixNano())
7,994✔
3334
                                        })
7,994✔
3335
                                        if err != nil {
80✔
3336
                                                si.err = NewJSSourceConsumerSetupFailedError(err, Unless(err))
×
3337
                                                retry = true
×
3338
                                                mset.mu.Unlock()
×
3339
                                                return
×
3340
                                        }
×
3341
                                        // Save our sub.
3342
                                        si.sub = sub
80✔
3343
                                }
3344
                        }
3345
                        mset.mu.Unlock()
80✔
3346
                case <-time.After(srcConsumerWaitTime):
5✔
3347
                        mset.unsubscribe(crSub)
5✔
3348
                        // We already waited 30 seconds, let's retry now.
5✔
3349
                        retry = true
5✔
3350
                }
3351
        }()
3352
}
3353

3354
// This will process all inbound source msgs.
3355
// We mux them into one go routine to avoid lock contention and high cpu and thread thrashing.
3356
// TODO(dlc) make this more then one and pin sources to one of a group.
3357
func (mset *stream) processAllSourceMsgs() {
48✔
3358
        s := mset.srv
48✔
3359
        defer s.grWG.Done()
48✔
3360

48✔
3361
        mset.mu.RLock()
48✔
3362
        msgs, qch := mset.smsgs, mset.qch
48✔
3363
        mset.mu.RUnlock()
48✔
3364

48✔
3365
        t := time.NewTicker(sourceHealthCheckInterval)
48✔
3366
        defer t.Stop()
48✔
3367

48✔
3368
        // When we detect we are no longer leader, we will cleanup.
48✔
3369
        // Should always return right after this is called.
48✔
3370
        cleanUp := func() {
48✔
3371
                mset.mu.Lock()
×
3372
                defer mset.mu.Unlock()
×
3373
                for _, si := range mset.sources {
×
3374
                        mset.cancelSourceConsumer(si.iname)
×
3375
                }
×
3376
                mset.smsgs.drain()
×
3377
                mset.smsgs.unregister()
×
3378
                mset.smsgs = nil
×
3379
        }
3380

3381
        for {
873✔
3382
                select {
825✔
3383
                case <-s.quitCh:
×
3384
                        return
×
3385
                case <-qch:
48✔
3386
                        return
48✔
3387
                case <-msgs.ch:
772✔
3388
                        ims := msgs.pop()
772✔
3389
                        for _, im := range ims {
7,010✔
3390
                                if !mset.processInboundSourceMsg(im.si, im) {
6,334✔
3391
                                        // If we are no longer leader bail.
96✔
3392
                                        if !mset.IsLeader() {
96✔
3393
                                                msgs.recycle(&ims)
×
3394
                                                cleanUp()
×
3395
                                                return
×
3396
                                        }
×
3397
                                        break
96✔
3398
                                }
3399
                                im.returnToPool()
6,142✔
3400
                        }
3401
                        msgs.recycle(&ims)
772✔
3402
                case <-t.C:
5✔
3403
                        // If we are no longer leader bail.
5✔
3404
                        if !mset.IsLeader() {
5✔
3405
                                cleanUp()
×
3406
                                return
×
3407
                        }
×
3408

3409
                        // Check health of all sources.
3410
                        var stalled []*sourceInfo
5✔
3411
                        mset.mu.RLock()
5✔
3412
                        for _, si := range mset.sources {
19✔
3413
                                if time.Since(time.Unix(0, si.last.Load())) > sourceHealthCheckInterval {
15✔
3414
                                        stalled = append(stalled, si)
1✔
3415
                                }
1✔
3416
                        }
3417
                        numSources := len(mset.sources)
5✔
3418
                        mset.mu.RUnlock()
5✔
3419

5✔
3420
                        // This can happen on an update when no longer have sources.
5✔
3421
                        if numSources == 0 {
5✔
3422
                                cleanUp()
×
3423
                                return
×
3424
                        }
×
3425

3426
                        // We do not want to block here so do in separate Go routine.
3427
                        if len(stalled) > 0 {
6✔
3428
                                go func() {
2✔
3429
                                        mset.mu.Lock()
1✔
3430
                                        defer mset.mu.Unlock()
1✔
3431
                                        for _, si := range stalled {
2✔
3432
                                                mset.setupSourceConsumer(si.iname, si.sseq+1, time.Time{})
1✔
3433
                                                si.last.Store(time.Now().UnixNano())
1✔
3434
                                        }
1✔
3435
                                }()
3436
                        }
3437
                }
3438
        }
3439
}
3440

3441
// isControlMsg determines if this is a control message.
3442
func (m *inMsg) isControlMsg() bool {
13,221✔
3443
        return len(m.msg) == 0 && len(m.hdr) > 0 && bytes.HasPrefix(m.hdr, []byte("NATS/1.0 100 "))
13,221✔
3444
}
13,221✔
3445

3446
// Sends a reply to a flow control request.
3447
func (mset *stream) sendFlowControlReply(reply string) {
×
3448
        mset.mu.RLock()
×
3449
        if mset.isLeader() && mset.outq != nil {
×
3450
                mset.outq.sendMsg(reply, nil)
×
3451
        }
×
3452
        mset.mu.RUnlock()
×
3453
}
3454

3455
// handleFlowControl will properly handle flow control messages for both R==1 and R>1.
3456
// Lock should be held.
3457
func (mset *stream) handleFlowControl(m *inMsg) {
×
3458
        // If we are clustered we will send the flow control message through the replication stack.
×
3459
        if mset.isClustered() {
×
3460
                mset.node.Propose(encodeStreamMsg(_EMPTY_, m.rply, m.hdr, nil, 0, 0, false))
×
3461
        } else {
×
3462
                mset.outq.sendMsg(m.rply, nil)
×
3463
        }
×
3464
}
3465

3466
// processInboundSourceMsg handles processing other stream messages bound for this stream.
3467
func (mset *stream) processInboundSourceMsg(si *sourceInfo, m *inMsg) bool {
6,238✔
3468
        mset.mu.Lock()
6,238✔
3469
        // If we are no longer the leader cancel this subscriber.
6,238✔
3470
        if !mset.isLeader() {
6,238✔
3471
                mset.cancelSourceConsumer(si.iname)
×
3472
                mset.mu.Unlock()
×
3473
                return false
×
3474
        }
×
3475

3476
        isControl := m.isControlMsg()
6,238✔
3477

6,238✔
3478
        // Ignore from old subscriptions.
6,238✔
3479
        if !si.isCurrentSub(m.rply) && !isControl {
6,238✔
3480
                mset.mu.Unlock()
×
3481
                return false
×
3482
        }
×
3483

3484
        // Check for heartbeats and flow control messages.
3485
        if isControl {
6,376✔
3486
                var needsRetry bool
138✔
3487
                // Flow controls have reply subjects.
138✔
3488
                if m.rply != _EMPTY_ {
138✔
3489
                        mset.handleFlowControl(m)
×
3490
                } else {
138✔
3491
                        // For idle heartbeats make sure we did not miss anything.
138✔
3492
                        if ldseq := parseInt64(getHeader(JSLastConsumerSeq, m.hdr)); ldseq > 0 && uint64(ldseq) != si.dseq {
160✔
3493
                                needsRetry = true
22✔
3494
                                mset.retrySourceConsumerAtSeq(si.iname, si.sseq+1)
22✔
3495
                        } else if fcReply := getHeader(JSConsumerStalled, m.hdr); len(fcReply) > 0 {
138✔
3496
                                // Other side thinks we are stalled, so send flow control reply.
×
3497
                                mset.outq.sendMsg(string(fcReply), nil)
×
3498
                        }
×
3499
                }
3500
                mset.mu.Unlock()
138✔
3501
                return !needsRetry
138✔
3502
        }
3503

3504
        sseq, dseq, dc, _, pending := replyInfo(m.rply)
6,100✔
3505

6,100✔
3506
        if dc > 1 {
6,100✔
3507
                mset.mu.Unlock()
×
3508
                return false
×
3509
        }
×
3510

3511
        // Tracking is done here.
3512
        if dseq == si.dseq+1 {
12,137✔
3513
                si.dseq++
6,037✔
3514
                si.sseq = sseq
6,037✔
3515
        } else if dseq > si.dseq {
6,163✔
3516
                if si.cname == _EMPTY_ {
63✔
3517
                        si.cname = tokenAt(m.rply, 4)
×
3518
                        si.dseq, si.sseq = dseq, sseq
×
3519
                } else {
63✔
3520
                        mset.retrySourceConsumerAtSeq(si.iname, si.sseq+1)
63✔
3521
                        mset.mu.Unlock()
63✔
3522
                        return false
63✔
3523
                }
63✔
3524
        } else {
×
3525
                mset.mu.Unlock()
×
3526
                return false
×
3527
        }
×
3528

3529
        if pending == 0 {
6,643✔
3530
                si.lag = 0
606✔
3531
        } else {
6,037✔
3532
                si.lag = pending - 1
5,431✔
3533
        }
5,431✔
3534
        node := mset.node
6,037✔
3535
        mset.mu.Unlock()
6,037✔
3536

6,037✔
3537
        hdr, msg := m.hdr, m.msg
6,037✔
3538

6,037✔
3539
        // If we are daisy chained here make sure to remove the original one.
6,037✔
3540
        if len(hdr) > 0 {
6,045✔
3541
                hdr = removeHeaderIfPresent(hdr, JSStreamSource)
8✔
3542
                // Remove any Nats-Expected- headers as we don't want to validate them.
8✔
3543
                hdr = removeHeaderIfPrefixPresent(hdr, "Nats-Expected-")
8✔
3544
        }
8✔
3545
        // Hold onto the origin reply which has all the metadata.
3546
        hdr = genHeader(hdr, JSStreamSource, si.genSourceHeader(m.rply))
6,037✔
3547

6,037✔
3548
        // Do the subject transform for the source if there's one
6,037✔
3549
        if len(si.trs) > 0 {
6,117✔
3550
                for _, tr := range si.trs {
180✔
3551
                        if tr == nil {
120✔
3552
                                continue
20✔
3553
                        } else {
80✔
3554
                                tsubj, err := tr.Match(m.subj)
80✔
3555
                                if err == nil {
140✔
3556
                                        m.subj = tsubj
60✔
3557
                                        break
60✔
3558
                                }
3559
                        }
3560
                }
3561
        }
3562

3563
        var err error
6,037✔
3564
        // If we are clustered we need to propose this message to the underlying raft group.
6,037✔
3565
        if node != nil {
8,262✔
3566
                err = mset.processClusteredInboundMsg(m.subj, _EMPTY_, hdr, msg, nil, true)
2,225✔
3567
        } else {
6,037✔
3568
                err = mset.processJetStreamMsg(m.subj, _EMPTY_, hdr, msg, 0, 0, nil, true)
3,812✔
3569
        }
3,812✔
3570

3571
        if err != nil {
6,048✔
3572
                s := mset.srv
11✔
3573
                if strings.Contains(err.Error(), "no space left") {
11✔
3574
                        s.Errorf("JetStream out of space, will be DISABLED")
×
3575
                        s.DisableJetStream()
×
3576
                } else {
11✔
3577
                        mset.mu.RLock()
11✔
3578
                        accName, sname, iName := mset.acc.Name, mset.cfg.Name, si.iname
11✔
3579
                        mset.mu.RUnlock()
11✔
3580

11✔
3581
                        // Can happen temporarily all the time during normal operations when the sourcing stream
11✔
3582
                        // is working queue/interest with a limit and discard new.
11✔
3583
                        // TODO - Improve sourcing to WQ with limit and new to use flow control rather than re-creating the consumer.
11✔
3584
                        if errors.Is(err, ErrMaxMsgs) || errors.Is(err, ErrMaxBytes) {
22✔
3585
                                // Do not need to do a full retry that includes finding the last sequence in the stream
11✔
3586
                                // for that source. Just re-create starting with the seq we couldn't store instead.
11✔
3587
                                mset.mu.Lock()
11✔
3588
                                mset.retrySourceConsumerAtSeq(iName, si.sseq)
11✔
3589
                                mset.mu.Unlock()
11✔
3590
                        } else {
11✔
3591
                                // Log some warning for errors other than errLastSeqMismatch or errMaxMsgs.
×
3592
                                if !errors.Is(err, errLastSeqMismatch) {
×
3593
                                        s.RateLimitWarnf("Error processing inbound source %q for '%s' > '%s': %v",
×
3594
                                                iName, accName, sname, err)
×
3595
                                }
×
3596
                                // Retry in all type of errors if we are still leader.
3597
                                if mset.isLeader() {
×
3598
                                        // This will make sure the source is still in mset.sources map,
×
3599
                                        // find the last sequence and then call setupSourceConsumer.
×
3600
                                        iNameMap := map[string]struct{}{iName: {}}
×
3601
                                        mset.setStartingSequenceForSources(iNameMap)
×
3602
                                        mset.mu.Lock()
×
3603
                                        mset.retrySourceConsumerAtSeq(iName, si.sseq+1)
×
3604
                                        mset.mu.Unlock()
×
3605
                                }
×
3606
                        }
3607
                }
3608
                return false
11✔
3609
        }
3610

3611
        return true
6,026✔
3612
}
3613

3614
// Generate a new (2.10) style source header (stream name, sequence number, source filter, source destination transform).
3615
func (si *sourceInfo) genSourceHeader(reply string) string {
6,037✔
3616
        var b strings.Builder
6,037✔
3617
        iNameParts := strings.Split(si.iname, " ")
6,037✔
3618

6,037✔
3619
        b.WriteString(iNameParts[0])
6,037✔
3620
        b.WriteByte(' ')
6,037✔
3621
        // Grab sequence as text here from reply subject.
6,037✔
3622
        var tsa [expectedNumReplyTokens]string
6,037✔
3623
        start, tokens := 0, tsa[:0]
6,037✔
3624
        for i := 0; i < len(reply); i++ {
339,694✔
3625
                if reply[i] == btsep {
381,953✔
3626
                        tokens, start = append(tokens, reply[start:i]), i+1
48,296✔
3627
                }
48,296✔
3628
        }
3629
        tokens = append(tokens, reply[start:])
6,037✔
3630
        seq := "1" // Default
6,037✔
3631
        if len(tokens) == expectedNumReplyTokens && tokens[0] == "$JS" && tokens[1] == "ACK" {
12,074✔
3632
                seq = tokens[5]
6,037✔
3633
        }
6,037✔
3634
        b.WriteString(seq)
6,037✔
3635

6,037✔
3636
        b.WriteByte(' ')
6,037✔
3637
        b.WriteString(iNameParts[1])
6,037✔
3638
        b.WriteByte(' ')
6,037✔
3639
        b.WriteString(iNameParts[2])
6,037✔
3640
        return b.String()
6,037✔
3641
}
3642

3643
// Original version of header that stored ack reply direct.
3644
func streamAndSeqFromAckReply(reply string) (string, string, uint64) {
×
3645
        tsa := [expectedNumReplyTokens]string{}
×
3646
        start, tokens := 0, tsa[:0]
×
3647
        for i := 0; i < len(reply); i++ {
×
3648
                if reply[i] == btsep {
×
3649
                        tokens, start = append(tokens, reply[start:i]), i+1
×
3650
                }
×
3651
        }
3652
        tokens = append(tokens, reply[start:])
×
3653
        if len(tokens) != expectedNumReplyTokens || tokens[0] != "$JS" || tokens[1] != "ACK" {
×
3654
                return _EMPTY_, _EMPTY_, 0
×
3655
        }
×
3656
        return tokens[2], _EMPTY_, uint64(parseAckReplyNum(tokens[5]))
×
3657
}
3658

3659
// Extract the stream name, the source index name and the message sequence number from the source header.
3660
// Uses the filter and transform arguments to provide backwards compatibility
3661
func streamAndSeq(shdr string) (string, string, uint64) {
464✔
3662
        if strings.HasPrefix(shdr, jsAckPre) {
464✔
3663
                return streamAndSeqFromAckReply(shdr)
×
3664
        }
×
3665
        // New version which is stream index name <SPC> sequence
3666
        fields := strings.Split(shdr, " ")
464✔
3667
        nFields := len(fields)
464✔
3668

464✔
3669
        if nFields != 2 && nFields <= 3 {
464✔
3670
                return _EMPTY_, _EMPTY_, 0
×
3671
        }
×
3672

3673
        if nFields >= 4 {
927✔
3674
                return fields[0], strings.Join([]string{fields[0], fields[2], fields[3]}, " "), uint64(parseAckReplyNum(fields[1]))
463✔
3675
        } else {
464✔
3676
                return fields[0], _EMPTY_, uint64(parseAckReplyNum(fields[1]))
1✔
3677
        }
1✔
3678

3679
}
3680

3681
// Lock should be held.
3682
func (mset *stream) setStartingSequenceForSources(iNames map[string]struct{}) {
15✔
3683
        var state StreamState
15✔
3684
        mset.store.FastState(&state)
15✔
3685

15✔
3686
        // Do not reset sseq here so we can remember when purge/expiration happens.
15✔
3687
        if state.Msgs == 0 {
22✔
3688
                for iName := range iNames {
14✔
3689
                        si := mset.sources[iName]
7✔
3690
                        if si == nil {
7✔
3691
                                continue
×
3692
                        } else {
7✔
3693
                                si.dseq = 0
7✔
3694
                        }
7✔
3695
                }
3696
                return
7✔
3697
        }
3698

3699
        var smv StoreMsg
8✔
3700
        for seq := state.LastSeq; seq >= state.FirstSeq; {
364✔
3701
                sm, err := mset.store.LoadPrevMsg(seq, &smv)
356✔
3702
                if err == ErrStoreEOF || err != nil {
356✔
3703
                        break
×
3704
                }
3705
                seq = sm.seq - 1
356✔
3706
                if len(sm.hdr) == 0 {
356✔
3707
                        continue
×
3708
                }
3709

3710
                ss := getHeader(JSStreamSource, sm.hdr)
356✔
3711
                if len(ss) == 0 {
356✔
3712
                        continue
×
3713
                }
3714
                streamName, indexName, sseq := streamAndSeq(bytesToString(ss))
356✔
3715

356✔
3716
                if _, ok := iNames[indexName]; ok {
358✔
3717
                        si := mset.sources[indexName]
2✔
3718
                        si.sseq = sseq
2✔
3719
                        si.dseq = 0
2✔
3720
                        delete(iNames, indexName)
2✔
3721
                } else if indexName == _EMPTY_ && streamName != _EMPTY_ {
357✔
3722
                        for iName := range iNames {
2✔
3723
                                // TODO streamSource is a linear walk, to optimize later
1✔
3724
                                if si := mset.sources[iName]; si != nil && streamName == si.name ||
1✔
3725
                                        (mset.streamSource(iName).External != nil && streamName == si.name+":"+getHash(mset.streamSource(iName).External.ApiPrefix)) {
2✔
3726
                                        si.sseq = sseq
1✔
3727
                                        si.dseq = 0
1✔
3728
                                        delete(iNames, iName)
1✔
3729
                                        break
1✔
3730
                                }
3731
                        }
3732
                }
3733
                if len(iNames) == 0 {
362✔
3734
                        break
6✔
3735
                }
3736
        }
3737
}
3738

3739
// Resets the SourceInfo for all the sources
3740
// lock should be held.
3741
func (mset *stream) resetSourceInfo() {
124✔
3742
        // Reset if needed.
124✔
3743
        mset.stopSourceConsumers()
124✔
3744
        mset.sources = make(map[string]*sourceInfo)
124✔
3745

124✔
3746
        for _, ssi := range mset.cfg.Sources {
318✔
3747
                if ssi.iname == _EMPTY_ {
299✔
3748
                        ssi.setIndexName()
105✔
3749
                }
105✔
3750

3751
                var si *sourceInfo
194✔
3752

194✔
3753
                if len(ssi.SubjectTransforms) == 0 {
378✔
3754
                        si = &sourceInfo{name: ssi.Name, iname: ssi.iname, sf: ssi.FilterSubject}
184✔
3755
                } else {
194✔
3756
                        sfs := make([]string, len(ssi.SubjectTransforms))
10✔
3757
                        trs := make([]*subjectTransform, len(ssi.SubjectTransforms))
10✔
3758
                        for i, str := range ssi.SubjectTransforms {
24✔
3759
                                tr, err := NewSubjectTransform(str.Source, str.Destination)
14✔
3760
                                if err != nil {
14✔
3761
                                        mset.srv.Errorf("Unable to get subject transform for source: %v", err)
×
3762
                                }
×
3763
                                sfs[i] = str.Source
14✔
3764
                                trs[i] = tr
14✔
3765
                        }
3766
                        si = &sourceInfo{name: ssi.Name, iname: ssi.iname, sfs: sfs, trs: trs}
10✔
3767
                }
3768
                mset.sources[ssi.iname] = si
194✔
3769
        }
3770
}
3771

3772
// This will do a reverse scan on startup or leader election
3773
// searching for the starting sequence number.
3774
// This can be slow in degenerative cases.
3775
// Lock should be held.
3776
func (mset *stream) startingSequenceForSources() {
58✔
3777
        if len(mset.cfg.Sources) == 0 {
58✔
3778
                return
×
3779
        }
×
3780

3781
        // Always reset here.
3782
        mset.resetSourceInfo()
58✔
3783

58✔
3784
        var state StreamState
58✔
3785
        mset.store.FastState(&state)
58✔
3786

58✔
3787
        // Bail if no messages, meaning no context.
58✔
3788
        if state.Msgs == 0 {
111✔
3789
                return
53✔
3790
        }
53✔
3791

3792
        // For short circuiting return.
3793
        expected := len(mset.cfg.Sources)
5✔
3794
        seqs := make(map[string]uint64)
5✔
3795

5✔
3796
        // Stamp our si seq records on the way out.
5✔
3797
        defer func() {
10✔
3798
                for sname, seq := range seqs {
11✔
3799
                        // Ignore if not set.
6✔
3800
                        if seq == 0 {
6✔
3801
                                continue
×
3802
                        }
3803
                        if si := mset.sources[sname]; si != nil {
12✔
3804
                                si.sseq = seq
6✔
3805
                                si.dseq = 0
6✔
3806
                        }
6✔
3807
                }
3808
        }()
3809

3810
        update := func(iName string, seq uint64) {
111✔
3811
                // Only update active in case we have older ones in here that got configured out.
106✔
3812
                if si := mset.sources[iName]; si != nil {
212✔
3813
                        if _, ok := seqs[iName]; !ok {
112✔
3814
                                seqs[iName] = seq
6✔
3815
                        }
6✔
3816
                }
3817
        }
3818

3819
        var smv StoreMsg
5✔
3820
        for seq := state.LastSeq; ; {
112✔
3821
                sm, err := mset.store.LoadPrevMsg(seq, &smv)
107✔
3822
                if err == ErrStoreEOF || err != nil {
108✔
3823
                        break
1✔
3824
                }
3825
                seq = sm.seq - 1
106✔
3826
                if len(sm.hdr) == 0 {
106✔
3827
                        continue
×
3828
                }
3829
                ss := getHeader(JSStreamSource, sm.hdr)
106✔
3830
                if len(ss) == 0 {
106✔
3831
                        continue
×
3832
                }
3833

3834
                streamName, iName, sseq := streamAndSeq(bytesToString(ss))
106✔
3835
                if iName == _EMPTY_ { // Pre-2.10 message header means it's a match for any source using that stream name
106✔
3836
                        for _, ssi := range mset.cfg.Sources {
×
3837
                                if streamName == ssi.Name || (ssi.External != nil && streamName == ssi.Name+":"+getHash(ssi.External.ApiPrefix)) {
×
3838
                                        update(ssi.iname, sseq)
×
3839
                                }
×
3840
                        }
3841
                } else {
106✔
3842
                        update(iName, sseq)
106✔
3843
                }
106✔
3844
                if len(seqs) == expected {
110✔
3845
                        return
4✔
3846
                }
4✔
3847
        }
3848
}
3849

3850
// Setup our source consumers.
3851
// Lock should be held.
3852
func (mset *stream) setupSourceConsumers() error {
60✔
3853
        if mset.outq == nil {
60✔
3854
                return errors.New("outq required")
×
3855
        }
×
3856
        // Reset if needed.
3857
        for _, si := range mset.sources {
150✔
3858
                if si.sub != nil {
90✔
3859
                        mset.cancelSourceConsumer(si.iname)
×
3860
                }
×
3861
        }
3862

3863
        // If we are no longer the leader, give up
3864
        if !mset.isLeader() {
62✔
3865
                return nil
2✔
3866
        }
2✔
3867

3868
        mset.startingSequenceForSources()
58✔
3869

58✔
3870
        // Setup our consumers at the proper starting position.
58✔
3871
        for _, ssi := range mset.cfg.Sources {
137✔
3872
                if si := mset.sources[ssi.iname]; si != nil {
158✔
3873
                        mset.setupSourceConsumer(ssi.iname, si.sseq+1, time.Time{})
79✔
3874
                }
79✔
3875
        }
3876

3877
        return nil
58✔
3878
}
3879

3880
// Will create internal subscriptions for the stream.
3881
// Lock should be held.
3882
func (mset *stream) subscribeToStream() error {
3,867✔
3883
        if mset.active {
3,901✔
3884
                return nil
34✔
3885
        }
34✔
3886
        for _, subject := range mset.cfg.Subjects {
7,849✔
3887
                if _, err := mset.subscribeInternal(subject, mset.processInboundJetStreamMsg); err != nil {
4,016✔
3888
                        return err
×
3889
                }
×
3890
        }
3891
        // Check if we need to setup mirroring.
3892
        if mset.cfg.Mirror != nil {
3,895✔
3893
                // setup the initial mirror sourceInfo
62✔
3894
                mset.mirror = &sourceInfo{name: mset.cfg.Mirror.Name}
62✔
3895
                sfs := make([]string, len(mset.cfg.Mirror.SubjectTransforms))
62✔
3896
                trs := make([]*subjectTransform, len(mset.cfg.Mirror.SubjectTransforms))
62✔
3897

62✔
3898
                for i, tr := range mset.cfg.Mirror.SubjectTransforms {
69✔
3899
                        // will not fail as already checked before that the transform will work
7✔
3900
                        subjectTransform, err := NewSubjectTransform(tr.Source, tr.Destination)
7✔
3901
                        if err != nil {
7✔
3902
                                mset.srv.Errorf("Unable to get transform for mirror consumer: %v", err)
×
3903
                        }
×
3904

3905
                        sfs[i] = tr.Source
7✔
3906
                        trs[i] = subjectTransform
7✔
3907
                }
3908
                mset.mirror.sfs = sfs
62✔
3909
                mset.mirror.trs = trs
62✔
3910
                // delay the actual mirror consumer creation for after a delay
62✔
3911
                mset.scheduleSetupMirrorConsumerRetry()
62✔
3912
        } else if len(mset.cfg.Sources) > 0 && mset.sourcesConsumerSetup == nil {
3,837✔
3913
                // Setup the initial source infos for the sources
66✔
3914
                mset.resetSourceInfo()
66✔
3915
                // Delay the actual source consumer(s) creation(s) for after a delay if a replicated stream.
66✔
3916
                // If it's an R1, this is done at startup and we will do inline.
66✔
3917
                if mset.cfg.Replicas == 1 {
102✔
3918
                        mset.setupSourceConsumers()
36✔
3919
                } else {
66✔
3920
                        mset.sourcesConsumerSetup = time.AfterFunc(time.Duration(rand.Intn(int(500*time.Millisecond)))+100*time.Millisecond, func() {
54✔
3921
                                mset.mu.Lock()
24✔
3922
                                mset.setupSourceConsumers()
24✔
3923
                                mset.mu.Unlock()
24✔
3924
                        })
24✔
3925
                }
3926
        }
3927
        // Check for direct get access.
3928
        // We spin up followers for clustered streams in monitorStream().
3929
        if mset.cfg.AllowDirect {
3,879✔
3930
                if err := mset.subscribeToDirect(); err != nil {
46✔
3931
                        return err
×
3932
                }
×
3933
        }
3934

3935
        mset.active = true
3,833✔
3936
        return nil
3,833✔
3937
}
3938

3939
// Lock should be held.
3940
func (mset *stream) subscribeToDirect() error {
56✔
3941
        // We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
56✔
3942
        if mset.directSub == nil {
112✔
3943
                dsubj := fmt.Sprintf(JSDirectMsgGetT, mset.cfg.Name)
56✔
3944
                if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetRequest); err == nil {
112✔
3945
                        mset.directSub = sub
56✔
3946
                } else {
56✔
3947
                        return err
×
3948
                }
×
3949
        }
3950
        // Now the one that will have subject appended past stream name.
3951
        if mset.lastBySub == nil {
112✔
3952
                dsubj := fmt.Sprintf(JSDirectGetLastBySubjectT, mset.cfg.Name, fwcs)
56✔
3953
                // We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
56✔
3954
                if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetLastBySubjectRequest); err == nil {
112✔
3955
                        mset.lastBySub = sub
56✔
3956
                } else {
56✔
3957
                        return err
×
3958
                }
×
3959
        }
3960

3961
        return nil
56✔
3962
}
3963

3964
// Lock should be held.
3965
func (mset *stream) unsubscribeToDirect() {
5,435✔
3966
        if mset.directSub != nil {
5,491✔
3967
                mset.unsubscribe(mset.directSub)
56✔
3968
                mset.directSub = nil
56✔
3969
        }
56✔
3970
        if mset.lastBySub != nil {
5,491✔
3971
                mset.unsubscribe(mset.lastBySub)
56✔
3972
                mset.lastBySub = nil
56✔
3973
        }
56✔
3974
}
3975

3976
// Lock should be held.
3977
func (mset *stream) subscribeToMirrorDirect() error {
4✔
3978
        if mset.mirror == nil {
4✔
3979
                return nil
×
3980
        }
×
3981

3982
        // We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
3983
        if mset.mirror.dsub == nil {
8✔
3984
                dsubj := fmt.Sprintf(JSDirectMsgGetT, mset.mirror.name)
4✔
3985
                // We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
4✔
3986
                if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetRequest); err == nil {
8✔
3987
                        mset.mirror.dsub = sub
4✔
3988
                } else {
4✔
3989
                        return err
×
3990
                }
×
3991
        }
3992
        // Now the one that will have subject appended past stream name.
3993
        if mset.mirror.lbsub == nil {
8✔
3994
                dsubj := fmt.Sprintf(JSDirectGetLastBySubjectT, mset.mirror.name, fwcs)
4✔
3995
                // We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
4✔
3996
                if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetLastBySubjectRequest); err == nil {
8✔
3997
                        mset.mirror.lbsub = sub
4✔
3998
                } else {
4✔
3999
                        return err
×
4000
                }
×
4001
        }
4002

4003
        return nil
4✔
4004
}
4005

4006
// Stop our source consumers.
4007
// Lock should be held.
4008
func (mset *stream) stopSourceConsumers() {
4,977✔
4009
        for _, si := range mset.sources {
5,278✔
4010
                mset.cancelSourceInfo(si)
301✔
4011
        }
301✔
4012
}
4013

4014
// Lock should be held.
4015
func (mset *stream) removeInternalConsumer(si *sourceInfo) {
630✔
4016
        if si == nil || si.cname == _EMPTY_ {
1,131✔
4017
                return
501✔
4018
        }
501✔
4019
        si.cname = _EMPTY_
129✔
4020
}
4021

4022
// Will unsubscribe from the stream.
4023
// Lock should be held.
4024
func (mset *stream) unsubscribeToStream(stopping bool) error {
10,214✔
4025
        for _, subject := range mset.cfg.Subjects {
20,839✔
4026
                mset.unsubscribeInternal(subject)
10,625✔
4027
        }
10,625✔
4028
        if mset.mirror != nil {
10,276✔
4029
                mset.cancelSourceInfo(mset.mirror)
62✔
4030
                mset.mirror = nil
62✔
4031
        }
62✔
4032

4033
        if len(mset.sources) > 0 {
10,314✔
4034
                mset.stopSourceConsumers()
100✔
4035
        }
100✔
4036

4037
        // In case we had a direct get subscriptions.
4038
        if stopping {
15,647✔
4039
                mset.unsubscribeToDirect()
5,433✔
4040
        }
5,433✔
4041

4042
        mset.active = false
10,214✔
4043
        return nil
10,214✔
4044
}
4045

4046
// Lock does NOT need to be held, we set the client on setup and never change it at this point.
4047
func (mset *stream) subscribeInternal(subject string, cb msgHandler) (*subscription, error) {
4,311✔
4048
        if mset.closed.Load() {
4,311✔
4049
                return nil, errStreamClosed
×
4050
        }
×
4051
        if cb == nil {
4,311✔
4052
                return nil, errInvalidMsgHandler
×
4053
        }
×
4054
        c := mset.client
4,311✔
4055
        sid := int(mset.sid.Add(1))
4,311✔
4056
        // Now create the subscription
4,311✔
4057
        return c.processSub([]byte(subject), nil, []byte(strconv.Itoa(sid)), cb, false)
4,311✔
4058
}
4059

4060
// Lock does NOT need to be held, we set the client on setup and never change it at this point.
4061
func (mset *stream) queueSubscribeInternal(subject, group string, cb msgHandler) (*subscription, error) {
120✔
4062
        if mset.closed.Load() {
120✔
4063
                return nil, errStreamClosed
×
4064
        }
×
4065
        if cb == nil {
120✔
4066
                return nil, errInvalidMsgHandler
×
4067
        }
×
4068
        c := mset.client
120✔
4069
        sid := int(mset.sid.Add(1))
120✔
4070
        // Now create the subscription
120✔
4071
        return c.processSub([]byte(subject), []byte(group), []byte(strconv.Itoa(sid)), cb, false)
120✔
4072
}
4073

4074
// This will unsubscribe us from the exact subject given.
4075
// We do not currently track the subs so do not have the sid.
4076
// This should be called only on an update.
4077
// Lock does NOT need to be held, we set the client on setup and never change it at this point.
4078
func (mset *stream) unsubscribeInternal(subject string) error {
10,637✔
4079
        if mset.closed.Load() {
16,398✔
4080
                return errStreamClosed
5,761✔
4081
        }
5,761✔
4082
        c := mset.client
4,876✔
4083
        var sid []byte
4,876✔
4084
        c.mu.Lock()
4,876✔
4085
        for _, sub := range c.subs {
6,340✔
4086
                if subject == string(sub.subject) {
2,836✔
4087
                        sid = sub.sid
1,372✔
4088
                        break
1,372✔
4089
                }
4090
        }
4091
        c.mu.Unlock()
4,876✔
4092

4,876✔
4093
        if sid != nil {
6,248✔
4094
                return c.processUnsub(sid)
1,372✔
4095
        }
1,372✔
4096
        return nil
3,504✔
4097
}
4098

4099
// Lock should be held.
4100
func (mset *stream) unsubscribe(sub *subscription) {
393✔
4101
        if sub == nil || mset.closed.Load() {
566✔
4102
                return
173✔
4103
        }
173✔
4104
        mset.client.processUnsub(sub.sid)
220✔
4105
}
4106

4107
func (mset *stream) setupStore(fsCfg *FileStoreConfig) error {
5,417✔
4108
        mset.mu.Lock()
5,417✔
4109
        mset.created = time.Now().UTC()
5,417✔
4110

5,417✔
4111
        switch mset.cfg.Storage {
5,417✔
4112
        case MemoryStorage:
322✔
4113
                ms, err := newMemStore(&mset.cfg)
322✔
4114
                if err != nil {
322✔
4115
                        mset.mu.Unlock()
×
4116
                        return err
×
4117
                }
×
4118
                mset.store = ms
322✔
4119
        case FileStorage:
5,095✔
4120
                s := mset.srv
5,095✔
4121
                prf := s.jsKeyGen(s.getOpts().JetStreamKey, mset.acc.Name)
5,095✔
4122
                if prf != nil {
5,163✔
4123
                        // We are encrypted here, fill in correct cipher selection.
68✔
4124
                        fsCfg.Cipher = s.getOpts().JetStreamCipher
68✔
4125
                }
68✔
4126
                oldprf := s.jsKeyGen(s.getOpts().JetStreamOldKey, mset.acc.Name)
5,095✔
4127
                cfg := *fsCfg
5,095✔
4128
                cfg.srv = s
5,095✔
4129
                fs, err := newFileStoreWithCreated(cfg, mset.cfg, mset.created, prf, oldprf)
5,095✔
4130
                if err != nil {
5,096✔
4131
                        mset.mu.Unlock()
1✔
4132
                        return err
1✔
4133
                }
1✔
4134
                mset.store = fs
5,094✔
4135
        }
4136
        // This will fire the callback but we do not require the lock since md will be 0 here.
4137
        mset.store.RegisterStorageUpdates(mset.storeUpdates)
5,416✔
4138
        mset.store.RegisterStorageRemoveMsg(func(seq uint64) {
5,516✔
4139
                if mset.IsClustered() {
191✔
4140
                        if mset.IsLeader() {
122✔
4141
                                mset.mu.RLock()
31✔
4142
                                md := streamMsgDelete{Seq: seq, NoErase: true, Stream: mset.cfg.Name}
31✔
4143
                                mset.node.Propose(encodeMsgDelete(&md))
31✔
4144
                                mset.mu.RUnlock()
31✔
4145
                        }
31✔
4146
                } else {
9✔
4147
                        mset.removeMsg(seq)
9✔
4148
                }
9✔
4149
        })
4150
        mset.store.RegisterSubjectDeleteMarkerUpdates(func(im *inMsg) {
5,523✔
4151
                if mset.IsClustered() {
205✔
4152
                        if mset.IsLeader() {
132✔
4153
                                mset.processClusteredInboundMsg(im.subj, im.rply, im.hdr, im.msg, im.mt, false)
34✔
4154
                        }
34✔
4155
                } else {
9✔
4156
                        mset.processJetStreamMsg(im.subj, im.rply, im.hdr, im.msg, 0, 0, im.mt, false)
9✔
4157
                }
9✔
4158
        })
4159
        mset.mu.Unlock()
5,416✔
4160

5,416✔
4161
        return nil
5,416✔
4162
}
4163

4164
// Called for any updates to the underlying stream. We pass through the bytes to the
4165
// jetstream account. We do local processing for stream pending for consumers, but only
4166
// for removals.
4167
// Lock should not be held.
4168
func (mset *stream) storeUpdates(md, bd int64, seq uint64, subj string) {
1,787,009✔
4169
        // If we have a single negative update then we will process our consumers for stream pending.
1,787,009✔
4170
        // Purge and Store handled separately inside individual calls.
1,787,009✔
4171
        if md == -1 && seq > 0 && subj != _EMPTY_ {
1,966,705✔
4172
                // We use our consumer list mutex here instead of the main stream lock since it may be held already.
179,696✔
4173
                mset.clsMu.RLock()
179,696✔
4174
                if mset.csl != nil {
271,499✔
4175
                        mset.csl.Match(subj, func(o *consumer) {
194,173✔
4176
                                o.decStreamPending(seq, subj)
102,370✔
4177
                        })
102,370✔
4178
                } else {
87,893✔
4179
                        for _, o := range mset.cList {
87,893✔
4180
                                o.decStreamPending(seq, subj)
×
4181
                        }
×
4182
                }
4183
                mset.clsMu.RUnlock()
179,696✔
4184
        } else if md < 0 {
1,608,063✔
4185
                // Batch decrements we need to force consumers to re-calculate num pending.
750✔
4186
                mset.clsMu.RLock()
750✔
4187
                for _, o := range mset.cList {
802✔
4188
                        o.streamNumPendingLocked()
52✔
4189
                }
52✔
4190
                mset.clsMu.RUnlock()
750✔
4191
        }
4192

4193
        if mset.jsa != nil {
3,574,018✔
4194
                mset.jsa.updateUsage(mset.tier, mset.stype, bd)
1,787,009✔
4195
        }
1,787,009✔
4196
}
4197

4198
// NumMsgIds returns the number of message ids being tracked for duplicate suppression.
4199
func (mset *stream) numMsgIds() int {
16✔
4200
        mset.mu.Lock()
16✔
4201
        defer mset.mu.Unlock()
16✔
4202
        if !mset.ddloaded {
17✔
4203
                mset.rebuildDedupe()
1✔
4204
        }
1✔
4205
        return len(mset.ddmap)
16✔
4206
}
4207

4208
// checkMsgId will process and check for duplicates.
4209
// Lock should be held.
4210
func (mset *stream) checkMsgId(id string) *ddentry {
231,204✔
4211
        if !mset.ddloaded {
231,206✔
4212
                mset.rebuildDedupe()
2✔
4213
        }
2✔
4214
        if id == _EMPTY_ || len(mset.ddmap) == 0 {
231,231✔
4215
                return nil
27✔
4216
        }
27✔
4217
        return mset.ddmap[id]
231,177✔
4218
}
4219

4220
// Will purge the entries that are past the window.
4221
// Should be called from a timer.
4222
func (mset *stream) purgeMsgIds() {
3✔
4223
        mset.mu.Lock()
3✔
4224
        defer mset.mu.Unlock()
3✔
4225

3✔
4226
        now := time.Now().UnixNano()
3✔
4227
        tmrNext := mset.cfg.Duplicates
3✔
4228
        window := int64(tmrNext)
3✔
4229

3✔
4230
        for i, dde := range mset.ddarr[mset.ddindex:] {
13✔
4231
                if now-dde.ts >= window {
19✔
4232
                        delete(mset.ddmap, dde.id)
9✔
4233
                } else {
10✔
4234
                        mset.ddindex += i
1✔
4235
                        // Check if we should garbage collect here if we are 1/3 total size.
1✔
4236
                        if cap(mset.ddarr) > 3*(len(mset.ddarr)-mset.ddindex) {
1✔
4237
                                mset.ddarr = append([]*ddentry(nil), mset.ddarr[mset.ddindex:]...)
×
4238
                                mset.ddindex = 0
×
4239
                        }
×
4240
                        tmrNext = time.Duration(window - (now - dde.ts))
1✔
4241
                        break
1✔
4242
                }
4243
        }
4244
        if len(mset.ddmap) > 0 {
4✔
4245
                // Make sure to not fire too quick
1✔
4246
                const minFire = 50 * time.Millisecond
1✔
4247
                if tmrNext < minFire {
1✔
4248
                        tmrNext = minFire
×
4249
                }
×
4250
                if mset.ddtmr != nil {
2✔
4251
                        mset.ddtmr.Reset(tmrNext)
1✔
4252
                } else {
1✔
4253
                        mset.ddtmr = time.AfterFunc(tmrNext, mset.purgeMsgIds)
×
4254
                }
×
4255
        } else {
2✔
4256
                if mset.ddtmr != nil {
4✔
4257
                        mset.ddtmr.Stop()
2✔
4258
                        mset.ddtmr = nil
2✔
4259
                }
2✔
4260
                mset.ddmap = nil
2✔
4261
                mset.ddarr = nil
2✔
4262
                mset.ddindex = 0
2✔
4263
        }
4264
}
4265

4266
// storeMsgIdLocked will store the message id for duplicate detection.
4267
// Lock should be held.
4268
func (mset *stream) storeMsgIdLocked(dde *ddentry) {
934,737✔
4269
        if mset.ddmap == nil {
934,800✔
4270
                mset.ddmap = make(map[string]*ddentry)
63✔
4271
        }
63✔
4272
        mset.ddmap[dde.id] = dde
934,737✔
4273
        mset.ddarr = append(mset.ddarr, dde)
934,737✔
4274
        if mset.ddtmr == nil {
934,800✔
4275
                mset.ddtmr = time.AfterFunc(mset.cfg.Duplicates, mset.purgeMsgIds)
63✔
4276
        }
63✔
4277
}
4278

4279
// Fast lookup of msgId.
4280
func getMsgId(hdr []byte) string {
1,199,223✔
4281
        return string(getHeader(JSMsgId, hdr))
1,199,223✔
4282
}
1,199,223✔
4283

4284
// Fast lookup of expected last msgId.
4285
func getExpectedLastMsgId(hdr []byte) string {
529,323✔
4286
        return string(getHeader(JSExpectedLastMsgId, hdr))
529,323✔
4287
}
529,323✔
4288

4289
// Fast lookup of expected stream.
4290
func getExpectedStream(hdr []byte) string {
258,744✔
4291
        return string(getHeader(JSExpectedStream, hdr))
258,744✔
4292
}
258,744✔
4293

4294
// Fast lookup of expected stream.
4295
func getExpectedLastSeq(hdr []byte) (uint64, bool) {
529,329✔
4296
        bseq := getHeader(JSExpectedLastSeq, hdr)
529,329✔
4297
        if len(bseq) == 0 {
1,058,649✔
4298
                return 0, false
529,320✔
4299
        }
529,320✔
4300
        return uint64(parseInt64(bseq)), true
9✔
4301
}
4302

4303
// Fast lookup of rollups.
4304
func getRollup(hdr []byte) string {
529,318✔
4305
        r := getHeader(JSMsgRollup, hdr)
529,318✔
4306
        if len(r) == 0 {
1,058,495✔
4307
                return _EMPTY_
529,177✔
4308
        }
529,177✔
4309
        return strings.ToLower(string(r))
141✔
4310
}
4311

4312
// Fast lookup of expected stream sequence per subject.
4313
func getExpectedLastSeqPerSubject(hdr []byte) (uint64, bool) {
740,943✔
4314
        bseq := getHeader(JSExpectedLastSubjSeq, hdr)
740,943✔
4315
        if len(bseq) == 0 {
1,481,238✔
4316
                return 0, false
740,295✔
4317
        }
740,295✔
4318
        return uint64(parseInt64(bseq)), true
648✔
4319
}
4320

4321
// Fast lookup of expected subject for the expected stream sequence per subject.
4322
func getExpectedLastSeqPerSubjectForSubject(hdr []byte) string {
648✔
4323
        return string(getHeader(JSExpectedLastSubjSeqSubj, hdr))
648✔
4324
}
648✔
4325

4326
// Fast lookup of the message TTL from headers:
4327
// - Positive return value: duration in seconds.
4328
// - Zero return value: no TTL or parse error.
4329
// - Negative return value: never expires.
4330
func getMessageTTL(hdr []byte) (int64, error) {
2,884,879✔
4331
        ttl := getHeader(JSMessageTTL, hdr)
2,884,879✔
4332
        if len(ttl) == 0 {
5,718,771✔
4333
                return 0, nil
2,833,892✔
4334
        }
2,833,892✔
4335
        return parseMessageTTL(bytesToString(ttl))
50,987✔
4336
}
4337

4338
// - Positive return value: duration in seconds.
4339
// - Zero return value: no TTL or parse error.
4340
// - Negative return value: never expires.
4341
func parseMessageTTL(ttl string) (int64, error) {
50,987✔
4342
        if strings.ToLower(ttl) == "never" {
51,021✔
4343
                return -1, nil
34✔
4344
        }
34✔
4345
        dur, err := time.ParseDuration(ttl)
50,953✔
4346
        if err == nil {
101,877✔
4347
                if dur < time.Second {
50,929✔
4348
                        return 0, NewJSMessageTTLInvalidError()
5✔
4349
                }
5✔
4350
                return int64(dur.Seconds()), nil
50,919✔
4351
        }
4352
        t := parseInt64(stringToBytes(ttl))
29✔
4353
        if t < 0 {
34✔
4354
                // This probably means a parse failure, hence why
5✔
4355
                // we have a special case "never" for returning -1.
5✔
4356
                // Otherwise we can't know if it's a genuine TTL
5✔
4357
                // that says never expire or if it's a parse error.
5✔
4358
                return 0, NewJSMessageTTLInvalidError()
5✔
4359
        }
5✔
4360
        return t, nil
24✔
4361
}
4362

4363
// Signal if we are clustered. Will acquire rlock.
4364
func (mset *stream) IsClustered() bool {
536,037✔
4365
        mset.mu.RLock()
536,037✔
4366
        defer mset.mu.RUnlock()
536,037✔
4367
        return mset.isClustered()
536,037✔
4368
}
536,037✔
4369

4370
// Lock should be held.
4371
func (mset *stream) isClustered() bool {
3,832,051✔
4372
        return mset.node != nil
3,832,051✔
4373
}
3,832,051✔
4374

4375
// Used if we have to queue things internally to avoid the route/gw path.
4376
type inMsg struct {
4377
        subj string
4378
        rply string
4379
        hdr  []byte
4380
        msg  []byte
4381
        si   *sourceInfo
4382
        mt   *msgTrace
4383
}
4384

4385
var inMsgPool = sync.Pool{
4386
        New: func() any {
33,795✔
4387
                return &inMsg{}
33,795✔
4388
        },
33,795✔
4389
}
4390

4391
func (im *inMsg) returnToPool() {
716,049✔
4392
        im.subj, im.rply, im.hdr, im.msg, im.si, im.mt = _EMPTY_, _EMPTY_, nil, nil, nil, nil
716,049✔
4393
        inMsgPool.Put(im)
716,049✔
4394
}
716,049✔
4395

4396
func (mset *stream) queueInbound(ib *ipQueue[*inMsg], subj, rply string, hdr, msg []byte, si *sourceInfo, mt *msgTrace) {
717,901✔
4397
        im := inMsgPool.Get().(*inMsg)
717,901✔
4398
        im.subj, im.rply, im.hdr, im.msg, im.si, im.mt = subj, rply, hdr, msg, si, mt
717,901✔
4399
        if _, err := ib.push(im); err != nil {
718,085✔
4400
                im.returnToPool()
184✔
4401
                mset.srv.RateLimitWarnf("Dropping messages due to excessive stream ingest rate on '%s' > '%s': %s", mset.acc.Name, mset.name(), err)
184✔
4402
                if rply != _EMPTY_ {
368✔
4403
                        hdr := []byte("NATS/1.0 429 Too Many Requests\r\n\r\n")
184✔
4404
                        b, _ := json.Marshal(&JSPubAckResponse{PubAck: &PubAck{Stream: mset.cfg.Name}, Error: NewJSStreamTooManyRequestsError()})
184✔
4405
                        mset.outq.send(newJSPubMsg(rply, _EMPTY_, _EMPTY_, hdr, b, nil, 0))
184✔
4406
                }
184✔
4407
        }
4408
}
4409

4410
var dgPool = sync.Pool{
4411
        New: func() any {
14✔
4412
                return &directGetReq{}
14✔
4413
        },
14✔
4414
}
4415

4416
// For when we need to not inline the request.
4417
type directGetReq struct {
4418
        // Copy of this is correct for this.
4419
        req   JSApiMsgGetRequest
4420
        reply string
4421
}
4422

4423
// processDirectGetRequest handles direct get request for stream messages.
4424
func (mset *stream) processDirectGetRequest(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
54✔
4425
        if len(reply) == 0 {
54✔
4426
                return
×
4427
        }
×
4428
        _, msg := c.msgParts(rmsg)
54✔
4429
        if len(msg) == 0 {
55✔
4430
                hdr := []byte("NATS/1.0 408 Empty Request\r\n\r\n")
1✔
4431
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
1✔
4432
                return
1✔
4433
        }
1✔
4434
        var req JSApiMsgGetRequest
53✔
4435
        err := json.Unmarshal(msg, &req)
53✔
4436
        if err != nil {
53✔
4437
                hdr := []byte("NATS/1.0 408 Malformed Request\r\n\r\n")
×
4438
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
×
4439
                return
×
4440
        }
×
4441
        // Check if nothing set.
4442
        if req.Seq == 0 && req.LastFor == _EMPTY_ && req.NextFor == _EMPTY_ && len(req.MultiLastFor) == 0 && req.StartTime == nil {
54✔
4443
                hdr := []byte("NATS/1.0 408 Empty Request\r\n\r\n")
1✔
4444
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
1✔
4445
                return
1✔
4446
        }
1✔
4447
        // Check we don't have conflicting options set.
4448
        // We do not allow batch mode for lastFor requests.
4449
        if (req.Seq > 0 && req.LastFor != _EMPTY_) ||
52✔
4450
                (req.Seq > 0 && req.StartTime != nil) ||
52✔
4451
                (req.StartTime != nil && req.LastFor != _EMPTY_) ||
52✔
4452
                (req.LastFor != _EMPTY_ && req.NextFor != _EMPTY_) ||
52✔
4453
                (req.LastFor != _EMPTY_ && req.Batch > 0) ||
52✔
4454
                (req.LastFor != _EMPTY_ && len(req.MultiLastFor) > 0) ||
52✔
4455
                (req.NextFor != _EMPTY_ && len(req.MultiLastFor) > 0) ||
52✔
4456
                (req.UpToSeq > 0 && req.UpToTime != nil) {
56✔
4457
                hdr := []byte("NATS/1.0 408 Bad Request\r\n\r\n")
4✔
4458
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
4✔
4459
                return
4✔
4460
        }
4✔
4461

4462
        inlineOk := c.kind != ROUTER && c.kind != GATEWAY && c.kind != LEAF
48✔
4463
        if !inlineOk {
51✔
4464
                dg := dgPool.Get().(*directGetReq)
3✔
4465
                dg.req, dg.reply = req, reply
3✔
4466
                mset.gets.push(dg)
3✔
4467
        } else {
48✔
4468
                mset.getDirectRequest(&req, reply)
45✔
4469
        }
45✔
4470
}
4471

4472
// This is for direct get by last subject which is part of the subject itself.
4473
func (mset *stream) processDirectGetLastBySubjectRequest(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
12,868✔
4474
        if len(reply) == 0 {
12,868✔
4475
                return
×
4476
        }
×
4477
        _, msg := c.msgParts(rmsg)
12,868✔
4478
        // This version expects no payload.
12,868✔
4479
        if len(msg) != 0 {
12,868✔
4480
                hdr := []byte("NATS/1.0 408 Bad Request\r\n\r\n")
×
4481
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
×
4482
                return
×
4483
        }
×
4484
        // Extract the key.
4485
        var key string
12,868✔
4486
        for i, n := 0, 0; i < len(subject); i++ {
360,296✔
4487
                if subject[i] == btsep {
411,768✔
4488
                        if n == 4 {
77,208✔
4489
                                if start := i + 1; start < len(subject) {
25,736✔
4490
                                        key = subject[i+1:]
12,868✔
4491
                                }
12,868✔
4492
                                break
12,868✔
4493
                        }
4494
                        n++
51,472✔
4495
                }
4496
        }
4497
        if len(key) == 0 {
12,868✔
4498
                hdr := []byte("NATS/1.0 408 Bad Request\r\n\r\n")
×
4499
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
×
4500
                return
×
4501
        }
×
4502

4503
        req := JSApiMsgGetRequest{LastFor: key}
12,868✔
4504

12,868✔
4505
        inlineOk := c.kind != ROUTER && c.kind != GATEWAY && c.kind != LEAF
12,868✔
4506
        if !inlineOk {
23,623✔
4507
                dg := dgPool.Get().(*directGetReq)
10,755✔
4508
                dg.req, dg.reply = req, reply
10,755✔
4509
                mset.gets.push(dg)
10,755✔
4510
        } else {
12,868✔
4511
                mset.getDirectRequest(&req, reply)
2,113✔
4512
        }
2,113✔
4513
}
4514

4515
// For direct get batch and multi requests.
4516
const (
4517
        dg   = "NATS/1.0\r\nNats-Stream: %s\r\nNats-Subject: %s\r\nNats-Sequence: %d\r\nNats-Time-Stamp: %s\r\n\r\n"
4518
        dgb  = "NATS/1.0\r\nNats-Stream: %s\r\nNats-Subject: %s\r\nNats-Sequence: %d\r\nNats-Time-Stamp: %s\r\nNats-Num-Pending: %d\r\nNats-Last-Sequence: %d\r\n\r\n"
4519
        eob  = "NATS/1.0 204 EOB\r\nNats-Num-Pending: %d\r\nNats-Last-Sequence: %d\r\n\r\n"
4520
        eobm = "NATS/1.0 204 EOB\r\nNats-Num-Pending: %d\r\nNats-Last-Sequence: %d\r\nNats-UpTo-Sequence: %d\r\n\r\n"
4521
)
4522

4523
// Handle a multi request.
4524
func (mset *stream) getDirectMulti(req *JSApiMsgGetRequest, reply string) {
19✔
4525
        // TODO(dlc) - Make configurable?
19✔
4526
        const maxAllowedResponses = 1024
19✔
4527

19✔
4528
        // We hold the lock here to try to avoid changes out from underneath of us.
19✔
4529
        mset.mu.RLock()
19✔
4530
        defer mset.mu.RUnlock()
19✔
4531
        // Grab store and name.
19✔
4532
        store, name, s := mset.store, mset.cfg.Name, mset.srv
19✔
4533

19✔
4534
        // Grab MaxBytes
19✔
4535
        mb := req.MaxBytes
19✔
4536
        if mb == 0 && s != nil {
38✔
4537
                // Fill in with the server's MaxPending.
19✔
4538
                mb = int(s.opts.MaxPending)
19✔
4539
        }
19✔
4540

4541
        upToSeq := req.UpToSeq
19✔
4542
        // If we have UpToTime set get the proper sequence.
19✔
4543
        if req.UpToTime != nil {
22✔
4544
                upToSeq = store.GetSeqFromTime((*req.UpToTime).UTC())
3✔
4545
                // We need to back off one since this is used to determine start sequence normally,
3✔
4546
                // were as here we want it to be the ceiling.
3✔
4547
                upToSeq--
3✔
4548
        }
3✔
4549
        // If not set, set to the last sequence and remember that for EOB.
4550
        if upToSeq == 0 {
33✔
4551
                var state StreamState
14✔
4552
                mset.store.FastState(&state)
14✔
4553
                upToSeq = state.LastSeq
14✔
4554
        }
14✔
4555

4556
        seqs, err := store.MultiLastSeqs(req.MultiLastFor, upToSeq, maxAllowedResponses)
19✔
4557
        if err != nil {
20✔
4558
                var hdr []byte
1✔
4559
                if err == ErrTooManyResults {
2✔
4560
                        hdr = []byte("NATS/1.0 413 Too Many Results\r\n\r\n")
1✔
4561
                } else {
1✔
4562
                        hdr = []byte(fmt.Sprintf("NATS/1.0 500 %v\r\n\r\n", err))
×
4563
                }
×
4564
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
1✔
4565
                return
1✔
4566
        }
4567
        if len(seqs) == 0 {
20✔
4568
                hdr := []byte("NATS/1.0 404 No Results\r\n\r\n")
2✔
4569
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
2✔
4570
                return
2✔
4571
        }
2✔
4572

4573
        np, lseq, sentBytes, sent := uint64(len(seqs)-1), uint64(0), 0, 0
16✔
4574
        for _, seq := range seqs {
2,805✔
4575
                if seq < req.Seq {
4,557✔
4576
                        if np > 0 {
3,536✔
4577
                                np--
1,768✔
4578
                        }
1,768✔
4579
                        continue
1,768✔
4580
                }
4581
                var svp StoreMsg
1,021✔
4582
                sm, err := store.LoadMsg(seq, &svp)
1,021✔
4583
                if err != nil {
1,021✔
4584
                        hdr := []byte("NATS/1.0 404 Message Not Found\r\n\r\n")
×
4585
                        mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
×
4586
                        return
×
4587
                }
×
4588

4589
                hdr := sm.hdr
1,021✔
4590
                ts := time.Unix(0, sm.ts).UTC()
1,021✔
4591

1,021✔
4592
                if len(hdr) == 0 {
2,042✔
4593
                        hdr = fmt.Appendf(nil, dgb, name, sm.subj, sm.seq, ts.Format(time.RFC3339Nano), np, lseq)
1,021✔
4594
                } else {
1,021✔
4595
                        hdr = copyBytes(hdr)
×
4596
                        hdr = genHeader(hdr, JSStream, name)
×
4597
                        hdr = genHeader(hdr, JSSubject, sm.subj)
×
4598
                        hdr = genHeader(hdr, JSSequence, strconv.FormatUint(sm.seq, 10))
×
4599
                        hdr = genHeader(hdr, JSTimeStamp, ts.Format(time.RFC3339Nano))
×
4600
                        hdr = genHeader(hdr, JSNumPending, strconv.FormatUint(np, 10))
×
4601
                        hdr = genHeader(hdr, JSLastSequence, strconv.FormatUint(lseq, 10))
×
4602
                }
×
4603
                // Decrement num pending. This is optimization and we do not continue to look it up for these operations.
4604
                if np > 0 {
2,033✔
4605
                        np--
1,012✔
4606
                }
1,012✔
4607
                // Track our lseq
4608
                lseq = sm.seq
1,021✔
4609
                // Send out our message.
1,021✔
4610
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, sm.msg, nil, 0))
1,021✔
4611
                // Check if we have exceeded max bytes.
1,021✔
4612
                sentBytes += len(sm.subj) + len(sm.hdr) + len(sm.msg)
1,021✔
4613
                if sentBytes >= mb {
1,024✔
4614
                        break
3✔
4615
                }
4616
                sent++
1,018✔
4617
                if req.Batch > 0 && sent >= req.Batch {
1,023✔
4618
                        break
5✔
4619
                }
4620
        }
4621

4622
        // Send out EOB
4623
        hdr := fmt.Appendf(nil, eobm, np, lseq, upToSeq)
16✔
4624
        mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
16✔
4625
}
4626

4627
// Do actual work on a direct msg request.
4628
// This could be called in a Go routine if we are inline for a non-client connection.
4629
func (mset *stream) getDirectRequest(req *JSApiMsgGetRequest, reply string) {
12,916✔
4630
        // Handle multi in separate function.
12,916✔
4631
        if len(req.MultiLastFor) > 0 {
12,935✔
4632
                mset.getDirectMulti(req, reply)
19✔
4633
                return
19✔
4634
        }
19✔
4635

4636
        mset.mu.RLock()
12,897✔
4637
        store, name, s := mset.store, mset.cfg.Name, mset.srv
12,897✔
4638
        mset.mu.RUnlock()
12,897✔
4639

12,897✔
4640
        var seq uint64
12,897✔
4641
        // Lookup start seq if AsOfTime is set.
12,897✔
4642
        if req.StartTime != nil {
12,903✔
4643
                seq = store.GetSeqFromTime(*req.StartTime)
6✔
4644
        } else {
12,897✔
4645
                seq = req.Seq
12,891✔
4646
        }
12,891✔
4647

4648
        wc := subjectHasWildcard(req.NextFor)
12,897✔
4649
        // For tracking num pending if we are batch.
12,897✔
4650
        var np, lseq, validThrough uint64
12,897✔
4651
        var isBatchRequest bool
12,897✔
4652
        batch := req.Batch
12,897✔
4653
        if batch == 0 {
25,786✔
4654
                batch = 1
12,889✔
4655
        } else {
12,897✔
4656
                // This is a batch request, capture initial numPending.
8✔
4657
                isBatchRequest = true
8✔
4658
                np, validThrough = store.NumPending(seq, req.NextFor, false)
8✔
4659
        }
8✔
4660

4661
        // Grab MaxBytes
4662
        mb := req.MaxBytes
12,897✔
4663
        if mb == 0 && s != nil {
25,792✔
4664
                // Fill in with the server's MaxPending.
12,895✔
4665
                mb = int(s.opts.MaxPending)
12,895✔
4666
        }
12,895✔
4667
        // Track what we have sent.
4668
        var sentBytes int
12,897✔
4669

12,897✔
4670
        // Loop over batch, which defaults to 1.
12,897✔
4671
        for i := 0; i < batch; i++ {
25,932✔
4672
                var (
13,035✔
4673
                        svp StoreMsg
13,035✔
4674
                        sm  *StoreMsg
13,035✔
4675
                        err error
13,035✔
4676
                )
13,035✔
4677
                if seq > 0 && req.NextFor == _EMPTY_ {
13,175✔
4678
                        // Only do direct lookup for first in a batch.
140✔
4679
                        if i == 0 {
150✔
4680
                                sm, err = store.LoadMsg(seq, &svp)
10✔
4681
                        } else {
140✔
4682
                                // We want to use load next with fwcs to step over deleted msgs.
130✔
4683
                                sm, seq, err = store.LoadNextMsg(fwcs, true, seq, &svp)
130✔
4684
                        }
130✔
4685
                        // Bump for next loop if applicable.
4686
                        seq++
140✔
4687
                } else if req.NextFor != _EMPTY_ {
12,914✔
4688
                        sm, seq, err = store.LoadNextMsg(req.NextFor, wc, seq, &svp)
19✔
4689
                        seq++
19✔
4690
                } else {
12,895✔
4691
                        // Batch is not applicable here, this is checked before we get here.
12,876✔
4692
                        sm, err = store.LoadLastMsg(req.LastFor, &svp)
12,876✔
4693
                }
12,876✔
4694
                if err != nil {
13,046✔
4695
                        // For batches, if we stop early we want to do EOB logic below.
11✔
4696
                        if batch > 1 && i > 0 {
12✔
4697
                                break
1✔
4698
                        }
4699
                        hdr := []byte("NATS/1.0 404 Message Not Found\r\n\r\n")
10✔
4700
                        mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
10✔
4701
                        return
10✔
4702
                }
4703

4704
                hdr := sm.hdr
13,024✔
4705
                ts := time.Unix(0, sm.ts).UTC()
13,024✔
4706

13,024✔
4707
                if isBatchRequest {
13,169✔
4708
                        if len(hdr) == 0 {
290✔
4709
                                hdr = fmt.Appendf(nil, dgb, name, sm.subj, sm.seq, ts.Format(time.RFC3339Nano), np, lseq)
145✔
4710
                        } else {
145✔
4711
                                hdr = copyBytes(hdr)
×
4712
                                hdr = genHeader(hdr, JSStream, name)
×
4713
                                hdr = genHeader(hdr, JSSubject, sm.subj)
×
4714
                                hdr = genHeader(hdr, JSSequence, strconv.FormatUint(sm.seq, 10))
×
4715
                                hdr = genHeader(hdr, JSTimeStamp, ts.Format(time.RFC3339Nano))
×
4716
                                hdr = genHeader(hdr, JSNumPending, strconv.FormatUint(np, 10))
×
4717
                                hdr = genHeader(hdr, JSLastSequence, strconv.FormatUint(lseq, 10))
×
4718
                        }
×
4719
                        // Decrement num pending. This is optimization and we do not continue to look it up for these operations.
4720
                        np--
145✔
4721
                } else {
12,879✔
4722
                        if len(hdr) == 0 {
25,746✔
4723
                                hdr = fmt.Appendf(nil, dg, name, sm.subj, sm.seq, ts.Format(time.RFC3339Nano))
12,867✔
4724
                        } else {
12,879✔
4725
                                hdr = copyBytes(hdr)
12✔
4726
                                hdr = genHeader(hdr, JSStream, name)
12✔
4727
                                hdr = genHeader(hdr, JSSubject, sm.subj)
12✔
4728
                                hdr = genHeader(hdr, JSSequence, strconv.FormatUint(sm.seq, 10))
12✔
4729
                                hdr = genHeader(hdr, JSTimeStamp, ts.Format(time.RFC3339Nano))
12✔
4730
                        }
12✔
4731
                }
4732
                // Track our lseq
4733
                lseq = sm.seq
13,024✔
4734
                // Send out our message.
13,024✔
4735
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, sm.msg, nil, 0))
13,024✔
4736
                // Check if we have exceeded max bytes.
13,024✔
4737
                sentBytes += len(sm.subj) + len(sm.hdr) + len(sm.msg)
13,024✔
4738
                if sentBytes >= mb {
13,027✔
4739
                        break
3✔
4740
                }
4741
        }
4742

4743
        // If batch was requested send EOB.
4744
        if isBatchRequest {
12,895✔
4745
                // Update if the stream's lasts sequence has moved past our validThrough.
8✔
4746
                if mset.lastSeq() > validThrough {
8✔
4747
                        np, _ = store.NumPending(seq, req.NextFor, false)
×
4748
                }
×
4749
                hdr := fmt.Appendf(nil, eob, np, lseq)
8✔
4750
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
8✔
4751
        }
4752
}
4753

4754
// processInboundJetStreamMsg handles processing messages bound for a stream.
4755
func (mset *stream) processInboundJetStreamMsg(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
702,924✔
4756
        hdr, msg := c.msgParts(copyBytes(rmsg)) // Need to copy.
702,924✔
4757
        if mt, traceOnly := c.isMsgTraceEnabled(); mt != nil {
702,970✔
4758
                // If message is delivered, we need to disable the message trace headers
46✔
4759
                // to prevent a trace event to be generated when a stored message
46✔
4760
                // is delivered to a consumer and routed.
46✔
4761
                if !traceOnly {
50✔
4762
                        disableTraceHeaders(c, hdr)
4✔
4763
                }
4✔
4764
                // This will add the jetstream event while in the client read loop.
4765
                // Since the event will be updated in a different go routine, the
4766
                // tracing object will have a separate reference to the JS trace
4767
                // object.
4768
                mt.addJetStreamEvent(mset.name())
46✔
4769
        }
4770
        mset.queueInbound(mset.msgs, subject, reply, hdr, msg, nil, c.pa.trace)
702,924✔
4771
}
4772

4773
var (
4774
        errLastSeqMismatch   = errors.New("last sequence mismatch")
4775
        errMsgIdDuplicate    = errors.New("msgid is duplicate")
4776
        errStreamClosed      = errors.New("stream closed")
4777
        errInvalidMsgHandler = errors.New("undefined message handler")
4778
        errStreamMismatch    = errors.New("expected stream does not match")
4779
        errMsgTTLDisabled    = errors.New("message TTL disabled")
4780
)
4781

4782
// processJetStreamMsg is where we try to actually process the stream msg.
4783
func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte, lseq uint64, ts int64, mt *msgTrace, sourced bool) (retErr error) {
1,375,288✔
4784
        if mt != nil {
1,375,334✔
4785
                // Only the leader/standalone will have mt!=nil. On exit, send the
46✔
4786
                // message trace event.
46✔
4787
                defer func() {
92✔
4788
                        mt.sendEventFromJetStream(retErr)
46✔
4789
                }()
46✔
4790
        }
4791

4792
        if mset.closed.Load() {
1,375,291✔
4793
                return errStreamClosed
3✔
4794
        }
3✔
4795

4796
        mset.mu.Lock()
1,375,285✔
4797
        s, store := mset.srv, mset.store
1,375,285✔
4798

1,375,285✔
4799
        traceOnly := mt.traceOnly()
1,375,285✔
4800
        bumpCLFS := func() {
1,375,376✔
4801
                // Do not bump if tracing and not doing message delivery.
91✔
4802
                if traceOnly {
128✔
4803
                        return
37✔
4804
                }
37✔
4805
                mset.clMu.Lock()
54✔
4806
                mset.clfs++
54✔
4807
                mset.clMu.Unlock()
54✔
4808
        }
4809

4810
        // Apply the input subject transform if any
4811
        if mset.itr != nil {
1,375,302✔
4812
                ts, err := mset.itr.Match(subject)
17✔
4813
                if err == nil {
34✔
4814
                        // no filtering: if the subject doesn't map the source of the transform, don't change it
17✔
4815
                        subject = ts
17✔
4816
                }
17✔
4817
        }
4818

4819
        var accName string
1,375,285✔
4820
        if mset.acc != nil {
2,750,570✔
4821
                accName = mset.acc.Name
1,375,285✔
4822
        }
1,375,285✔
4823

4824
        js, jsa, doAck := mset.js, mset.jsa, !mset.cfg.NoAck
1,375,285✔
4825
        name, stype := mset.cfg.Name, mset.cfg.Storage
1,375,285✔
4826
        maxMsgSize := int(mset.cfg.MaxMsgSize)
1,375,285✔
4827
        numConsumers := len(mset.consumers)
1,375,285✔
4828
        interestRetention := mset.cfg.Retention == InterestPolicy
1,375,285✔
4829
        // Snapshot if we are the leader and if we can respond.
1,375,285✔
4830
        isLeader, isSealed := mset.isLeaderNodeState(), mset.cfg.Sealed
1,375,285✔
4831
        canRespond := doAck && len(reply) > 0 && isLeader
1,375,285✔
4832

1,375,285✔
4833
        var resp = &JSPubAckResponse{}
1,375,285✔
4834

1,375,285✔
4835
        // Bail here if sealed.
1,375,285✔
4836
        if isSealed {
1,375,290✔
4837
                outq := mset.outq
5✔
4838
                mset.mu.Unlock()
5✔
4839
                bumpCLFS()
5✔
4840
                if canRespond && outq != nil {
10✔
4841
                        resp.PubAck = &PubAck{Stream: name}
5✔
4842
                        resp.Error = ApiErrors[JSStreamSealedErr]
5✔
4843
                        b, _ := json.Marshal(resp)
5✔
4844
                        outq.sendMsg(reply, b)
5✔
4845
                }
5✔
4846
                return ApiErrors[JSStreamSealedErr]
5✔
4847
        }
4848

4849
        var buf [256]byte
1,375,280✔
4850
        pubAck := append(buf[:0], mset.pubAck...)
1,375,280✔
4851

1,375,280✔
4852
        // If this is a non-clustered msg and we are not considered active, meaning no active subscription, do not process.
1,375,280✔
4853
        if lseq == 0 && ts == 0 && !mset.active {
1,375,280✔
4854
                mset.mu.Unlock()
×
4855
                return nil
×
4856
        }
×
4857

4858
        // For clustering the lower layers will pass our expected lseq. If it is present check for that here.
4859
        if lseq > 0 && lseq != (mset.lseq+mset.clfs) {
1,375,289✔
4860
                isMisMatch := true
9✔
4861
                // We may be able to recover here if we have no state whatsoever, or we are a mirror.
9✔
4862
                // See if we have to adjust our starting sequence.
9✔
4863
                if mset.lseq == 0 || mset.cfg.Mirror != nil {
9✔
4864
                        var state StreamState
×
4865
                        mset.store.FastState(&state)
×
4866
                        if state.FirstSeq == 0 {
×
4867
                                mset.store.Compact(lseq + 1)
×
4868
                                mset.lseq = lseq
×
4869
                                isMisMatch = false
×
4870
                        }
×
4871
                }
4872
                // Really is a mismatch.
4873
                if isMisMatch {
18✔
4874
                        outq := mset.outq
9✔
4875
                        mset.mu.Unlock()
9✔
4876
                        if canRespond && outq != nil {
10✔
4877
                                resp.PubAck = &PubAck{Stream: name}
1✔
4878
                                resp.Error = ApiErrors[JSStreamSequenceNotMatchErr]
1✔
4879
                                b, _ := json.Marshal(resp)
1✔
4880
                                outq.sendMsg(reply, b)
1✔
4881
                        }
1✔
4882
                        return errLastSeqMismatch
9✔
4883
                }
4884
        }
4885

4886
        // If we have received this message across an account we may have request information attached.
4887
        // For now remove. TODO(dlc) - Should this be opt-in or opt-out?
4888
        if len(hdr) > 0 {
1,904,641✔
4889
                hdr = removeHeaderIfPresent(hdr, ClientInfoHdr)
529,370✔
4890
        }
529,370✔
4891

4892
        // Process additional msg headers if still present.
4893
        var msgId string
1,375,271✔
4894
        var rollupSub, rollupAll bool
1,375,271✔
4895
        isClustered := mset.isClustered()
1,375,271✔
4896

1,375,271✔
4897
        if len(hdr) > 0 {
1,904,631✔
4898
                outq := mset.outq
529,360✔
4899

529,360✔
4900
                // Certain checks have already been performed if in clustered mode, so only check if not.
529,360✔
4901
                // Note, for cluster mode but with message tracing (without message delivery), we need
529,360✔
4902
                // to do this check here since it was not done in processClusteredInboundMsg().
529,360✔
4903
                if !isClustered || traceOnly {
554,431✔
4904
                        // Expected stream.
25,071✔
4905
                        if sname := getExpectedStream(hdr); sname != _EMPTY_ && sname != name {
25,076✔
4906
                                mset.mu.Unlock()
5✔
4907
                                bumpCLFS()
5✔
4908
                                if canRespond {
10✔
4909
                                        resp.PubAck = &PubAck{Stream: name}
5✔
4910
                                        resp.Error = NewJSStreamNotMatchError()
5✔
4911
                                        b, _ := json.Marshal(resp)
5✔
4912
                                        outq.sendMsg(reply, b)
5✔
4913
                                }
5✔
4914
                                return errStreamMismatch
5✔
4915
                        }
4916
                }
4917

4918
                // TTL'd messages are rejected entirely if TTLs are not enabled on the stream.
4919
                // Shouldn't happen in clustered mode since we should have already caught this
4920
                // in processClusteredInboundMsg, but needed here for non-clustered etc.
4921
                if ttl, _ := getMessageTTL(hdr); !sourced && ttl != 0 && !mset.cfg.AllowMsgTTL {
529,357✔
4922
                        mset.mu.Unlock()
2✔
4923
                        bumpCLFS()
2✔
4924
                        if canRespond {
4✔
4925
                                resp.PubAck = &PubAck{Stream: name}
2✔
4926
                                resp.Error = NewJSMessageTTLDisabledError()
2✔
4927
                                b, _ := json.Marshal(resp)
2✔
4928
                                outq.sendMsg(reply, b)
2✔
4929
                        }
2✔
4930
                        return errMsgTTLDisabled
2✔
4931
                }
4932

4933
                // Dedupe detection. This is done at the cluster level for dedupe detectiom above the
4934
                // lower layers. But we still need to pull out the msgId.
4935
                if msgId = getMsgId(hdr); msgId != _EMPTY_ {
1,027,912✔
4936
                        // Do real check only if not clustered or traceOnly flag is set.
498,559✔
4937
                        if !isClustered || traceOnly {
498,616✔
4938
                                if dde := mset.checkMsgId(msgId); dde != nil {
71✔
4939
                                        mset.mu.Unlock()
14✔
4940
                                        bumpCLFS()
14✔
4941
                                        if canRespond {
28✔
4942
                                                response := append(pubAck, strconv.FormatUint(dde.seq, 10)...)
14✔
4943
                                                response = append(response, ",\"duplicate\": true}"...)
14✔
4944
                                                outq.sendMsg(reply, response)
14✔
4945
                                        }
14✔
4946
                                        return errMsgIdDuplicate
14✔
4947
                                }
4948
                        }
4949
                }
4950

4951
                // Expected last sequence per subject.
4952
                if seq, exists := getExpectedLastSeqPerSubject(hdr); exists {
529,870✔
4953
                        // Allow override of the subject used for the check.
531✔
4954
                        seqSubj := subject
531✔
4955
                        if optSubj := getExpectedLastSeqPerSubjectForSubject(hdr); optSubj != _EMPTY_ {
567✔
4956
                                seqSubj = optSubj
36✔
4957
                        }
36✔
4958

4959
                        // TODO(dlc) - We could make a new store func that does this all in one.
4960
                        var smv StoreMsg
531✔
4961
                        var fseq uint64
531✔
4962
                        sm, err := store.LoadLastMsg(seqSubj, &smv)
531✔
4963
                        if sm != nil {
1,027✔
4964
                                fseq = sm.seq
496✔
4965
                        }
496✔
4966
                        if err == ErrStoreMsgNotFound {
566✔
4967
                                if seq == 0 {
69✔
4968
                                        fseq, err = 0, nil
34✔
4969
                                } else if mset.isClustered() {
35✔
4970
                                        // Do not bump clfs in case message was not found and could have been deleted.
×
4971
                                        var ss StreamState
×
4972
                                        store.FastState(&ss)
×
4973
                                        if seq <= ss.LastSeq {
×
4974
                                                fseq, err = seq, nil
×
4975
                                        }
×
4976
                                }
4977
                        }
4978
                        if err != nil || fseq != seq {
541✔
4979
                                mset.mu.Unlock()
10✔
4980
                                bumpCLFS()
10✔
4981
                                if canRespond {
20✔
4982
                                        resp.PubAck = &PubAck{Stream: name}
10✔
4983
                                        resp.Error = NewJSStreamWrongLastSequenceError(fseq)
10✔
4984
                                        b, _ := json.Marshal(resp)
10✔
4985
                                        outq.sendMsg(reply, b)
10✔
4986
                                }
10✔
4987
                                return fmt.Errorf("last sequence by subject mismatch: %d vs %d", seq, fseq)
10✔
4988
                        }
4989
                }
4990

4991
                // Expected last sequence.
4992
                if seq, exists := getExpectedLastSeq(hdr); exists && seq != mset.lseq {
529,335✔
4993
                        mlseq := mset.lseq
6✔
4994
                        mset.mu.Unlock()
6✔
4995
                        bumpCLFS()
6✔
4996
                        if canRespond {
12✔
4997
                                resp.PubAck = &PubAck{Stream: name}
6✔
4998
                                resp.Error = NewJSStreamWrongLastSequenceError(mlseq)
6✔
4999
                                b, _ := json.Marshal(resp)
6✔
5000
                                outq.sendMsg(reply, b)
6✔
5001
                        }
6✔
5002
                        return fmt.Errorf("last sequence mismatch: %d vs %d", seq, mlseq)
6✔
5003
                }
5004
                // Expected last msgId.
5005
                if lmsgId := getExpectedLastMsgId(hdr); lmsgId != _EMPTY_ {
529,329✔
5006
                        if mset.lmsgId == _EMPTY_ && !mset.ddloaded {
6✔
5007
                                mset.rebuildDedupe()
×
5008
                        }
×
5009
                        if lmsgId != mset.lmsgId {
11✔
5010
                                last := mset.lmsgId
5✔
5011
                                mset.mu.Unlock()
5✔
5012
                                bumpCLFS()
5✔
5013
                                if canRespond {
10✔
5014
                                        resp.PubAck = &PubAck{Stream: name}
5✔
5015
                                        resp.Error = NewJSStreamWrongLastMsgIDError(last)
5✔
5016
                                        b, _ := json.Marshal(resp)
5✔
5017
                                        outq.sendMsg(reply, b)
5✔
5018
                                }
5✔
5019
                                return fmt.Errorf("last msgid mismatch: %q vs %q", lmsgId, last)
5✔
5020
                        }
5021
                }
5022
                // Check for any rollups.
5023
                if rollup := getRollup(hdr); rollup != _EMPTY_ {
529,459✔
5024
                        if !mset.cfg.AllowRollup || mset.cfg.DenyPurge {
145✔
5025
                                mset.mu.Unlock()
4✔
5026
                                bumpCLFS()
4✔
5027
                                if canRespond {
8✔
5028
                                        resp.PubAck = &PubAck{Stream: name}
4✔
5029
                                        resp.Error = NewJSStreamRollupFailedError(errors.New("rollup not permitted"))
4✔
5030
                                        b, _ := json.Marshal(resp)
4✔
5031
                                        outq.sendMsg(reply, b)
4✔
5032
                                }
4✔
5033
                                return errors.New("rollup not permitted")
4✔
5034
                        }
5035
                        switch rollup {
137✔
5036
                        case JSMsgRollupSubject:
131✔
5037
                                rollupSub = true
131✔
5038
                        case JSMsgRollupAll:
2✔
5039
                                rollupAll = true
2✔
5040
                        default:
4✔
5041
                                mset.mu.Unlock()
4✔
5042
                                bumpCLFS()
4✔
5043
                                err := fmt.Errorf("rollup value invalid: %q", rollup)
4✔
5044
                                if canRespond {
8✔
5045
                                        resp.PubAck = &PubAck{Stream: name}
4✔
5046
                                        resp.Error = NewJSStreamRollupFailedError(err)
4✔
5047
                                        b, _ := json.Marshal(resp)
4✔
5048
                                        outq.sendMsg(reply, b)
4✔
5049
                                }
4✔
5050
                                return err
4✔
5051
                        }
5052
                }
5053
        }
5054

5055
        // Response Ack.
5056
        var (
1,375,221✔
5057
                response []byte
1,375,221✔
5058
                seq      uint64
1,375,221✔
5059
                err      error
1,375,221✔
5060
        )
1,375,221✔
5061

1,375,221✔
5062
        // Check to see if we are over the max msg size.
1,375,221✔
5063
        if maxMsgSize >= 0 && (len(hdr)+len(msg)) > maxMsgSize {
1,375,227✔
5064
                mset.mu.Unlock()
6✔
5065
                bumpCLFS()
6✔
5066
                if canRespond {
12✔
5067
                        resp.PubAck = &PubAck{Stream: name}
6✔
5068
                        resp.Error = NewJSStreamMessageExceedsMaximumError()
6✔
5069
                        response, _ = json.Marshal(resp)
6✔
5070
                        mset.outq.sendMsg(reply, response)
6✔
5071
                }
6✔
5072
                return ErrMaxPayload
6✔
5073
        }
5074

5075
        if len(hdr) > math.MaxUint16 {
1,375,215✔
5076
                mset.mu.Unlock()
×
5077
                bumpCLFS()
×
5078
                if canRespond {
×
5079
                        resp.PubAck = &PubAck{Stream: name}
×
5080
                        resp.Error = NewJSStreamHeaderExceedsMaximumError()
×
5081
                        response, _ = json.Marshal(resp)
×
5082
                        mset.outq.sendMsg(reply, response)
×
5083
                }
×
5084
                return ErrMaxPayload
×
5085
        }
5086

5087
        // Check to see if we have exceeded our limits.
5088
        if js.limitsExceeded(stype) {
1,375,216✔
5089
                s.resourcesExceededError()
1✔
5090
                mset.mu.Unlock()
1✔
5091
                bumpCLFS()
1✔
5092
                if canRespond {
2✔
5093
                        resp.PubAck = &PubAck{Stream: name}
1✔
5094
                        resp.Error = NewJSInsufficientResourcesError()
1✔
5095
                        response, _ = json.Marshal(resp)
1✔
5096
                        mset.outq.sendMsg(reply, response)
1✔
5097
                }
1✔
5098
                // Stepdown regardless.
5099
                if node := mset.raftNode(); node != nil {
1✔
5100
                        node.StepDown()
×
5101
                }
×
5102
                return NewJSInsufficientResourcesError()
1✔
5103
        }
5104

5105
        var noInterest bool
1,375,214✔
5106

1,375,214✔
5107
        // If we are interest based retention and have no consumers then we can skip.
1,375,214✔
5108
        if interestRetention {
1,470,460✔
5109
                mset.clsMu.RLock()
95,246✔
5110
                noInterest = numConsumers == 0 || mset.csl == nil || !mset.csl.HasInterest(subject)
95,246✔
5111
                mset.clsMu.RUnlock()
95,246✔
5112
        }
95,246✔
5113

5114
        // Grab timestamp if not already set.
5115
        if ts == 0 && lseq > 0 {
1,375,214✔
5116
                ts = time.Now().UnixNano()
×
5117
        }
×
5118

5119
        mt.updateJetStreamEvent(subject, noInterest)
1,375,214✔
5120
        if traceOnly {
1,375,219✔
5121
                mset.mu.Unlock()
5✔
5122
                return nil
5✔
5123
        }
5✔
5124

5125
        // Skip msg here.
5126
        if noInterest {
1,420,182✔
5127
                mset.lseq = store.SkipMsg()
44,973✔
5128
                mset.lmsgId = msgId
44,973✔
5129
                // If we have a msgId make sure to save.
44,973✔
5130
                if msgId != _EMPTY_ {
44,974✔
5131
                        mset.storeMsgIdLocked(&ddentry{msgId, mset.lseq, ts})
1✔
5132
                }
1✔
5133
                if canRespond {
56,374✔
5134
                        response = append(pubAck, strconv.FormatUint(mset.lseq, 10)...)
11,401✔
5135
                        response = append(response, '}')
11,401✔
5136
                        mset.outq.sendMsg(reply, response)
11,401✔
5137
                }
11,401✔
5138
                mset.mu.Unlock()
44,973✔
5139
                return nil
44,973✔
5140
        }
5141

5142
        // If here we will attempt to store the message.
5143
        // Assume this will succeed.
5144
        olmsgId := mset.lmsgId
1,330,236✔
5145
        mset.lmsgId = msgId
1,330,236✔
5146
        clfs := mset.clfs
1,330,236✔
5147
        mset.lseq++
1,330,236✔
5148
        tierName := mset.tier
1,330,236✔
5149

1,330,236✔
5150
        // Republish state if needed.
1,330,236✔
5151
        var tsubj string
1,330,236✔
5152
        var tlseq uint64
1,330,236✔
5153
        var thdrsOnly bool
1,330,236✔
5154
        if mset.tr != nil {
1,331,741✔
5155
                tsubj, _ = mset.tr.Match(subject)
1,505✔
5156
                if mset.cfg.RePublish != nil {
3,010✔
5157
                        thdrsOnly = mset.cfg.RePublish.HeadersOnly
1,505✔
5158
                }
1,505✔
5159
        }
5160
        republish := tsubj != _EMPTY_ && isLeader
1,330,236✔
5161

1,330,236✔
5162
        // If we are republishing grab last sequence for this exact subject. Aids in gap detection for lightweight clients.
1,330,236✔
5163
        if republish {
1,330,939✔
5164
                var smv StoreMsg
703✔
5165
                if sm, _ := store.LoadLastMsg(subject, &smv); sm != nil {
1,398✔
5166
                        tlseq = sm.seq
695✔
5167
                }
695✔
5168
        }
5169

5170
        // If clustered this was already checked and we do not want to check here and possibly introduce skew.
5171
        if !isClustered {
1,594,099✔
5172
                if exceeded, err := jsa.wouldExceedLimits(stype, tierName, mset.cfg.Replicas, subject, hdr, msg); exceeded {
263,896✔
5173
                        if err == nil {
65✔
5174
                                err = NewJSAccountResourcesExceededError()
32✔
5175
                        }
32✔
5176
                        s.RateLimitWarnf("JetStream resource limits exceeded for account: %q", accName)
33✔
5177
                        if canRespond {
66✔
5178
                                resp.PubAck = &PubAck{Stream: name}
33✔
5179
                                resp.Error = err
33✔
5180
                                response, _ = json.Marshal(resp)
33✔
5181
                                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0))
33✔
5182
                        }
33✔
5183
                        mset.mu.Unlock()
33✔
5184
                        return err
33✔
5185
                }
5186
        }
5187

5188
        // Find the message TTL if any.
5189
        ttl, err := getMessageTTL(hdr)
1,330,203✔
5190
        if err != nil {
1,330,207✔
5191
                if canRespond {
8✔
5192
                        resp.PubAck = &PubAck{Stream: name}
4✔
5193
                        resp.Error = NewJSMessageTTLInvalidError()
4✔
5194
                        response, _ = json.Marshal(resp)
4✔
5195
                        mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0))
4✔
5196
                }
4✔
5197
                mset.mu.Unlock()
4✔
5198
                return err
4✔
5199
        }
5200

5201
        // If subject delete markers are used, ensure message TTL is that at minimum.
5202
        // Otherwise, subject delete markers could be missed if one already exists for this subject.
5203
        if ttl > 0 && mset.cfg.SubjectDeleteMarkerTTL > 0 {
1,330,450✔
5204
                if minTtl := int64(mset.cfg.SubjectDeleteMarkerTTL.Seconds()); ttl < minTtl {
267✔
5205
                        ttl = minTtl
16✔
5206
                }
16✔
5207
        }
5208

5209
        // Store actual msg.
5210
        if lseq == 0 && ts == 0 {
1,588,179✔
5211
                seq, ts, err = store.StoreMsg(subject, hdr, msg, ttl)
257,980✔
5212
        } else {
1,330,199✔
5213
                // Make sure to take into account any message assignments that we had to skip (clfs).
1,072,219✔
5214
                seq = lseq + 1 - clfs
1,072,219✔
5215
                // Check for preAcks and the need to clear it.
1,072,219✔
5216
                if mset.hasAllPreAcks(seq, subject) {
1,072,237✔
5217
                        mset.clearAllPreAcks(seq)
18✔
5218
                }
18✔
5219
                err = store.StoreRawMsg(subject, hdr, msg, seq, ts, ttl)
1,072,219✔
5220
        }
5221

5222
        if err != nil {
1,330,228✔
5223
                if isPermissionError(err) {
29✔
5224
                        mset.mu.Unlock()
×
5225
                        // messages in block cache could be lost in the worst case.
×
5226
                        // In the clustered mode it is very highly unlikely as a result of replication.
×
5227
                        mset.srv.DisableJetStream()
×
5228
                        mset.srv.Warnf("Filesystem permission denied while writing msg, disabling JetStream: %v", err)
×
5229
                        return err
×
5230
                }
×
5231
                // If we did not succeed put those values back and increment clfs in case we are clustered.
5232
                var state StreamState
29✔
5233
                mset.store.FastState(&state)
29✔
5234
                mset.lseq = state.LastSeq
29✔
5235
                mset.lmsgId = olmsgId
29✔
5236
                mset.mu.Unlock()
29✔
5237
                bumpCLFS()
29✔
5238

29✔
5239
                switch err {
29✔
5240
                case ErrMaxMsgs, ErrMaxBytes, ErrMaxMsgsPerSubject, ErrMsgTooLarge:
26✔
5241
                        s.RateLimitDebugf("JetStream failed to store a msg on stream '%s > %s': %v", accName, name, err)
26✔
5242
                case ErrStoreClosed:
×
5243
                default:
3✔
5244
                        s.Errorf("JetStream failed to store a msg on stream '%s > %s': %v", accName, name, err)
3✔
5245
                }
5246

5247
                if canRespond {
46✔
5248
                        resp.PubAck = &PubAck{Stream: name}
17✔
5249
                        resp.Error = NewJSStreamStoreFailedError(err, Unless(err))
17✔
5250
                        response, _ = json.Marshal(resp)
17✔
5251
                        mset.outq.sendMsg(reply, response)
17✔
5252
                }
17✔
5253
                return err
29✔
5254
        }
5255

5256
        // If we have a msgId make sure to save.
5257
        // This will replace our estimate from the cluster layer if we are clustered.
5258
        if msgId != _EMPTY_ {
1,828,710✔
5259
                if isClustered && isLeader && mset.ddmap != nil {
707,632✔
5260
                        if dde := mset.ddmap[msgId]; dde != nil {
418,181✔
5261
                                dde.seq, dde.ts = seq, ts
209,089✔
5262
                        } else {
209,092✔
5263
                                mset.storeMsgIdLocked(&ddentry{msgId, seq, ts})
3✔
5264
                        }
3✔
5265
                } else {
289,448✔
5266
                        // R1 or not leader..
289,448✔
5267
                        mset.storeMsgIdLocked(&ddentry{msgId, seq, ts})
289,448✔
5268
                }
289,448✔
5269
        }
5270

5271
        // If here we succeeded in storing the message.
5272
        mset.mu.Unlock()
1,330,170✔
5273

1,330,170✔
5274
        // No errors, this is the normal path.
1,330,170✔
5275
        if rollupSub {
1,330,299✔
5276
                mset.purge(&JSApiStreamPurgeRequest{Subject: subject, Keep: 1})
129✔
5277
        } else if rollupAll {
1,330,172✔
5278
                mset.purge(&JSApiStreamPurgeRequest{Keep: 1})
2✔
5279
        }
2✔
5280

5281
        // Check for republish.
5282
        if republish {
1,330,873✔
5283
                const ht = "NATS/1.0\r\nNats-Stream: %s\r\nNats-Subject: %s\r\nNats-Sequence: %d\r\nNats-Time-Stamp: %s\r\nNats-Last-Sequence: %d\r\n\r\n"
703✔
5284
                const htho = "NATS/1.0\r\nNats-Stream: %s\r\nNats-Subject: %s\r\nNats-Sequence: %d\r\nNats-Time-Stamp: %s\r\nNats-Last-Sequence: %d\r\nNats-Msg-Size: %d\r\n\r\n"
703✔
5285
                // When adding to existing headers, will use the fmt.Append version so this skips the headers from above.
703✔
5286
                const hoff = 10
703✔
5287

703✔
5288
                tsStr := time.Unix(0, ts).UTC().Format(time.RFC3339Nano)
703✔
5289
                var rpMsg []byte
703✔
5290
                if len(hdr) == 0 {
1,406✔
5291
                        if !thdrsOnly {
1,306✔
5292
                                hdr = fmt.Appendf(nil, ht, name, subject, seq, tsStr, tlseq)
603✔
5293
                                rpMsg = copyBytes(msg)
603✔
5294
                        } else {
703✔
5295
                                hdr = fmt.Appendf(nil, htho, name, subject, seq, tsStr, tlseq, len(msg))
100✔
5296
                        }
100✔
5297
                } else {
×
5298
                        // use hdr[:end:end] to make sure as we add we copy the original hdr.
×
5299
                        end := len(hdr) - LEN_CR_LF
×
5300
                        if !thdrsOnly {
×
5301
                                hdr = fmt.Appendf(hdr[:end:end], ht[hoff:], name, subject, seq, tsStr, tlseq)
×
5302
                                rpMsg = copyBytes(msg)
×
5303
                        } else {
×
5304
                                hdr = fmt.Appendf(hdr[:end:end], htho[hoff:], name, subject, seq, tsStr, tlseq, len(msg))
×
5305
                        }
×
5306
                }
5307
                mset.outq.send(newJSPubMsg(tsubj, _EMPTY_, _EMPTY_, hdr, rpMsg, nil, seq))
703✔
5308
        }
5309

5310
        // Send response here.
5311
        if canRespond {
1,967,239✔
5312
                response = append(pubAck, strconv.FormatUint(seq, 10)...)
637,069✔
5313
                response = append(response, '}')
637,069✔
5314
                mset.outq.sendMsg(reply, response)
637,069✔
5315
        }
637,069✔
5316

5317
        // Signal consumers for new messages.
5318
        if numConsumers > 0 {
2,088,283✔
5319
                mset.sigq.push(newCMsg(subject, seq))
758,113✔
5320
                select {
758,113✔
5321
                case mset.sch <- struct{}{}:
635,507✔
5322
                default:
122,606✔
5323
                }
5324
        }
5325

5326
        return nil
1,330,170✔
5327
}
5328

5329
// Used to signal inbound message to registered consumers.
5330
type cMsg struct {
5331
        seq  uint64
5332
        subj string
5333
}
5334

5335
// Pool to recycle consumer bound msgs.
5336
var cMsgPool sync.Pool
5337

5338
// Used to queue up consumer bound msgs for signaling.
5339
func newCMsg(subj string, seq uint64) *cMsg {
758,113✔
5340
        var m *cMsg
758,113✔
5341
        cm := cMsgPool.Get()
758,113✔
5342
        if cm != nil {
1,502,988✔
5343
                m = cm.(*cMsg)
744,875✔
5344
        } else {
758,113✔
5345
                m = new(cMsg)
13,238✔
5346
        }
13,238✔
5347
        m.subj, m.seq = subj, seq
758,113✔
5348

758,113✔
5349
        return m
758,113✔
5350
}
5351

5352
func (m *cMsg) returnToPool() {
758,113✔
5353
        if m == nil {
758,113✔
5354
                return
×
5355
        }
×
5356
        m.subj, m.seq = _EMPTY_, 0
758,113✔
5357
        cMsgPool.Put(m)
758,113✔
5358
}
5359

5360
// Go routine to signal consumers.
5361
// Offloaded from stream msg processing.
5362
func (mset *stream) signalConsumersLoop() {
5,417✔
5363
        mset.mu.RLock()
5,417✔
5364
        s, qch, sch, msgs := mset.srv, mset.qch, mset.sch, mset.sigq
5,417✔
5365
        mset.mu.RUnlock()
5,417✔
5366

5,417✔
5367
        for {
646,341✔
5368
                select {
640,924✔
5369
                case <-s.quitCh:
3✔
5370
                        return
3✔
5371
                case <-qch:
5,414✔
5372
                        return
5,414✔
5373
                case <-sch:
635,507✔
5374
                        cms := msgs.pop()
635,507✔
5375
                        for _, m := range cms {
1,393,620✔
5376
                                seq, subj := m.seq, m.subj
758,113✔
5377
                                m.returnToPool()
758,113✔
5378
                                // Signal all appropriate consumers.
758,113✔
5379
                                mset.signalConsumers(subj, seq)
758,113✔
5380
                        }
758,113✔
5381
                        msgs.recycle(&cms)
635,507✔
5382
                }
5383
        }
5384
}
5385

5386
// This will update and signal all consumers that match.
5387
func (mset *stream) signalConsumers(subj string, seq uint64) {
758,113✔
5388
        mset.clsMu.RLock()
758,113✔
5389
        defer mset.clsMu.RUnlock()
758,113✔
5390
        csl := mset.csl
758,113✔
5391
        if csl == nil {
758,113✔
5392
                return
×
5393
        }
×
5394
        csl.Match(subj, func(o *consumer) {
1,543,768✔
5395
                o.processStreamSignal(seq)
785,655✔
5396
        })
785,655✔
5397
}
5398

5399
// Internal message for use by jetstream subsystem.
5400
type jsPubMsg struct {
5401
        dsubj string // Subject to send to, e.g. _INBOX.xxx
5402
        reply string
5403
        StoreMsg
5404
        o *consumer
5405
}
5406

5407
var jsPubMsgPool sync.Pool
5408

5409
func newJSPubMsg(dsubj, subj, reply string, hdr, msg []byte, o *consumer, seq uint64) *jsPubMsg {
988,264✔
5410
        var m *jsPubMsg
988,264✔
5411
        var buf []byte
988,264✔
5412
        pm := jsPubMsgPool.Get()
988,264✔
5413
        if pm != nil {
1,953,081✔
5414
                m = pm.(*jsPubMsg)
964,817✔
5415
                buf = m.buf[:0]
964,817✔
5416
                if hdr != nil {
1,039,690✔
5417
                        hdr = append(m.hdr[:0], hdr...)
74,873✔
5418
                }
74,873✔
5419
        } else {
23,447✔
5420
                m = new(jsPubMsg)
23,447✔
5421
        }
23,447✔
5422
        // When getting something from a pool it is critical that all fields are
5423
        // initialized. Doing this way guarantees that if someone adds a field to
5424
        // the structure, the compiler will fail the build if this line is not updated.
5425
        (*m) = jsPubMsg{dsubj, reply, StoreMsg{subj, hdr, msg, buf, seq, 0}, o}
988,264✔
5426

988,264✔
5427
        return m
988,264✔
5428
}
5429

5430
// Gets a jsPubMsg from the pool.
5431
func getJSPubMsgFromPool() *jsPubMsg {
529,649✔
5432
        pm := jsPubMsgPool.Get()
529,649✔
5433
        if pm != nil {
1,055,133✔
5434
                return pm.(*jsPubMsg)
525,484✔
5435
        }
525,484✔
5436
        return new(jsPubMsg)
4,165✔
5437
}
5438

5439
func (pm *jsPubMsg) returnToPool() {
1,517,638✔
5440
        if pm == nil {
1,517,638✔
5441
                return
×
5442
        }
×
5443
        pm.subj, pm.dsubj, pm.reply, pm.hdr, pm.msg, pm.o = _EMPTY_, _EMPTY_, _EMPTY_, nil, nil, nil
1,517,638✔
5444
        if len(pm.buf) > 0 {
1,942,106✔
5445
                pm.buf = pm.buf[:0]
424,468✔
5446
        }
424,468✔
5447
        if len(pm.hdr) > 0 {
1,517,638✔
5448
                pm.hdr = pm.hdr[:0]
×
5449
        }
×
5450
        jsPubMsgPool.Put(pm)
1,517,638✔
5451
}
5452

5453
func (pm *jsPubMsg) size() int {
414,413✔
5454
        if pm == nil {
414,413✔
5455
                return 0
×
5456
        }
×
5457
        return len(pm.dsubj) + len(pm.reply) + len(pm.hdr) + len(pm.msg)
414,413✔
5458
}
5459

5460
// Queue of *jsPubMsg for sending internal system messages.
5461
type jsOutQ struct {
5462
        *ipQueue[*jsPubMsg]
5463
}
5464

5465
func (q *jsOutQ) sendMsg(subj string, msg []byte) {
890,506✔
5466
        if q != nil {
1,781,012✔
5467
                q.send(newJSPubMsg(subj, _EMPTY_, _EMPTY_, nil, msg, nil, 0))
890,506✔
5468
        }
890,506✔
5469
}
5470

5471
func (q *jsOutQ) send(msg *jsPubMsg) {
1,402,677✔
5472
        if q == nil || msg == nil {
1,402,677✔
5473
                return
×
5474
        }
×
5475
        q.push(msg)
1,402,677✔
5476
}
5477

5478
func (q *jsOutQ) unregister() {
590✔
5479
        if q == nil {
591✔
5480
                return
1✔
5481
        }
1✔
5482
        q.ipQueue.unregister()
589✔
5483
}
5484

5485
// StoredMsg is for raw access to messages in a stream.
5486
type StoredMsg struct {
5487
        Subject  string    `json:"subject"`
5488
        Sequence uint64    `json:"seq"`
5489
        Header   []byte    `json:"hdrs,omitempty"`
5490
        Data     []byte    `json:"data,omitempty"`
5491
        Time     time.Time `json:"time"`
5492
}
5493

5494
// This is similar to system semantics but did not want to overload the single system sendq,
5495
// or require system account when doing simple setup with jetstream.
5496
func (mset *stream) setupSendCapabilities() {
5,416✔
5497
        mset.mu.Lock()
5,416✔
5498
        defer mset.mu.Unlock()
5,416✔
5499
        if mset.outq != nil {
5,416✔
5500
                return
×
5501
        }
×
5502
        qname := fmt.Sprintf("[ACC:%s] stream '%s' sendQ", mset.acc.Name, mset.cfg.Name)
5,416✔
5503
        mset.outq = &jsOutQ{newIPQueue[*jsPubMsg](mset.srv, qname)}
5,416✔
5504
        go mset.internalLoop()
5,416✔
5505
}
5506

5507
// Returns the associated account name.
5508
func (mset *stream) accName() string {
23,590✔
5509
        if mset == nil {
23,597✔
5510
                return _EMPTY_
7✔
5511
        }
7✔
5512
        mset.mu.RLock()
23,583✔
5513
        acc := mset.acc
23,583✔
5514
        mset.mu.RUnlock()
23,583✔
5515
        return acc.Name
23,583✔
5516
}
5517

5518
// Name returns the stream name.
5519
func (mset *stream) name() string {
110,790✔
5520
        if mset == nil {
110,797✔
5521
                return _EMPTY_
7✔
5522
        }
7✔
5523
        mset.mu.RLock()
110,783✔
5524
        defer mset.mu.RUnlock()
110,783✔
5525
        return mset.cfg.Name
110,783✔
5526
}
5527

5528
func (mset *stream) internalLoop() {
5,416✔
5529
        mset.mu.RLock()
5,416✔
5530
        setGoRoutineLabels(pprofLabels{
5,416✔
5531
                "account": mset.acc.Name,
5,416✔
5532
                "stream":  mset.cfg.Name,
5,416✔
5533
        })
5,416✔
5534
        s := mset.srv
5,416✔
5535
        c := s.createInternalJetStreamClient()
5,416✔
5536
        c.registerWithAccount(mset.acc)
5,416✔
5537
        defer c.closeConnection(ClientClosed)
5,416✔
5538
        outq, qch, msgs, gets := mset.outq, mset.qch, mset.msgs, mset.gets
5,416✔
5539

5,416✔
5540
        // For the ack msgs queue for interest retention.
5,416✔
5541
        var (
5,416✔
5542
                amch chan struct{}
5,416✔
5543
                ackq *ipQueue[uint64]
5,416✔
5544
        )
5,416✔
5545
        if mset.ackq != nil {
6,922✔
5546
                ackq, amch = mset.ackq, mset.ackq.ch
1,506✔
5547
        }
1,506✔
5548
        mset.mu.RUnlock()
5,416✔
5549

5,416✔
5550
        // Raw scratch buffer.
5,416✔
5551
        // This should be rarely used now so can be smaller.
5,416✔
5552
        var _r [1024]byte
5,416✔
5553

5,416✔
5554
        // To optimize for not converting a string to a []byte slice.
5,416✔
5555
        var (
5,416✔
5556
                subj  [256]byte
5,416✔
5557
                dsubj [256]byte
5,416✔
5558
                rply  [256]byte
5,416✔
5559
                szb   [10]byte
5,416✔
5560
                hdb   [10]byte
5,416✔
5561
        )
5,416✔
5562

5,416✔
5563
        for {
1,449,746✔
5564
                select {
1,444,330✔
5565
                case <-outq.ch:
892,116✔
5566
                        pms := outq.pop()
892,116✔
5567
                        for _, pm := range pms {
2,294,518✔
5568
                                c.pa.subject = append(dsubj[:0], pm.dsubj...)
1,402,402✔
5569
                                c.pa.deliver = append(subj[:0], pm.subj...)
1,402,402✔
5570
                                c.pa.size = len(pm.msg) + len(pm.hdr)
1,402,402✔
5571
                                c.pa.szb = append(szb[:0], strconv.Itoa(c.pa.size)...)
1,402,402✔
5572
                                if len(pm.reply) > 0 {
1,817,058✔
5573
                                        c.pa.reply = append(rply[:0], pm.reply...)
414,656✔
5574
                                } else {
1,402,402✔
5575
                                        c.pa.reply = nil
987,746✔
5576
                                }
987,746✔
5577

5578
                                // If we have an underlying buf that is the wire contents for hdr + msg, else construct on the fly.
5579
                                var msg []byte
1,402,402✔
5580
                                if len(pm.buf) > 0 {
1,808,774✔
5581
                                        msg = pm.buf
406,372✔
5582
                                } else {
1,402,402✔
5583
                                        if len(pm.hdr) > 0 {
1,072,239✔
5584
                                                msg = pm.hdr
76,209✔
5585
                                                if len(pm.msg) > 0 {
91,025✔
5586
                                                        msg = _r[:0]
14,816✔
5587
                                                        msg = append(msg, pm.hdr...)
14,816✔
5588
                                                        msg = append(msg, pm.msg...)
14,816✔
5589
                                                }
14,816✔
5590
                                        } else if len(pm.msg) > 0 {
1,615,780✔
5591
                                                // We own this now from a low level buffer perspective so can use directly here.
695,959✔
5592
                                                msg = pm.msg
695,959✔
5593
                                        }
695,959✔
5594
                                }
5595

5596
                                if len(pm.hdr) > 0 {
1,690,942✔
5597
                                        c.pa.hdr = len(pm.hdr)
288,540✔
5598
                                        c.pa.hdb = []byte(strconv.Itoa(c.pa.hdr))
288,540✔
5599
                                        c.pa.hdb = append(hdb[:0], strconv.Itoa(c.pa.hdr)...)
288,540✔
5600
                                } else {
1,402,402✔
5601
                                        c.pa.hdr = -1
1,113,862✔
5602
                                        c.pa.hdb = nil
1,113,862✔
5603
                                }
1,113,862✔
5604

5605
                                msg = append(msg, _CRLF_...)
1,402,402✔
5606

1,402,402✔
5607
                                didDeliver, _ := c.processInboundClientMsg(msg)
1,402,402✔
5608
                                c.pa.szb, c.pa.subject, c.pa.deliver = nil, nil, nil
1,402,402✔
5609

1,402,402✔
5610
                                // Check to see if this is a delivery for a consumer and
1,402,402✔
5611
                                // we failed to deliver the message. If so alert the consumer.
1,402,402✔
5612
                                if pm.o != nil && pm.seq > 0 && !didDeliver {
1,403,875✔
5613
                                        pm.o.didNotDeliver(pm.seq, pm.dsubj)
1,473✔
5614
                                }
1,473✔
5615
                                pm.returnToPool()
1,402,402✔
5616
                        }
5617
                        // TODO: Move in the for-loop?
5618
                        c.flushClients(0)
892,116✔
5619
                        outq.recycle(&pms)
892,116✔
5620
                case <-msgs.ch:
535,830✔
5621
                        // This can possibly change now so needs to be checked here.
535,830✔
5622
                        isClustered := mset.IsClustered()
535,830✔
5623
                        ims := msgs.pop()
535,830✔
5624
                        for _, im := range ims {
1,238,570✔
5625
                                // If we are clustered we need to propose this message to the underlying raft group.
702,740✔
5626
                                if isClustered {
1,150,972✔
5627
                                        mset.processClusteredInboundMsg(im.subj, im.rply, im.hdr, im.msg, im.mt, false)
448,232✔
5628
                                } else {
702,740✔
5629
                                        mset.processJetStreamMsg(im.subj, im.rply, im.hdr, im.msg, 0, 0, im.mt, false)
254,508✔
5630
                                }
254,508✔
5631
                                im.returnToPool()
702,740✔
5632
                        }
5633
                        msgs.recycle(&ims)
535,830✔
5634
                case <-gets.ch:
10,756✔
5635
                        dgs := gets.pop()
10,756✔
5636
                        for _, dg := range dgs {
21,514✔
5637
                                mset.getDirectRequest(&dg.req, dg.reply)
10,758✔
5638
                                dgPool.Put(dg)
10,758✔
5639
                        }
10,758✔
5640
                        gets.recycle(&dgs)
10,756✔
5641

5642
                case <-amch:
212✔
5643
                        seqs := ackq.pop()
212✔
5644
                        for _, seq := range seqs {
426✔
5645
                                mset.ackMsg(nil, seq)
214✔
5646
                        }
214✔
5647
                        ackq.recycle(&seqs)
212✔
5648
                case <-qch:
5,403✔
5649
                        return
5,403✔
5650
                case <-s.quitCh:
13✔
5651
                        return
13✔
5652
                }
5653
        }
5654
}
5655

5656
// Used to break consumers out of their monitorConsumer go routines.
5657
func (mset *stream) resetAndWaitOnConsumers() {
16✔
5658
        mset.mu.RLock()
16✔
5659
        consumers := make([]*consumer, 0, len(mset.consumers))
16✔
5660
        for _, o := range mset.consumers {
16✔
5661
                consumers = append(consumers, o)
×
5662
        }
×
5663
        mset.mu.RUnlock()
16✔
5664

16✔
5665
        for _, o := range consumers {
16✔
5666
                if node := o.raftNode(); node != nil {
×
5667
                        node.StepDown()
×
5668
                        node.Delete()
×
5669
                }
×
5670
                if o.isMonitorRunning() {
×
5671
                        o.monitorWg.Wait()
×
5672
                }
×
5673
        }
5674
}
5675

5676
// Internal function to delete a stream.
5677
func (mset *stream) delete() error {
314✔
5678
        if mset == nil {
315✔
5679
                return nil
1✔
5680
        }
1✔
5681
        return mset.stop(true, true)
313✔
5682
}
5683

5684
// Internal function to stop or delete the stream.
5685
func (mset *stream) stop(deleteFlag, advisory bool) error {
5,433✔
5686
        mset.mu.RLock()
5,433✔
5687
        js, jsa, name := mset.js, mset.jsa, mset.cfg.Name
5,433✔
5688
        mset.mu.RUnlock()
5,433✔
5689

5,433✔
5690
        if jsa == nil {
5,433✔
5691
                return NewJSNotEnabledForAccountError()
×
5692
        }
×
5693

5694
        // Remove from our account map first.
5695
        jsa.mu.Lock()
5,433✔
5696
        delete(jsa.streams, name)
5,433✔
5697
        accName := jsa.account.Name
5,433✔
5698
        jsa.mu.Unlock()
5,433✔
5699

5,433✔
5700
        // Kick monitor and collect consumers first.
5,433✔
5701
        mset.mu.Lock()
5,433✔
5702

5,433✔
5703
        // Mark closed.
5,433✔
5704
        mset.closed.Store(true)
5,433✔
5705

5,433✔
5706
        // Signal to the monitor loop.
5,433✔
5707
        // Can't use qch here.
5,433✔
5708
        if mset.mqch != nil {
10,849✔
5709
                close(mset.mqch)
5,416✔
5710
                mset.mqch = nil
5,416✔
5711
        }
5,416✔
5712

5713
        // Stop responding to sync requests.
5714
        mset.stopClusterSubs()
5,433✔
5715
        // Unsubscribe from direct stream.
5,433✔
5716
        mset.unsubscribeToStream(true)
5,433✔
5717

5,433✔
5718
        // Our info sub if we spun it up.
5,433✔
5719
        if mset.infoSub != nil {
9,188✔
5720
                mset.srv.sysUnsubscribe(mset.infoSub)
3,755✔
5721
                mset.infoSub = nil
3,755✔
5722
        }
3,755✔
5723

5724
        // Clean up consumers.
5725
        var obs []*consumer
5,433✔
5726
        for _, o := range mset.consumers {
7,452✔
5727
                obs = append(obs, o)
2,019✔
5728
        }
2,019✔
5729
        mset.clsMu.Lock()
5,433✔
5730
        mset.consumers, mset.cList, mset.csl = nil, nil, nil
5,433✔
5731
        mset.clsMu.Unlock()
5,433✔
5732

5,433✔
5733
        // Check if we are a mirror.
5,433✔
5734
        if mset.mirror != nil && mset.mirror.sub != nil {
5,433✔
5735
                mset.unsubscribe(mset.mirror.sub)
×
5736
                mset.mirror.sub = nil
×
5737
                mset.removeInternalConsumer(mset.mirror)
×
5738
        }
×
5739
        // Now check for sources.
5740
        if len(mset.sources) > 0 {
5,503✔
5741
                for _, si := range mset.sources {
182✔
5742
                        mset.cancelSourceConsumer(si.iname)
112✔
5743
                }
112✔
5744
        }
5745
        mset.mu.Unlock()
5,433✔
5746

5,433✔
5747
        isShuttingDown := js.isShuttingDown()
5,433✔
5748
        for _, o := range obs {
7,452✔
5749
                if !o.isClosed() {
4,036✔
5750
                        // Third flag says do not broadcast a signal.
2,017✔
5751
                        // TODO(dlc) - If we have an err here we don't want to stop
2,017✔
5752
                        // but should we log?
2,017✔
5753
                        o.stopWithFlags(deleteFlag, deleteFlag, false, advisory)
2,017✔
5754
                        if !isShuttingDown {
2,147✔
5755
                                o.monitorWg.Wait()
130✔
5756
                        }
130✔
5757
                }
5758
        }
5759

5760
        mset.mu.Lock()
5,433✔
5761
        // Send stream delete advisory after the consumers.
5,433✔
5762
        if deleteFlag && advisory {
5,839✔
5763
                mset.sendDeleteAdvisoryLocked()
406✔
5764
        }
406✔
5765

5766
        // Quit channel, do this after sending the delete advisory
5767
        if mset.qch != nil {
10,849✔
5768
                close(mset.qch)
5,416✔
5769
                mset.qch = nil
5,416✔
5770
        }
5,416✔
5771

5772
        // Cluster cleanup
5773
        var sa *streamAssignment
5,433✔
5774
        if n := mset.node; n != nil {
8,431✔
5775
                if deleteFlag {
3,226✔
5776
                        n.Delete()
228✔
5777
                        sa = mset.sa
228✔
5778
                } else {
2,998✔
5779
                        n.Stop()
2,770✔
5780
                }
2,770✔
5781
        }
5782

5783
        // Cleanup duplicate timer if running.
5784
        if mset.ddtmr != nil {
5,494✔
5785
                mset.ddtmr.Stop()
61✔
5786
                mset.ddtmr = nil
61✔
5787
                mset.ddmap = nil
61✔
5788
                mset.ddarr = nil
61✔
5789
                mset.ddindex = 0
61✔
5790
        }
61✔
5791

5792
        sysc := mset.sysc
5,433✔
5793
        mset.sysc = nil
5,433✔
5794

5,433✔
5795
        if deleteFlag {
6,023✔
5796
                // Unregistering ipQueues do not prevent them from push/pop
590✔
5797
                // just will remove them from the central monitoring map
590✔
5798
                mset.msgs.unregister()
590✔
5799
                mset.ackq.unregister()
590✔
5800
                mset.outq.unregister()
590✔
5801
                mset.sigq.unregister()
590✔
5802
                mset.smsgs.unregister()
590✔
5803
        }
590✔
5804

5805
        // Snapshot store.
5806
        store := mset.store
5,433✔
5807
        c := mset.client
5,433✔
5808

5,433✔
5809
        // Clustered cleanup.
5,433✔
5810
        mset.mu.Unlock()
5,433✔
5811

5,433✔
5812
        // Check if the stream assignment has the group node specified.
5,433✔
5813
        // We need this cleared for if the stream gets reassigned here.
5,433✔
5814
        if sa != nil {
5,661✔
5815
                js.mu.Lock()
228✔
5816
                if sa.Group != nil {
456✔
5817
                        sa.Group.node = nil
228✔
5818
                }
228✔
5819
                js.mu.Unlock()
228✔
5820
        }
5821

5822
        if c != nil {
10,866✔
5823
                c.closeConnection(ClientClosed)
5,433✔
5824
        }
5,433✔
5825

5826
        if sysc != nil {
10,849✔
5827
                sysc.closeConnection(ClientClosed)
5,416✔
5828
        }
5,416✔
5829

5830
        if deleteFlag {
6,023✔
5831
                if store != nil {
1,179✔
5832
                        // Ignore errors.
589✔
5833
                        store.Delete()
589✔
5834
                }
589✔
5835
                // Release any resources.
5836
                js.releaseStreamResources(&mset.cfg)
590✔
5837
                // cleanup directories after the stream
590✔
5838
                accDir := filepath.Join(js.config.StoreDir, accName)
590✔
5839
                // Do cleanup in separate go routine similar to how fs will use purge here..
590✔
5840
                go func() {
1,180✔
5841
                        // no op if not empty
590✔
5842
                        os.Remove(filepath.Join(accDir, streamsDir))
590✔
5843
                        os.Remove(accDir)
590✔
5844
                }()
590✔
5845
        } else if store != nil {
9,686✔
5846
                // Ignore errors.
4,843✔
5847
                store.Stop()
4,843✔
5848
        }
4,843✔
5849

5850
        return nil
5,433✔
5851
}
5852

5853
func (mset *stream) getMsg(seq uint64) (*StoredMsg, error) {
75✔
5854
        var smv StoreMsg
75✔
5855
        sm, err := mset.store.LoadMsg(seq, &smv)
75✔
5856
        if err != nil {
81✔
5857
                return nil, err
6✔
5858
        }
6✔
5859
        // This only used in tests directly so no need to pool etc.
5860
        return &StoredMsg{
69✔
5861
                Subject:  sm.subj,
69✔
5862
                Sequence: sm.seq,
69✔
5863
                Header:   sm.hdr,
69✔
5864
                Data:     sm.msg,
69✔
5865
                Time:     time.Unix(0, sm.ts).UTC(),
69✔
5866
        }, nil
69✔
5867
}
5868

5869
// getConsumers will return a copy of all the current consumers for this stream.
5870
func (mset *stream) getConsumers() []*consumer {
6,058✔
5871
        mset.clsMu.RLock()
6,058✔
5872
        defer mset.clsMu.RUnlock()
6,058✔
5873
        return append([]*consumer(nil), mset.cList...)
6,058✔
5874
}
6,058✔
5875

5876
// Lock should be held for this one.
5877
func (mset *stream) numPublicConsumers() int {
69✔
5878
        return len(mset.consumers) - mset.directs
69✔
5879
}
69✔
5880

5881
// This returns all consumers that are not DIRECT.
5882
func (mset *stream) getPublicConsumers() []*consumer {
175✔
5883
        mset.clsMu.RLock()
175✔
5884
        defer mset.clsMu.RUnlock()
175✔
5885

175✔
5886
        var obs []*consumer
175✔
5887
        for _, o := range mset.cList {
360✔
5888
                if !o.cfg.Direct {
365✔
5889
                        obs = append(obs, o)
180✔
5890
                }
180✔
5891
        }
5892
        return obs
175✔
5893
}
5894

5895
// 2 minutes plus up to 30s jitter.
5896
const (
5897
        defaultCheckInterestStateT = 2 * time.Minute
5898
        defaultCheckInterestStateJ = 30
5899
)
5900

5901
var (
5902
        checkInterestStateT = defaultCheckInterestStateT // Interval
5903
        checkInterestStateJ = defaultCheckInterestStateJ // Jitter (secs)
5904
)
5905

5906
// Will check for interest retention and make sure messages
5907
// that have been acked are processed and removed.
5908
// This will check the ack floors of all consumers, and adjust our first sequence accordingly.
5909
func (mset *stream) checkInterestState() {
9,817✔
5910
        if mset == nil || !mset.isInterestRetention() {
14,780✔
5911
                // If we are limits based nothing to do.
4,963✔
5912
                return
4,963✔
5913
        }
4,963✔
5914

5915
        var ss StreamState
4,854✔
5916
        mset.store.FastState(&ss)
4,854✔
5917

4,854✔
5918
        for _, o := range mset.getConsumers() {
5,332✔
5919
                o.checkStateForInterestStream(&ss)
478✔
5920
        }
478✔
5921
}
5922

5923
func (mset *stream) isInterestRetention() bool {
15,926✔
5924
        mset.mu.RLock()
15,926✔
5925
        defer mset.mu.RUnlock()
15,926✔
5926
        return mset.cfg.Retention != LimitsPolicy
15,926✔
5927
}
15,926✔
5928

5929
// NumConsumers reports on number of active consumers for this stream.
5930
func (mset *stream) numConsumers() int {
1,236✔
5931
        mset.mu.RLock()
1,236✔
5932
        defer mset.mu.RUnlock()
1,236✔
5933
        return len(mset.consumers)
1,236✔
5934
}
1,236✔
5935

5936
// Lock should be held.
5937
func (mset *stream) setConsumer(o *consumer) {
9,149✔
5938
        mset.consumers[o.name] = o
9,149✔
5939
        if len(o.subjf) > 0 {
16,783✔
5940
                mset.numFilter++
7,634✔
5941
        }
7,634✔
5942
        if o.cfg.Direct {
9,278✔
5943
                mset.directs++
129✔
5944
        }
129✔
5945
        // Now update consumers list as well
5946
        mset.clsMu.Lock()
9,149✔
5947
        mset.cList = append(mset.cList, o)
9,149✔
5948
        if mset.csl == nil {
10,692✔
5949
                mset.csl = gsl.NewSublist[*consumer]()
1,543✔
5950
        }
1,543✔
5951
        for _, sub := range o.signalSubs() {
18,392✔
5952
                mset.csl.Insert(sub, o)
9,243✔
5953
        }
9,243✔
5954
        mset.clsMu.Unlock()
9,149✔
5955
}
5956

5957
// Lock should be held.
5958
func (mset *stream) removeConsumer(o *consumer) {
9,159✔
5959
        if o.cfg.FilterSubject != _EMPTY_ && mset.numFilter > 0 {
16,736✔
5960
                mset.numFilter--
7,577✔
5961
        }
7,577✔
5962
        if o.cfg.Direct && mset.directs > 0 {
9,288✔
5963
                mset.directs--
129✔
5964
        }
129✔
5965
        if mset.consumers != nil {
16,299✔
5966
                delete(mset.consumers, o.name)
7,140✔
5967
                // Now update consumers list as well
7,140✔
5968
                mset.clsMu.Lock()
7,140✔
5969
                for i, ol := range mset.cList {
135,269✔
5970
                        if ol == o {
135,259✔
5971
                                mset.cList = append(mset.cList[:i], mset.cList[i+1:]...)
7,130✔
5972
                                break
7,130✔
5973
                        }
5974
                }
5975
                // Always remove from the leader sublist.
5976
                if mset.csl != nil {
14,276✔
5977
                        for _, sub := range o.signalSubs() {
14,332✔
5978
                                mset.csl.Remove(sub, o)
7,196✔
5979
                        }
7,196✔
5980
                }
5981
                mset.clsMu.Unlock()
7,140✔
5982
        }
5983
}
5984

5985
// swapSigSubs will update signal Subs for a new subject filter.
5986
// consumer lock should not be held.
5987
func (mset *stream) swapSigSubs(o *consumer, newFilters []string) {
12✔
5988
        mset.clsMu.Lock()
12✔
5989
        o.mu.Lock()
12✔
5990

12✔
5991
        if o.closed || o.mset == nil {
12✔
5992
                o.mu.Unlock()
×
5993
                mset.clsMu.Unlock()
×
5994
                return
×
5995
        }
×
5996

5997
        if o.sigSubs != nil {
24✔
5998
                if mset.csl != nil {
24✔
5999
                        for _, sub := range o.sigSubs {
29✔
6000
                                mset.csl.Remove(sub, o)
17✔
6001
                        }
17✔
6002
                }
6003
                o.sigSubs = nil
12✔
6004
        }
6005

6006
        if o.isLeader() {
22✔
6007
                if mset.csl == nil {
10✔
6008
                        mset.csl = gsl.NewSublist[*consumer]()
×
6009
                }
×
6010
                // If no filters are preset, add fwcs to sublist for that consumer.
6011
                if newFilters == nil {
10✔
6012
                        mset.csl.Insert(fwcs, o)
×
6013
                        o.sigSubs = append(o.sigSubs, fwcs)
×
6014
                        // If there are filters, add their subjects to sublist.
×
6015
                } else {
10✔
6016
                        for _, filter := range newFilters {
22✔
6017
                                mset.csl.Insert(filter, o)
12✔
6018
                                o.sigSubs = append(o.sigSubs, filter)
12✔
6019
                        }
12✔
6020
                }
6021
        }
6022
        o.mu.Unlock()
12✔
6023
        mset.clsMu.Unlock()
12✔
6024

12✔
6025
        mset.mu.Lock()
12✔
6026
        defer mset.mu.Unlock()
12✔
6027

12✔
6028
        if mset.numFilter > 0 && len(o.subjf) > 0 {
24✔
6029
                mset.numFilter--
12✔
6030
        }
12✔
6031
        if len(newFilters) > 0 {
22✔
6032
                mset.numFilter++
10✔
6033
        }
10✔
6034
}
6035

6036
// lookupConsumer will retrieve a consumer by name.
6037
func (mset *stream) lookupConsumer(name string) *consumer {
21,032✔
6038
        mset.mu.RLock()
21,032✔
6039
        defer mset.mu.RUnlock()
21,032✔
6040
        return mset.consumers[name]
21,032✔
6041
}
21,032✔
6042

6043
func (mset *stream) numDirectConsumers() (num int) {
179✔
6044
        mset.clsMu.RLock()
179✔
6045
        defer mset.clsMu.RUnlock()
179✔
6046

179✔
6047
        // Consumers that are direct are not recorded at the store level.
179✔
6048
        for _, o := range mset.cList {
434✔
6049
                o.mu.RLock()
255✔
6050
                if o.cfg.Direct {
510✔
6051
                        num++
255✔
6052
                }
255✔
6053
                o.mu.RUnlock()
255✔
6054
        }
6055
        return num
179✔
6056
}
6057

6058
// State will return the current state for this stream.
6059
func (mset *stream) state() StreamState {
11,032✔
6060
        return mset.stateWithDetail(false)
11,032✔
6061
}
11,032✔
6062

6063
func (mset *stream) stateWithDetail(details bool) StreamState {
25,321✔
6064
        // mset.store does not change once set, so ok to reference here directly.
25,321✔
6065
        // We do this elsewhere as well.
25,321✔
6066
        store := mset.store
25,321✔
6067
        if store == nil {
25,321✔
6068
                return StreamState{}
×
6069
        }
×
6070

6071
        // Currently rely on store for details.
6072
        if details {
25,325✔
6073
                return store.State()
4✔
6074
        }
4✔
6075
        // Here we do the fast version.
6076
        var state StreamState
25,317✔
6077
        store.FastState(&state)
25,317✔
6078
        return state
25,317✔
6079
}
6080

6081
func (mset *stream) Store() StreamStore {
3✔
6082
        mset.mu.RLock()
3✔
6083
        defer mset.mu.RUnlock()
3✔
6084
        return mset.store
3✔
6085
}
3✔
6086

6087
// Determines if the new proposed partition is unique amongst all consumers.
6088
// Lock should be held.
6089
func (mset *stream) partitionUnique(name string, partitions []string) bool {
23✔
6090
        for _, partition := range partitions {
45✔
6091
                for n, o := range mset.consumers {
59✔
6092
                        // Skip the consumer being checked.
37✔
6093
                        if n == name {
42✔
6094
                                continue
5✔
6095
                        }
6096
                        if o.subjf == nil {
32✔
6097
                                return false
×
6098
                        }
×
6099
                        for _, filter := range o.subjf {
71✔
6100
                                if SubjectsCollide(partition, filter.subject) {
50✔
6101
                                        return false
11✔
6102
                                }
11✔
6103
                        }
6104
                }
6105
        }
6106
        return true
12✔
6107
}
6108

6109
// Lock should be held.
6110
func (mset *stream) potentialFilteredConsumers() bool {
64,286✔
6111
        numSubjects := len(mset.cfg.Subjects)
64,286✔
6112
        if len(mset.consumers) == 0 || numSubjects == 0 {
64,289✔
6113
                return false
3✔
6114
        }
3✔
6115
        if numSubjects > 1 || subjectHasWildcard(mset.cfg.Subjects[0]) {
82,300✔
6116
                return true
18,017✔
6117
        }
18,017✔
6118
        return false
46,266✔
6119
}
6120

6121
// Check if there is no interest in this sequence number across our consumers.
6122
// The consumer passed is optional if we are processing the ack for that consumer.
6123
// Write lock should be held.
6124
func (mset *stream) noInterest(seq uint64, obs *consumer) bool {
64,286✔
6125
        return !mset.checkForInterest(seq, obs)
64,286✔
6126
}
64,286✔
6127

6128
// Check if there is no interest in this sequence number and subject across our consumers.
6129
// The consumer passed is optional if we are processing the ack for that consumer.
6130
// Write lock should be held.
6131
func (mset *stream) noInterestWithSubject(seq uint64, subj string, obs *consumer) bool {
18✔
6132
        return !mset.checkForInterestWithSubject(seq, subj, obs)
18✔
6133
}
18✔
6134

6135
// Write lock should be held here for the stream to avoid race conditions on state.
6136
func (mset *stream) checkForInterest(seq uint64, obs *consumer) bool {
64,286✔
6137
        var subj string
64,286✔
6138
        if mset.potentialFilteredConsumers() {
82,303✔
6139
                pmsg := getJSPubMsgFromPool()
18,017✔
6140
                defer pmsg.returnToPool()
18,017✔
6141
                sm, err := mset.store.LoadMsg(seq, &pmsg.StoreMsg)
18,017✔
6142
                if err != nil {
24,043✔
6143
                        if err == ErrStoreEOF {
6,026✔
6144
                                // Register this as a preAck.
×
6145
                                mset.registerPreAck(obs, seq)
×
6146
                                return true
×
6147
                        }
×
6148
                        mset.clearAllPreAcks(seq)
6,026✔
6149
                        return false
6,026✔
6150
                }
6151
                subj = sm.subj
11,991✔
6152
        }
6153
        return mset.checkForInterestWithSubject(seq, subj, obs)
58,260✔
6154
}
6155

6156
// Checks for interest given a sequence and subject.
6157
func (mset *stream) checkForInterestWithSubject(seq uint64, subj string, obs *consumer) bool {
58,278✔
6158
        for _, o := range mset.consumers {
178,402✔
6159
                // If this is us or we have a registered preAck for this consumer continue inspecting.
120,124✔
6160
                if o == obs || mset.hasPreAck(o, seq) {
176,572✔
6161
                        continue
56,448✔
6162
                }
6163
                // Check if we need an ack.
6164
                if o.needAck(seq, subj) {
66,472✔
6165
                        return true
2,796✔
6166
                }
2,796✔
6167
        }
6168
        mset.clearAllPreAcks(seq)
55,482✔
6169
        return false
55,482✔
6170
}
6171

6172
// Check if we have a pre-registered ack for this sequence.
6173
// Write lock should be held.
6174
func (mset *stream) hasPreAck(o *consumer, seq uint64) bool {
63,694✔
6175
        if o == nil || len(mset.preAcks) == 0 {
127,370✔
6176
                return false
63,676✔
6177
        }
63,676✔
6178
        consumers := mset.preAcks[seq]
18✔
6179
        if len(consumers) == 0 {
18✔
6180
                return false
×
6181
        }
×
6182
        _, found := consumers[o]
18✔
6183
        return found
18✔
6184
}
6185

6186
// Check if we have all consumers pre-acked for this sequence and subject.
6187
// Write lock should be held.
6188
func (mset *stream) hasAllPreAcks(seq uint64, subj string) bool {
1,345,400✔
6189
        if len(mset.preAcks) == 0 || len(mset.preAcks[seq]) == 0 {
2,690,782✔
6190
                return false
1,345,382✔
6191
        }
1,345,382✔
6192
        // Since these can be filtered and mutually exclusive,
6193
        // if we have some preAcks we need to check all interest here.
6194
        return mset.noInterestWithSubject(seq, subj, nil)
18✔
6195
}
6196

6197
// Check if we have all consumers pre-acked.
6198
// Write lock should be held.
6199
func (mset *stream) clearAllPreAcks(seq uint64) {
197,952✔
6200
        delete(mset.preAcks, seq)
197,952✔
6201
}
197,952✔
6202

6203
// Clear all preAcks below floor.
6204
// Write lock should be held.
6205
func (mset *stream) clearAllPreAcksBelowFloor(floor uint64) {
1,148✔
6206
        for seq := range mset.preAcks {
1,160✔
6207
                if seq < floor {
15✔
6208
                        delete(mset.preAcks, seq)
3✔
6209
                }
3✔
6210
        }
6211
}
6212

6213
// This will register an ack for a consumer if it arrives before the actual message.
6214
func (mset *stream) registerPreAckLock(o *consumer, seq uint64) {
9✔
6215
        mset.mu.Lock()
9✔
6216
        defer mset.mu.Unlock()
9✔
6217
        mset.registerPreAck(o, seq)
9✔
6218
}
9✔
6219

6220
// This will register an ack for a consumer if it arrives before
6221
// the actual message.
6222
// Write lock should be held.
6223
func (mset *stream) registerPreAck(o *consumer, seq uint64) {
30✔
6224
        if o == nil {
30✔
6225
                return
×
6226
        }
×
6227
        if mset.preAcks == nil {
40✔
6228
                mset.preAcks = make(map[uint64]map[*consumer]struct{})
10✔
6229
        }
10✔
6230
        if mset.preAcks[seq] == nil {
60✔
6231
                mset.preAcks[seq] = make(map[*consumer]struct{})
30✔
6232
        }
30✔
6233
        mset.preAcks[seq][o] = struct{}{}
30✔
6234
}
6235

6236
// This will clear an ack for a consumer.
6237
// Write lock should be held.
6238
func (mset *stream) clearPreAck(o *consumer, seq uint64) {
71,908✔
6239
        if o == nil || len(mset.preAcks) == 0 {
143,813✔
6240
                return
71,905✔
6241
        }
71,905✔
6242
        if consumers := mset.preAcks[seq]; len(consumers) > 0 {
3✔
6243
                delete(consumers, o)
×
6244
                if len(consumers) == 0 {
×
6245
                        delete(mset.preAcks, seq)
×
6246
                }
×
6247
        }
6248
}
6249

6250
// ackMsg is called into from a consumer when we have a WorkQueue or Interest Retention Policy.
6251
// Returns whether the message at seq was removed as a result of the ACK.
6252
// (Or should be removed in the case of clustered streams, since it requires a message delete proposal)
6253
func (mset *stream) ackMsg(o *consumer, seq uint64) bool {
72,003✔
6254
        if seq == 0 {
72,003✔
6255
                return false
×
6256
        }
×
6257

6258
        // Don't make this RLock(). We need to have only 1 running at a time to gauge interest across all consumers.
6259
        mset.mu.Lock()
72,003✔
6260
        if mset.closed.Load() || mset.cfg.Retention == LimitsPolicy {
72,077✔
6261
                mset.mu.Unlock()
74✔
6262
                return false
74✔
6263
        }
74✔
6264

6265
        store := mset.store
71,929✔
6266
        var state StreamState
71,929✔
6267
        store.FastState(&state)
71,929✔
6268

71,929✔
6269
        // If this has arrived before we have processed the message itself.
71,929✔
6270
        if seq > state.LastSeq {
71,950✔
6271
                mset.registerPreAck(o, seq)
21✔
6272
                mset.mu.Unlock()
21✔
6273
                // We have not removed the message, but should still signal so we could retry later
21✔
6274
                // since we potentially need to remove it then.
21✔
6275
                return true
21✔
6276
        }
21✔
6277

6278
        // Always clear pre-ack if here.
6279
        mset.clearPreAck(o, seq)
71,908✔
6280

71,908✔
6281
        // Make sure this sequence is not below our first sequence.
71,908✔
6282
        if seq < state.FirstSeq {
72,174✔
6283
                mset.mu.Unlock()
266✔
6284
                return false
266✔
6285
        }
266✔
6286

6287
        var shouldRemove bool
71,642✔
6288
        switch mset.cfg.Retention {
71,642✔
6289
        case WorkQueuePolicy:
14,243✔
6290
                // Normally we just remove a message when its ack'd here but if we have direct consumers
14,243✔
6291
                // from sources and/or mirrors we need to make sure they have delivered the msg.
14,243✔
6292
                shouldRemove = mset.directs <= 0 || mset.noInterest(seq, o)
14,243✔
6293
        case InterestPolicy:
57,399✔
6294
                shouldRemove = mset.noInterest(seq, o)
57,399✔
6295
        }
6296

6297
        // If nothing else to do.
6298
        if !shouldRemove {
74,114✔
6299
                mset.mu.Unlock()
2,472✔
6300
                return false
2,472✔
6301
        }
2,472✔
6302

6303
        if !mset.isClustered() {
70,986✔
6304
                mset.mu.Unlock()
1,816✔
6305
                // If we are here we should attempt to remove.
1,816✔
6306
                if _, err := store.RemoveMsg(seq); err == ErrStoreEOF {
1,816✔
6307
                        // This should not happen, but being pedantic.
×
6308
                        mset.registerPreAckLock(o, seq)
×
6309
                }
×
6310
                return true
1,816✔
6311
        }
6312

6313
        // Only propose message deletion to the stream if we're consumer leader, otherwise all followers would also propose.
6314
        // We must be the consumer leader, since we know for sure we've stored the message and don't register as pre-ack.
6315
        if o != nil && !o.IsLeader() {
112,570✔
6316
                mset.mu.Unlock()
45,216✔
6317
                // Must still mark as removal if follower. If we become leader later, we must be able to retry the proposal.
45,216✔
6318
                return true
45,216✔
6319
        }
45,216✔
6320

6321
        md := streamMsgDelete{Seq: seq, NoErase: true, Stream: mset.cfg.Name}
22,138✔
6322
        mset.node.ForwardProposal(encodeMsgDelete(&md))
22,138✔
6323
        mset.mu.Unlock()
22,138✔
6324
        return true
22,138✔
6325
}
6326

6327
// Snapshot creates a snapshot for the stream and possibly consumers.
6328
func (mset *stream) snapshot(deadline time.Duration, checkMsgs, includeConsumers bool) (*SnapshotResult, error) {
14✔
6329
        if mset.closed.Load() {
14✔
6330
                return nil, errStreamClosed
×
6331
        }
×
6332
        store := mset.store
14✔
6333
        return store.Snapshot(deadline, checkMsgs, includeConsumers)
14✔
6334
}
6335

6336
const snapsDir = "__snapshots__"
6337

6338
// RestoreStream will restore a stream from a snapshot.
6339
func (a *Account) RestoreStream(ncfg *StreamConfig, r io.Reader) (*stream, error) {
24✔
6340
        if ncfg == nil {
24✔
6341
                return nil, errors.New("nil config on stream restore")
×
6342
        }
×
6343

6344
        s, jsa, err := a.checkForJetStream()
24✔
6345
        if err != nil {
24✔
6346
                return nil, err
×
6347
        }
×
6348
        js := jsa.js
24✔
6349
        if js == nil {
24✔
6350
                return nil, NewJSNotEnabledForAccountError()
×
6351
        }
×
6352

6353
        cfg, apiErr := s.checkStreamCfg(ncfg, a, false)
24✔
6354
        if apiErr != nil {
24✔
6355
                return nil, apiErr
×
6356
        }
×
6357

6358
        sd := filepath.Join(jsa.storeDir, snapsDir)
24✔
6359
        if _, err := os.Stat(sd); os.IsNotExist(err) {
44✔
6360
                if err := os.MkdirAll(sd, defaultDirPerms); err != nil {
20✔
6361
                        return nil, fmt.Errorf("could not create snapshots directory - %v", err)
×
6362
                }
×
6363
        }
6364
        sdir, err := os.MkdirTemp(sd, "snap-")
24✔
6365
        if err != nil {
24✔
6366
                return nil, err
×
6367
        }
×
6368
        if _, err := os.Stat(sdir); os.IsNotExist(err) {
24✔
6369
                if err := os.MkdirAll(sdir, defaultDirPerms); err != nil {
×
6370
                        return nil, fmt.Errorf("could not create snapshots directory - %v", err)
×
6371
                }
×
6372
        }
6373
        defer os.RemoveAll(sdir)
24✔
6374

24✔
6375
        logAndReturnError := func() error {
25✔
6376
                a.mu.RLock()
1✔
6377
                err := fmt.Errorf("unexpected content (account=%s)", a.Name)
1✔
6378
                if a.srv != nil {
2✔
6379
                        a.srv.Errorf("Stream restore failed due to %v", err)
1✔
6380
                }
1✔
6381
                a.mu.RUnlock()
1✔
6382
                return err
1✔
6383
        }
6384
        sdirCheck := filepath.Clean(sdir) + string(os.PathSeparator)
24✔
6385

24✔
6386
        _, isClustered := jsa.jetStreamAndClustered()
24✔
6387
        jsa.usageMu.RLock()
24✔
6388
        selected, tier, hasTier := jsa.selectLimits(cfg.Replicas)
24✔
6389
        jsa.usageMu.RUnlock()
24✔
6390
        reserved := int64(0)
24✔
6391
        if hasTier {
48✔
6392
                if isClustered {
32✔
6393
                        js.mu.RLock()
8✔
6394
                        _, reserved = tieredStreamAndReservationCount(js.cluster.streams[a.Name], tier, &cfg)
8✔
6395
                        js.mu.RUnlock()
8✔
6396
                } else {
24✔
6397
                        reserved = jsa.tieredReservation(tier, &cfg)
16✔
6398
                }
16✔
6399
        }
6400

6401
        var bc int64
24✔
6402
        tr := tar.NewReader(s2.NewReader(r))
24✔
6403
        for {
229✔
6404
                hdr, err := tr.Next()
205✔
6405
                if err == io.EOF {
228✔
6406
                        break // End of snapshot
23✔
6407
                }
6408
                if err != nil {
182✔
6409
                        return nil, err
×
6410
                }
×
6411
                if hdr.Typeflag != tar.TypeReg {
182✔
6412
                        return nil, logAndReturnError()
×
6413
                }
×
6414
                bc += hdr.Size
182✔
6415
                js.mu.RLock()
182✔
6416
                err = js.checkAllLimits(&selected, &cfg, reserved, bc)
182✔
6417
                js.mu.RUnlock()
182✔
6418
                if err != nil {
182✔
6419
                        return nil, err
×
6420
                }
×
6421
                fpath := filepath.Join(sdir, filepath.Clean(hdr.Name))
182✔
6422
                if !strings.HasPrefix(fpath, sdirCheck) {
183✔
6423
                        return nil, logAndReturnError()
1✔
6424
                }
1✔
6425
                os.MkdirAll(filepath.Dir(fpath), defaultDirPerms)
181✔
6426
                fd, err := os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0600)
181✔
6427
                if err != nil {
181✔
6428
                        return nil, err
×
6429
                }
×
6430
                _, err = io.Copy(fd, tr)
181✔
6431
                fd.Close()
181✔
6432
                if err != nil {
181✔
6433
                        return nil, err
×
6434
                }
×
6435
        }
6436

6437
        // Check metadata.
6438
        // The cfg passed in will be the new identity for the stream.
6439
        var fcfg FileStreamInfo
23✔
6440
        b, err := os.ReadFile(filepath.Join(sdir, JetStreamMetaFile))
23✔
6441
        if err != nil {
23✔
6442
                return nil, err
×
6443
        }
×
6444
        if err := json.Unmarshal(b, &fcfg); err != nil {
23✔
6445
                return nil, err
×
6446
        }
×
6447

6448
        // Check to make sure names match.
6449
        if fcfg.Name != cfg.Name {
24✔
6450
                return nil, errors.New("stream names do not match")
1✔
6451
        }
1✔
6452

6453
        // See if this stream already exists.
6454
        if _, err := a.lookupStream(cfg.Name); err == nil {
23✔
6455
                return nil, NewJSStreamNameExistRestoreFailedError()
1✔
6456
        }
1✔
6457
        // Move into the correct place here.
6458
        ndir := filepath.Join(jsa.storeDir, streamsDir, cfg.Name)
21✔
6459
        // Remove old one if for some reason it is still here.
21✔
6460
        if _, err := os.Stat(ndir); err == nil {
21✔
6461
                os.RemoveAll(ndir)
×
6462
        }
×
6463
        // Make sure our destination streams directory exists.
6464
        if err := os.MkdirAll(filepath.Join(jsa.storeDir, streamsDir), defaultDirPerms); err != nil {
21✔
6465
                return nil, err
×
6466
        }
×
6467
        // Move into new location.
6468
        if err := os.Rename(sdir, ndir); err != nil {
21✔
6469
                return nil, err
×
6470
        }
×
6471

6472
        if cfg.Template != _EMPTY_ {
21✔
6473
                if err := jsa.addStreamNameToTemplate(cfg.Template, cfg.Name); err != nil {
×
6474
                        return nil, err
×
6475
                }
×
6476
        }
6477
        mset, err := a.addStream(&cfg)
21✔
6478
        if err != nil {
22✔
6479
                // Make sure to clean up after ourselves here.
1✔
6480
                os.RemoveAll(ndir)
1✔
6481
                return nil, err
1✔
6482
        }
1✔
6483
        if !fcfg.Created.IsZero() {
38✔
6484
                mset.setCreatedTime(fcfg.Created)
18✔
6485
        }
18✔
6486

6487
        // Make sure we do an update if the configs have changed.
6488
        if !reflect.DeepEqual(fcfg.StreamConfig, cfg) {
25✔
6489
                if err := mset.update(&cfg); err != nil {
5✔
6490
                        return nil, err
×
6491
                }
×
6492
        }
6493

6494
        // Now do consumers.
6495
        odir := filepath.Join(ndir, consumerDir)
20✔
6496
        ofis, _ := os.ReadDir(odir)
20✔
6497
        for _, ofi := range ofis {
38✔
6498
                metafile := filepath.Join(odir, ofi.Name(), JetStreamMetaFile)
18✔
6499
                metasum := filepath.Join(odir, ofi.Name(), JetStreamMetaFileSum)
18✔
6500
                if _, err := os.Stat(metafile); os.IsNotExist(err) {
18✔
6501
                        mset.stop(true, false)
×
6502
                        return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err)
×
6503
                }
×
6504
                buf, err := os.ReadFile(metafile)
18✔
6505
                if err != nil {
18✔
6506
                        mset.stop(true, false)
×
6507
                        return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err)
×
6508
                }
×
6509
                if _, err := os.Stat(metasum); os.IsNotExist(err) {
18✔
6510
                        mset.stop(true, false)
×
6511
                        return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err)
×
6512
                }
×
6513
                var cfg FileConsumerInfo
18✔
6514
                if err := json.Unmarshal(buf, &cfg); err != nil {
18✔
6515
                        mset.stop(true, false)
×
6516
                        return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err)
×
6517
                }
×
6518
                isEphemeral := !isDurableConsumer(&cfg.ConsumerConfig)
18✔
6519
                if isEphemeral {
18✔
6520
                        // This is an ephermal consumer and this could fail on restart until
×
6521
                        // the consumer can reconnect. We will create it as a durable and switch it.
×
6522
                        cfg.ConsumerConfig.Durable = ofi.Name()
×
6523
                }
×
6524
                obs, err := mset.addConsumer(&cfg.ConsumerConfig)
18✔
6525
                if err != nil {
18✔
6526
                        mset.stop(true, false)
×
6527
                        return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err)
×
6528
                }
×
6529
                if isEphemeral {
18✔
6530
                        obs.switchToEphemeral()
×
6531
                }
×
6532
                if !cfg.Created.IsZero() {
36✔
6533
                        obs.setCreatedTime(cfg.Created)
18✔
6534
                }
18✔
6535
                obs.mu.Lock()
18✔
6536
                err = obs.readStoredState()
18✔
6537
                obs.mu.Unlock()
18✔
6538
                if err != nil {
18✔
6539
                        mset.stop(true, false)
×
6540
                        return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err)
×
6541
                }
×
6542
        }
6543
        return mset, nil
20✔
6544
}
6545

6546
// This is to check for dangling messages on interest retention streams. Only called on account enable.
6547
// Issue https://github.com/nats-io/nats-server/issues/3612
6548
func (mset *stream) checkForOrphanMsgs() {
50✔
6549
        mset.mu.RLock()
50✔
6550
        consumers := make([]*consumer, 0, len(mset.consumers))
50✔
6551
        for _, o := range mset.consumers {
64✔
6552
                consumers = append(consumers, o)
14✔
6553
        }
14✔
6554
        accName, stream := mset.acc.Name, mset.cfg.Name
50✔
6555

50✔
6556
        var ss StreamState
50✔
6557
        mset.store.FastState(&ss)
50✔
6558
        mset.mu.RUnlock()
50✔
6559

50✔
6560
        for _, o := range consumers {
64✔
6561
                if err := o.checkStateForInterestStream(&ss); err == errAckFloorHigherThanLastSeq {
15✔
6562
                        o.mu.RLock()
1✔
6563
                        s, consumer := o.srv, o.name
1✔
6564
                        state, _ := o.store.State()
1✔
6565
                        asflr := state.AckFloor.Stream
1✔
6566
                        o.mu.RUnlock()
1✔
6567
                        // Warn about stream state vs our ack floor.
1✔
6568
                        s.RateLimitWarnf("Detected consumer '%s > %s > %s' ack floor %d is ahead of stream's last sequence %d",
1✔
6569
                                accName, stream, consumer, asflr, ss.LastSeq)
1✔
6570
                }
1✔
6571
        }
6572
}
6573

6574
// Check on startup to make sure that consumers replication matches us.
6575
// Interest retention requires replication matches.
6576
func (mset *stream) checkConsumerReplication() {
50✔
6577
        mset.mu.RLock()
50✔
6578
        defer mset.mu.RUnlock()
50✔
6579

50✔
6580
        if mset.cfg.Retention != InterestPolicy {
50✔
6581
                return
×
6582
        }
×
6583

6584
        s, acc := mset.srv, mset.acc
50✔
6585
        for _, o := range mset.consumers {
64✔
6586
                o.mu.RLock()
14✔
6587
                // Consumer replicas 0 can be a legit config for the replicas and we will inherit from the stream
14✔
6588
                // when this is the case.
14✔
6589
                if mset.cfg.Replicas != o.cfg.Replicas && o.cfg.Replicas != 0 {
14✔
6590
                        s.Errorf("consumer '%s > %s > %s' MUST match replication (%d vs %d) of stream with interest policy",
×
6591
                                acc, mset.cfg.Name, o.cfg.Name, mset.cfg.Replicas, o.cfg.Replicas)
×
6592
                }
×
6593
                o.mu.RUnlock()
14✔
6594
        }
6595
}
6596

6597
// Will check if we are running in the monitor already and if not set the appropriate flag.
6598
func (mset *stream) checkInMonitor() bool {
3,008✔
6599
        mset.mu.Lock()
3,008✔
6600
        defer mset.mu.Unlock()
3,008✔
6601

3,008✔
6602
        if mset.inMonitor {
3,008✔
6603
                return true
×
6604
        }
×
6605
        mset.inMonitor = true
3,008✔
6606
        return false
3,008✔
6607
}
6608

6609
// Clear us being in the monitor routine.
6610
func (mset *stream) clearMonitorRunning() {
3,008✔
6611
        mset.mu.Lock()
3,008✔
6612
        defer mset.mu.Unlock()
3,008✔
6613
        mset.inMonitor = false
3,008✔
6614
}
3,008✔
6615

6616
// Check if our monitor is running.
6617
func (mset *stream) isMonitorRunning() bool {
832✔
6618
        mset.mu.RLock()
832✔
6619
        defer mset.mu.RUnlock()
832✔
6620
        return mset.inMonitor
832✔
6621
}
832✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc