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

nats-io / nats-server / 15339392784

29 May 2025 08:38AM UTC coverage: 85.689% (+0.05%) from 85.641%
15339392784

push

github

web-flow
[FIXED] LeafNode: Unable to reply if origin originates from super-cluster (#6931)

If a request originates from cluster A and is routed to cluster B then
to a leafnode where a service is running, sending back the reply could
fail if the leafnode has restrictive publish permissions.

Resolves #6894

Signed-off-by: Ivan Kozlovic <ivan@synadia.com>

69965 of 81650 relevant lines covered (85.69%)

367460.0 hits per line

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

85.21
/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 {
544✔
118
        clone := *cfg
544✔
119
        if cfg.Placement != nil {
599✔
120
                placement := *cfg.Placement
55✔
121
                clone.Placement = &placement
55✔
122
        }
55✔
123
        if cfg.Mirror != nil {
545✔
124
                mirror := *cfg.Mirror
1✔
125
                clone.Mirror = &mirror
1✔
126
        }
1✔
127
        if len(cfg.Sources) > 0 {
564✔
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 {
545✔
135
                transform := *cfg.SubjectTransform
1✔
136
                clone.SubjectTransform = &transform
1✔
137
        }
1✔
138
        if cfg.RePublish != nil {
545✔
139
                rePublish := *cfg.RePublish
1✔
140
                clone.RePublish = &rePublish
1✔
141
        }
1✔
142
        if cfg.Metadata != nil {
1,088✔
143
                clone.Metadata = make(map[string]string, len(cfg.Metadata))
544✔
144
                for k, v := range cfg.Metadata {
1,087✔
145
                        clone.Metadata[k] = v
543✔
146
                }
543✔
147
        }
148
        return &clone
544✔
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) {
967✔
466
        return a.addStreamWithAssignment(config, nil, nil, false)
967✔
467
}
967✔
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,120✔
475
        return a.addStreamWithAssignment(config, nil, nil, pedantic)
1,120✔
476
}
1,120✔
477

478
func (a *Account) addStreamWithAssignment(config *StreamConfig, fsConfig *FileStoreConfig, sa *streamAssignment, pedantic bool) (*stream, error) {
5,574✔
479
        s, jsa, err := a.checkForJetStream()
5,574✔
480
        if err != nil {
5,574✔
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,574✔
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,574✔
493
        if apiErr != nil {
5,629✔
494
                return nil, apiErr
55✔
495
        }
55✔
496
        cfg := &ccfg
5,519✔
497

5,519✔
498
        singleServerMode := !s.JetStreamIsClustered() && s.standAloneMode()
5,519✔
499
        if singleServerMode && cfg.Replicas > 1 {
5,521✔
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,517✔
511
        swg.Add(1)
5,517✔
512
        v, loaded := jsa.inflight.LoadOrStore(cfg.Name, swg)
5,517✔
513
        wg := v.(*sync.WaitGroup)
5,517✔
514
        if loaded {
5,517✔
515
                wg.Wait()
×
516
                // This waitgroup is "thrown away" (since there was an existing one).
×
517
                swg.Done()
×
518
        } else {
5,517✔
519
                defer func() {
11,034✔
520
                        jsa.inflight.Delete(cfg.Name)
5,517✔
521
                        wg.Done()
5,517✔
522
                }()
5,517✔
523
        }
524

525
        js, isClustered := jsa.jetStreamAndClustered()
5,517✔
526
        jsa.mu.Lock()
5,517✔
527
        if mset, ok := jsa.streams[cfg.Name]; ok {
5,534✔
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,500✔
548
        selected, tier, hasTier := jsa.selectLimits(cfg.Replicas)
5,500✔
549
        jsa.usageMu.RUnlock()
5,500✔
550
        reserved := int64(0)
5,500✔
551
        if !isClustered {
7,510✔
552
                reserved = jsa.tieredReservation(tier, cfg)
2,010✔
553
        }
2,010✔
554
        jsa.mu.Unlock()
5,500✔
555

5,500✔
556
        if !hasTier {
5,501✔
557
                return nil, NewJSNoLimitsError()
1✔
558
        }
1✔
559
        js.mu.RLock()
5,499✔
560
        if isClustered {
8,989✔
561
                _, reserved = tieredStreamAndReservationCount(js.cluster.streams[a.Name], tier, cfg)
3,490✔
562
        }
3,490✔
563
        if err := js.checkAllLimits(&selected, cfg, reserved, 0); err != nil {
5,508✔
564
                js.mu.RUnlock()
9✔
565
                return nil, err
9✔
566
        }
9✔
567
        js.mu.RUnlock()
5,490✔
568
        jsa.mu.Lock()
5,490✔
569
        // Check for template ownership if present.
5,490✔
570
        if cfg.Template != _EMPTY_ && jsa.account != nil {
5,696✔
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,576✔
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,643✔
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,515✔
629
                jsa.mu.Unlock()
26✔
630
                return nil, NewJSStreamSubjectOverlapError()
26✔
631
        }
26✔
632

633
        if !hasTier {
5,463✔
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,463✔
640
        ic := s.createInternalJetStreamClient()
5,463✔
641

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

652
        qpfx := fmt.Sprintf("[ACC:%s] stream '%s' ", a.Name, config.Name)
5,463✔
653
        mset := &stream{
5,463✔
654
                acc:       a,
5,463✔
655
                jsa:       jsa,
5,463✔
656
                cfg:       *cfg,
5,463✔
657
                js:        js,
5,463✔
658
                srv:       s,
5,463✔
659
                client:    c,
5,463✔
660
                sysc:      ic,
5,463✔
661
                tier:      tier,
5,463✔
662
                stype:     cfg.Storage,
5,463✔
663
                consumers: make(map[string]*consumer),
5,463✔
664
                msgs: newIPQueue[*inMsg](s, qpfx+"messages",
5,463✔
665
                        ipqSizeCalculation(func(msg *inMsg) uint64 {
744,306✔
666
                                return uint64(len(msg.hdr) + len(msg.msg) + len(msg.rply) + len(msg.subj))
738,843✔
667
                        }),
738,843✔
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,463✔
680
        go mset.signalConsumersLoop()
5,463✔
681

5,463✔
682
        // For no-ack consumers when we are interest retention.
5,463✔
683
        if cfg.Retention != LimitsPolicy {
6,969✔
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,466✔
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,473✔
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,463✔
708
        jsa.mu.Unlock()
5,463✔
709

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

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

5,463✔
732
        if err := mset.setupStore(fsCfg); err != nil {
5,464✔
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,676✔
739
                mset.pubAck = []byte(fmt.Sprintf("{%q:%q, %q:%q, %q:", "stream", cfg.Name, "domain", domain, "seq"))
214✔
740
        } else {
5,462✔
741
                mset.pubAck = []byte(fmt.Sprintf("{%q:%q, %q:", "stream", cfg.Name, "seq"))
5,248✔
742
        }
5,248✔
743
        end := len(mset.pubAck)
5,462✔
744
        mset.pubAck = mset.pubAck[:end:end]
5,462✔
745

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

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

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

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

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

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

5,462✔
776
        // Reserve resources if MaxBytes present.
5,462✔
777
        if reserveResources {
10,909✔
778
                mset.js.reserveStreamResources(&mset.cfg)
5,447✔
779
        }
5,447✔
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,135✔
784
                if err := mset.setLeader(true); err != nil {
1,673✔
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,131✔
792
                // Send advisory.
2,669✔
793
                var suppress bool
2,669✔
794
                if !s.standAloneMode() && sa == nil {
3,000✔
795
                        if cfg.Replicas > 1 {
547✔
796
                                suppress = true
216✔
797
                        }
216✔
798
                } else if sa != nil {
3,003✔
799
                        suppress = sa.responded
665✔
800
                }
665✔
801
                if !suppress {
5,122✔
802
                        mset.sendCreateAdvisory()
2,453✔
803
                }
2,453✔
804
        }
805

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

5,462✔
811
        return mset, nil
5,462✔
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 {
627✔
818
        var iName = ssi.Name
627✔
819

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

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

627✔
827
        if len(ssi.SubjectTransforms) == 0 {
1,235✔
828
                // normalize filter and destination in case they are empty
608✔
829
                if source == _EMPTY_ {
1,111✔
830
                        source = fwcs
503✔
831
                }
503✔
832
                if destination == _EMPTY_ {
608✔
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}, " ")
627✔
854
}
855

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

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

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

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

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

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

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

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

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

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

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

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

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

937
// Lock should be held.
938
func (mset *stream) isLeader() bool {
467,371✔
939
        if mset.isClustered() {
922,843✔
940
                return mset.node.Leader()
455,472✔
941
        }
455,472✔
942
        return true
11,899✔
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,429,850✔
951
        if mset.isClustered() {
2,556,077✔
952
                return mset.node.State() == Leader
1,126,227✔
953
        }
1,126,227✔
954
        return true
303,623✔
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,732✔
959
        mset.mu.Lock()
8,732✔
960
        // If we are here we have a change in leader status.
8,732✔
961
        if isLeader {
12,619✔
962
                // Make sure we are listening for sync requests.
3,887✔
963
                // TODO(dlc) - Original design was that all in sync members of the group would do DQ.
3,887✔
964
                if mset.isClustered() {
5,321✔
965
                        mset.startClusterSubs()
1,434✔
966
                }
1,434✔
967

968
                // Setup subscriptions if we were not already the leader.
969
                if err := mset.subscribeToStream(); err != nil {
3,887✔
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,845✔
978
                // cancel timer to create the source consumers if not fired yet
4,845✔
979
                if mset.sourcesConsumerSetup != nil {
4,873✔
980
                        mset.sourcesConsumerSetup.Stop()
28✔
981
                        mset.sourcesConsumerSetup = nil
28✔
982
                } else {
4,845✔
983
                        // Stop any source consumers
4,817✔
984
                        mset.stopSourceConsumers()
4,817✔
985
                }
4,817✔
986

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

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

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

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

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

1018
// account gets the account for this stream.
1019
func (mset *stream) account() *Account {
67,038✔
1020
        mset.mu.RLock()
67,038✔
1021
        jsa := mset.jsa
67,038✔
1022
        mset.mu.RUnlock()
67,038✔
1023
        if jsa == nil {
67,038✔
1024
                return nil
×
1025
        }
×
1026
        return jsa.acc()
67,038✔
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,129✔
1067
        var totalEstSize uint64
5,129✔
1068

5,129✔
1069
        // MaxBytes will take precedence for now.
5,129✔
1070
        if mset.cfg.MaxBytes > 0 {
5,268✔
1071
                totalEstSize = uint64(mset.cfg.MaxBytes)
139✔
1072
        } else if mset.cfg.MaxMsgs > 0 {
5,400✔
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,668✔
1076
                fsCfg.BlockSize = uint64(defaultKVBlockSize)
678✔
1077
                return
678✔
1078
        } else {
4,719✔
1079
                // If nothing set will let underlying filestore determine blkSize.
4,041✔
1080
                return
4,041✔
1081
        }
4,041✔
1082

1083
        blkSize := (totalEstSize / 4) + 1 // (25% overhead)
410✔
1084
        // Round up to nearest 100
410✔
1085
        if m := blkSize % 100; m != 0 {
820✔
1086
                blkSize += 100 - m
410✔
1087
        }
410✔
1088
        if blkSize <= FileStoreMinBlkSize {
451✔
1089
                blkSize = FileStoreMinBlkSize
41✔
1090
        } else if blkSize >= FileStoreMaxBlkSize {
718✔
1091
                blkSize = FileStoreMaxBlkSize
308✔
1092
        } else {
369✔
1093
                blkSize = defaultMediumBlockSize
61✔
1094
        }
61✔
1095
        fsCfg.BlockSize = uint64(blkSize)
410✔
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,282✔
1121
                sm, err := mset.store.LoadMsg(seq, &smv)
307,275✔
1122
                if err != nil {
307,275✔
1123
                        continue
×
1124
                }
1125
                var msgId string
307,275✔
1126
                if len(sm.hdr) > 0 {
614,550✔
1127
                        if msgId = getMsgId(sm.hdr); msgId != _EMPTY_ {
614,549✔
1128
                                mset.storeMsgIdLocked(&ddentry{msgId, sm.seq, sm.ts})
307,274✔
1129
                        }
307,274✔
1130
                }
1131
                if seq == state.LastSeq {
307,282✔
1132
                        mset.lmsgId = msgId
7✔
1133
                }
7✔
1134
        }
1135
}
1136

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

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

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

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

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

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

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

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

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

1198
        subj := JSAdvisoryStreamCreatedPre + "." + name
3,121✔
1199
        outq.sendMsg(subj, j)
3,121✔
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() {
207✔
1227
        if mset.outq == nil {
207✔
1228
                return
×
1229
        }
×
1230

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

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

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

1257
// Internal to allow creation time to be restored.
1258
func (mset *stream) setCreatedTime(created time.Time) {
4,409✔
1259
        mset.mu.Lock()
4,409✔
1260
        mset.created = created
4,409✔
1261
        mset.mu.Unlock()
4,409✔
1262
}
4,409✔
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,974✔
1268
        for _, mset := range jsa.streams {
61,961✔
1269
                if self != nil && mset == self {
56,471✔
1270
                        continue
484✔
1271
                }
1272
                for _, subj := range mset.cfg.Subjects {
111,157✔
1273
                        for _, tsubj := range subjects {
111,735✔
1274
                                if SubjectsCollide(tsubj, subj) {
56,108✔
1275
                                        return true
27✔
1276
                                }
27✔
1277
                        }
1278
                }
1279
        }
1280
        return false
5,947✔
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) {
8,063✔
1287
        lim := &s.getOpts().JetStreamLimits
8,063✔
1288

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

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

1310
        cfg := *config
8,054✔
1311

8,054✔
1312
        // Make file the default.
8,054✔
1313
        if cfg.Storage == 0 {
8,122✔
1314
                cfg.Storage = FileStorage
68✔
1315
        }
68✔
1316
        if cfg.Replicas == 0 {
9,080✔
1317
                cfg.Replicas = 1
1,026✔
1318
        }
1,026✔
1319
        if cfg.Replicas > StreamMaxReplicas {
8,059✔
1320
                return cfg, NewJSStreamInvalidConfigError(fmt.Errorf("maximum replicas is %d", StreamMaxReplicas))
5✔
1321
        }
5✔
1322
        if cfg.Replicas < 0 {
8,053✔
1323
                return cfg, NewJSReplicasCountCannotBeNegativeError()
4✔
1324
        }
4✔
1325
        if cfg.MaxMsgs == 0 {
11,132✔
1326
                cfg.MaxMsgs = -1
3,087✔
1327
        }
3,087✔
1328
        if cfg.MaxMsgsPer == 0 {
10,692✔
1329
                cfg.MaxMsgsPer = -1
2,647✔
1330
        }
2,647✔
1331
        if cfg.MaxBytes == 0 {
11,064✔
1332
                cfg.MaxBytes = -1
3,019✔
1333
        }
3,019✔
1334
        if cfg.MaxMsgSize == 0 {
11,186✔
1335
                cfg.MaxMsgSize = -1
3,141✔
1336
        }
3,141✔
1337
        if cfg.MaxConsumers == 0 {
11,195✔
1338
                cfg.MaxConsumers = -1
3,150✔
1339
        }
3,150✔
1340
        if cfg.Duplicates == 0 && cfg.Mirror == nil {
11,110✔
1341
                maxWindow := StreamDefaultDuplicatesWindow
3,065✔
1342
                if lim.Duplicates > 0 && maxWindow > lim.Duplicates {
3,069✔
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,128✔
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 {
3,002✔
1354
                        cfg.Duplicates = maxWindow
3,002✔
1355
                }
3,002✔
1356
        }
1357
        if cfg.MaxAge > 0 && cfg.MaxAge < 100*time.Millisecond {
8,045✔
1358
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("max age needs to be >= 100ms"))
×
1359
        }
×
1360
        if cfg.Duplicates < 0 {
8,047✔
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 {
8,046✔
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 {
8,049✔
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 {
8,031✔
1372
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicates window needs to be >= 100ms"))
×
1373
        }
×
1374

1375
        if cfg.DenyPurge && cfg.AllowRollup {
8,033✔
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,269✔
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,188✔
1390
                if cfg.SubjectDeleteMarkerTTL < time.Second {
168✔
1391
                        return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete marker TTL must be at least 1 second"))
1✔
1392
                }
1✔
1393
                if !cfg.AllowMsgTTL {
188✔
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 {
209✔
1400
                        if pedantic {
45✔
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
43✔
1404
                }
1405
        } else if cfg.SubjectDeleteMarkerTTL < 0 {
7,855✔
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,790✔
1410
                var exists bool
773✔
1411
                var cfg StreamConfig
773✔
1412
                if s.JetStreamIsClustered() {
1,330✔
1413
                        if js, _ := s.getJetStreamCluster(); js != nil {
1,114✔
1414
                                js.mu.RLock()
557✔
1415
                                if sa := js.streamAssignment(acc.Name, streamName); sa != nil {
1,063✔
1416
                                        cfg = *sa.Config.clone()
506✔
1417
                                        exists = true
506✔
1418
                                }
506✔
1419
                                js.mu.RUnlock()
557✔
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
773✔
1426
        }
1427

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

1433
        var streamSubs []string
8,017✔
1434
        var deliveryPrefixes []string
8,017✔
1435
        var apiPrefixes []string
8,017✔
1436

8,017✔
1437
        // Do some pre-checking for mirror config to avoid cycles in clustered mode.
8,017✔
1438
        if cfg.Mirror != nil {
8,145✔
1439
                if cfg.FirstSeq > 0 {
129✔
1440
                        return StreamConfig{}, NewJSMirrorWithFirstSeqError()
1✔
1441
                }
1✔
1442
                if len(cfg.Subjects) > 0 {
129✔
1443
                        return StreamConfig{}, NewJSMirrorWithSubjectsError()
2✔
1444
                }
2✔
1445
                if len(cfg.Sources) > 0 {
125✔
1446
                        return StreamConfig{}, NewJSMirrorWithSourcesError()
×
1447
                }
×
1448
                if cfg.Mirror.FilterSubject != _EMPTY_ && len(cfg.Mirror.SubjectTransforms) != 0 {
126✔
1449
                        return StreamConfig{}, NewJSMirrorMultipleFiltersNotAllowedError()
1✔
1450
                }
1✔
1451
                if cfg.SubjectDeleteMarkerTTL > 0 {
125✔
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 {
136✔
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 {
215✔
1477
                        if !isValidName(cfg.Mirror.Name) {
98✔
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)
98✔
1482
                        if len(subs) > 0 {
173✔
1483
                                streamSubs = append(streamSubs, subs...)
75✔
1484
                        }
75✔
1485
                        if exists {
177✔
1486
                                if cfg.MaxMsgSize > 0 && maxMsgSize > 0 && cfg.MaxMsgSize < maxMsgSize {
79✔
1487
                                        return StreamConfig{}, NewJSMirrorMaxMessageSizeTooBigError()
×
1488
                                }
×
1489
                        }
1490
                        // Determine if we are inheriting direct gets.
1491
                        if exists, ocfg := getStream(cfg.Mirror.Name); exists {
177✔
1492
                                if pedantic && cfg.MirrorDirect != ocfg.AllowDirect {
79✔
1493
                                        return StreamConfig{}, NewJSPedanticError(fmt.Errorf("origin stream has direct get set, mirror has it disabled"))
×
1494
                                }
×
1495
                                cfg.MirrorDirect = ocfg.AllowDirect
79✔
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{})
8,006✔
1525
        for _, src := range cfg.Sources {
8,260✔
1526
                if !isValidName(src.Name) {
255✔
1527
                        return StreamConfig{}, NewJSSourceInvalidStreamNameError()
1✔
1528
                }
1✔
1529
                if _, ok := iNames[src.composeIName()]; !ok {
506✔
1530
                        iNames[src.composeIName()] = struct{}{}
253✔
1531
                } else {
253✔
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 {
475✔
1537
                        exists, maxMsgSize, subs := hasStream(src.Name)
222✔
1538
                        if len(subs) > 0 {
397✔
1539
                                streamSubs = append(streamSubs, subs...)
175✔
1540
                        }
175✔
1541
                        if exists {
397✔
1542
                                if cfg.MaxMsgSize > 0 && maxMsgSize > 0 && cfg.MaxMsgSize < maxMsgSize {
175✔
1543
                                        return StreamConfig{}, NewJSSourceMaxMessageSizeTooBigError()
×
1544
                                }
×
1545
                        }
1546

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

1551
                        for _, tr := range src.SubjectTransforms {
231✔
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 {
227✔
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
220✔
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 {
8,019✔
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 {
8,053✔
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}
8,001✔
1605
        visited := make(map[string]struct{})
8,001✔
1606
        overlaps := func(subjects []string, filter string) bool {
8,006✔
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,291✔
1619
                cfg := toVisit[0]
8,290✔
1620
                toVisit = toVisit[1:]
8,290✔
1621
                visited[cfg.Name] = struct{}{}
8,290✔
1622
                for _, src := range cfg.Sources {
8,581✔
1623
                        if src.External != nil {
321✔
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 {
266✔
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 {
465✔
1633
                                toVisit = append(toVisit, &cfg)
209✔
1634
                        }
209✔
1635
                }
1636
                // Avoid cycles hiding behind mirrors
1637
                if m := cfg.Mirror; m != nil {
8,405✔
1638
                        if m.External == nil {
216✔
1639
                                if _, ok := visited[m.Name]; ok {
99✔
1640
                                        return StreamConfig{}, NewJSStreamInvalidConfigError(errors.New("detected cycle"))
×
1641
                                }
×
1642
                                if exists, cfg := getStream(m.Name); exists {
179✔
1643
                                        toVisit = append(toVisit, &cfg)
80✔
1644
                                }
80✔
1645
                        }
1646
                }
1647
        }
1648

1649
        if len(cfg.Subjects) == 0 {
8,799✔
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,199✔
1654
                if cfg.Mirror != nil {
7,199✔
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,199✔
1661
                for _, subj := range cfg.Subjects {
15,022✔
1662
                        // Make sure the subject is valid. Check this first.
7,823✔
1663
                        if !IsValidSubject(subj) {
7,830✔
1664
                                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("invalid subject"))
7✔
1665
                        }
7✔
1666
                        if _, ok := dset[subj]; ok {
7,816✔
1667
                                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicate subjects detected"))
×
1668
                        }
×
1669
                        // Check for trying to capture everything.
1670
                        if subj == fwcs {
7,824✔
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,613✔
1681
                                for _, namespace := range []string{"$JS.>", "$JSC.>", "$NRG.>"} {
31,189✔
1682
                                        if SubjectsCollide(subj, namespace) {
23,398✔
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,797✔
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,802✔
1697
                }
1698
        }
1699

1700
        if len(cfg.Subjects) == 0 && len(cfg.Sources) == 0 && cfg.Mirror == nil {
7,978✔
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,980✔
1707
                return StreamConfig{}, NewJSStreamMaxBytesRequiredError()
2✔
1708
        } else if limit > 0 && cfg.MaxBytes > limit {
7,980✔
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,386✔
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,992✔
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,977✔
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,966✔
1764
                return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("preferred server not permitted in placement"))
×
1765
        }
×
1766

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

1770
// Config returns the stream's configuration.
1771
func (mset *stream) config() StreamConfig {
41,889✔
1772
        mset.cfgMu.RLock()
41,889✔
1773
        defer mset.cfgMu.RUnlock()
41,889✔
1774
        return mset.cfg
41,889✔
1775
}
41,889✔
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) {
668✔
1789
        cfg, apiErr := s.checkStreamCfg(new, jsa.acc(), pedantic)
668✔
1790
        if apiErr != nil {
672✔
1791
                return nil, apiErr
4✔
1792
        }
4✔
1793

1794
        // Name must match.
1795
        if cfg.Name != old.Name {
666✔
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 {
664✔
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 {
662✔
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 {
673✔
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_ {
656✔
1814
                return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update not allowed on template owned stream"))
×
1815
        }
×
1816
        if cfg.Template != _EMPTY_ {
658✔
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 {
656✔
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 {
653✔
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 {
651✔
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) {
653✔
1833
                return nil, NewJSStreamMirrorNotUpdatableError()
2✔
1834
        }
2✔
1835

1836
        // Check on new discard new per subject.
1837
        if cfg.DiscardNewPer {
649✔
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 {
651✔
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 {
666✔
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
647✔
1864
        if maxBytesDiff < 0 {
665✔
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
647✔
1874
        maxBytesOffset := int64(0)
647✔
1875

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

647✔
1882
        // Check limits.
647✔
1883
        js, isClustered := jsa.jetStreamAndClustered()
647✔
1884
        jsa.mu.RLock()
647✔
1885
        acc := jsa.account
647✔
1886
        jsa.usageMu.RLock()
647✔
1887
        selected, tier, hasTier := jsa.selectLimits(cfg.Replicas)
647✔
1888
        if !hasTier && old.Replicas != cfg.Replicas {
647✔
1889
                selected, tier, hasTier = jsa.selectLimits(old.Replicas)
×
1890
        }
×
1891
        jsa.usageMu.RUnlock()
647✔
1892
        reserved := int64(0)
647✔
1893
        if !isClustered {
714✔
1894
                reserved = jsa.tieredReservation(tier, &cfg)
67✔
1895
        }
67✔
1896
        jsa.mu.RUnlock()
647✔
1897
        if !hasTier {
647✔
1898
                return nil, NewJSNoLimitsError()
×
1899
        }
×
1900
        js.mu.RLock()
647✔
1901
        defer js.mu.RUnlock()
647✔
1902
        if isClustered {
1,227✔
1903
                _, reserved = tieredStreamAndReservationCount(js.cluster.streams[acc.Name], tier, &cfg)
580✔
1904
        }
580✔
1905
        // reservation does not account for this stream, hence add the old value
1906
        if tier == _EMPTY_ && old.Replicas > 1 {
1,098✔
1907
                reserved += old.MaxBytes * int64(old.Replicas)
451✔
1908
        } else {
647✔
1909
                reserved += old.MaxBytes
196✔
1910
        }
196✔
1911
        if err := js.checkAllLimits(&selected, &cfg, reserved, maxBytesOffset); err != nil {
654✔
1912
                return nil, err
7✔
1913
        }
7✔
1914
        // Restore the user configured MaxBytes.
1915
        cfg.MaxBytes = newMaxBytes
640✔
1916
        return &cfg, nil
640✔
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 {
511✔
1930
        _, jsa, err := mset.acc.checkForJetStream()
511✔
1931
        if err != nil {
511✔
1932
                return err
×
1933
        }
×
1934

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

511✔
1940
        cfg, err := mset.jsa.configUpdateCheck(&ocfg, config, s, pedantic)
511✔
1941
        if err != nil {
533✔
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 ||
489✔
1948
                ocfg.ConsumerLimits.MaxAckPending != cfg.ConsumerLimits.MaxAckPending
489✔
1949
        if updateLimits {
493✔
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()
485✔
1975
        if jsa.subjectsOverlap(cfg.Subjects, mset) {
486✔
1976
                jsa.mu.RUnlock()
1✔
1977
                return NewJSStreamSubjectOverlapError()
1✔
1978
        }
1✔
1979
        jsa.mu.RUnlock()
484✔
1980

484✔
1981
        mset.mu.Lock()
484✔
1982
        if mset.isLeader() {
696✔
1983
                // Now check for subject interest differences.
212✔
1984
                current := make(map[string]struct{}, len(ocfg.Subjects))
212✔
1985
                for _, s := range ocfg.Subjects {
432✔
1986
                        current[s] = struct{}{}
220✔
1987
                }
220✔
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 {
438✔
1993
                        if _, ok := current[s]; !ok {
244✔
1994
                                if _, err := mset.subscribeInternal(s, mset.processInboundJetStreamMsg); err != nil {
18✔
1995
                                        mset.mu.Unlock()
×
1996
                                        return err
×
1997
                                }
×
1998
                        }
1999
                        delete(current, s)
226✔
2000
                }
2001
                // What is left in current needs to be deleted.
2002
                for s := range current {
224✔
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 {
213✔
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 {
226✔
2017
                        currentIName := make(map[string]struct{})
14✔
2018
                        needsStartingSeqNum := make(map[string]struct{})
14✔
2019

14✔
2020
                        for _, s := range ocfg.Sources {
23✔
2021
                                currentIName[s.iname] = struct{}{}
9✔
2022
                        }
9✔
2023
                        for _, s := range cfg.Sources {
30✔
2024
                                s.setIndexName()
16✔
2025
                                if _, ok := currentIName[s.iname]; !ok {
29✔
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 {
3✔
2055
                                        // source already exists
3✔
2056
                                        delete(currentIName, s.iname)
3✔
2057
                                }
3✔
2058
                        }
2059
                        // What is left in currentIName needs to be deleted.
2060
                        for iName := range currentIName {
20✔
2061
                                mset.cancelSourceConsumer(iName)
6✔
2062
                                delete(mset.sources, iName)
6✔
2063
                        }
6✔
2064
                        neededCopy := make(map[string]struct{}, len(needsStartingSeqNum))
14✔
2065
                        for iName := range needsStartingSeqNum {
27✔
2066
                                neededCopy[iName] = struct{}{}
13✔
2067
                        }
13✔
2068
                        mset.setStartingSequenceForSources(needsStartingSeqNum)
14✔
2069
                        for iName := range neededCopy {
27✔
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 {
491✔
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 {
488✔
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 {
480✔
2103
                mset.tr = nil
480✔
2104
        }
480✔
2105

2106
        // Check for changes to subject transform
2107
        if ocfg.SubjectTransform == nil && cfg.SubjectTransform != nil {
484✔
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 &&
484✔
2115
                (ocfg.SubjectTransform.Source != cfg.SubjectTransform.Source || ocfg.SubjectTransform.Destination != cfg.SubjectTransform.Destination) {
484✔
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 {
484✔
2123
                mset.itr = nil
×
2124
        }
×
2125

2126
        js := mset.js
484✔
2127

484✔
2128
        if targetTier := tierName(cfg.Replicas); mset.tier != targetTier {
954✔
2129
                // In cases such as R1->R3, only one update is needed
470✔
2130
                jsa.usageMu.RLock()
470✔
2131
                _, ok := jsa.limits[targetTier]
470✔
2132
                jsa.usageMu.RUnlock()
470✔
2133
                if ok {
475✔
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 {
488✔
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 {
30✔
2148
                        if c.Config.Replicas > 0 && c.Config.Replicas != cfg.Replicas {
27✔
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()
483✔
2162
        mset.cfg = *cfg
483✔
2163
        mset.cfgMu.Unlock()
483✔
2164

483✔
2165
        // If we're changing retention and haven't errored because of consumer
483✔
2166
        // replicas by now, whip through and update the consumer retention.
483✔
2167
        if ocfg.Retention != cfg.Retention && cfg.Retention == InterestPolicy {
492✔
2168
                toUpdate := make([]*consumer, 0, len(mset.consumers))
9✔
2169
                for _, c := range mset.consumers {
68✔
2170
                        toUpdate = append(toUpdate, c)
59✔
2171
                }
59✔
2172
                var ss StreamState
9✔
2173
                mset.store.FastState(&ss)
9✔
2174
                mset.mu.Unlock()
9✔
2175
                for _, c := range toUpdate {
68✔
2176
                        c.mu.Lock()
59✔
2177
                        c.retention = cfg.Retention
59✔
2178
                        c.mu.Unlock()
59✔
2179
                        if c.retention == InterestPolicy {
118✔
2180
                                // If we're switching to interest, force a check of the
59✔
2181
                                // interest of existing stream messages.
59✔
2182
                                c.checkStateForInterestStream(&ss)
59✔
2183
                        }
59✔
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 {
690✔
2190
                mset.sendUpdateAdvisoryLocked()
207✔
2191
        }
207✔
2192
        mset.mu.Unlock()
483✔
2193

483✔
2194
        if js != nil {
966✔
2195
                maxBytesDiff := cfg.MaxBytes - ocfg.MaxBytes
483✔
2196
                if maxBytesDiff > 0 {
495✔
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 {
497✔
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)
483✔
2212

483✔
2213
        return nil
483✔
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,658✔
2220
        mset.cfgMu.RLock()
4,658✔
2221
        defer mset.cfgMu.RUnlock()
4,658✔
2222
        return mset.cfg.Name
4,658✔
2223
}
4,658✔
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) {
303✔
2227
        mset.mu.RLock()
303✔
2228
        if mset.closed.Load() {
303✔
2229
                mset.mu.RUnlock()
×
2230
                return 0, errStreamClosed
×
2231
        }
×
2232
        if mset.cfg.Sealed {
303✔
2233
                mset.mu.RUnlock()
×
2234
                return 0, errors.New("sealed stream")
×
2235
        }
×
2236
        store, mlseq := mset.store, mset.lseq
303✔
2237
        mset.mu.RUnlock()
303✔
2238

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

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

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

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

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

2270
        mset.clsMu.RLock()
303✔
2271
        for _, o := range mset.cList {
369✔
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 than 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()
303✔
2294

303✔
2295
        return purged, nil
303✔
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) {
68,822✔
2301
        return mset.deleteMsg(seq)
68,822✔
2302
}
68,822✔
2303

2304
// DeleteMsg will remove a message from a stream.
2305
func (mset *stream) deleteMsg(seq uint64) (bool, error) {
68,840✔
2306
        if mset.closed.Load() {
68,840✔
2307
                return false, errStreamClosed
×
2308
        }
×
2309
        removed, err := mset.store.RemoveMsg(seq)
68,840✔
2310
        if err != nil {
72,049✔
2311
                return removed, err
3,209✔
2312
        }
3,209✔
2313
        mset.mu.Lock()
65,631✔
2314
        mset.clearAllPreAcks(seq)
65,631✔
2315
        mset.mu.Unlock()
65,631✔
2316
        return removed, err
65,631✔
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 {
10✔
2336
        mset.mu.RLock()
10✔
2337
        defer mset.mu.RUnlock()
10✔
2338
        return mset.cfg.Mirror != nil
10✔
2339
}
10✔
2340

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

2350
// Lock should be held
2351
func (mset *stream) sourceInfo(si *sourceInfo) *StreamSourceInfo {
18,705✔
2352
        if si == nil {
36,156✔
2353
                return nil
17,451✔
2354
        }
17,451✔
2355

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

1,254✔
2358
        trConfigs := make([]SubjectTransformConfig, len(si.sfs))
1,254✔
2359
        for i := range si.sfs {
1,317✔
2360
                destination := _EMPTY_
63✔
2361
                if si.trs[i] != nil {
102✔
2362
                        destination = si.trs[i].dest
39✔
2363
                }
39✔
2364
                trConfigs[i] = SubjectTransformConfig{si.sfs[i], destination}
63✔
2365
        }
2366

2367
        ssi.SubjectTransforms = trConfigs
1,254✔
2368

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

2376
        var ext *ExternalStream
1,254✔
2377
        if mset.cfg.Mirror != nil {
2,027✔
2378
                ext = mset.cfg.Mirror.External
773✔
2379
        } else if ss := mset.streamSource(si.iname); ss != nil && ss.External != nil {
1,305✔
2380
                ext = ss.External
51✔
2381
        }
51✔
2382
        if ext != nil {
1,388✔
2383
                ssi.External = &ExternalStream{
134✔
2384
                        ApiPrefix:     ext.ApiPrefix,
134✔
2385
                        DeliverPrefix: ext.DeliverPrefix,
134✔
2386
                }
134✔
2387
        }
134✔
2388
        return &ssi
1,254✔
2389
}
2390

2391
// Return our source info for our mirror.
2392
func (mset *stream) mirrorInfo() *StreamSourceInfo {
18,224✔
2393
        mset.mu.RLock()
18,224✔
2394
        defer mset.mu.RUnlock()
18,224✔
2395
        return mset.sourceInfo(mset.mirror)
18,224✔
2396
}
18,224✔
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,512✔
2435
                select {
1,463✔
2436
                case <-s.quitCh:
×
2437
                        return
×
2438
                case <-qch:
×
2439
                        return
×
2440
                case <-siqch:
49✔
2441
                        return
49✔
2442
                case <-msgs.ch:
1,410✔
2443
                        ims := msgs.pop()
1,410✔
2444
                        for _, im := range ims {
7,512✔
2445
                                if !mset.processInboundMirrorMsg(im) {
6,102✔
2446
                                        break
×
2447
                                }
2448
                                im.returnToPool()
6,102✔
2449
                        }
2450
                        msgs.recycle(&ims)
1,410✔
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 {
12,349✔
2477
        return si.cname != _EMPTY_ && strings.HasPrefix(reply, jsAckPre) && si.cname == tokenAt(reply, 4)
12,349✔
2478
}
12,349✔
2479

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

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

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

2502
        // Check for heartbeats and flow control messages.
2503
        if isControl {
6,123✔
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,081✔
2525

6,081✔
2526
        if dc > 1 {
6,081✔
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,081✔
2533
        if sseq == mset.mirror.sseq+1 {
12,056✔
2534
                mset.mirror.dseq = dseq
5,975✔
2535
                mset.mirror.sseq++
5,975✔
2536
        } else if sseq <= mset.mirror.sseq {
6,081✔
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 {
7,398✔
2557
                mset.mirror.lag = 0
1,317✔
2558
        } else {
6,081✔
2559
                mset.mirror.lag = pending - 1
4,764✔
2560
        }
4,764✔
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,085✔
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 {
6,335✔
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,081✔
2587
        node := mset.node
6,081✔
2588
        mset.mu.Unlock()
6,081✔
2589

6,081✔
2590
        var err error
6,081✔
2591
        if node != nil {
7,197✔
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 {
4,965✔
2599
                err = mset.processJetStreamMsg(m.subj, _EMPTY_, m.hdr, m.msg, sseq-1, ts, nil, true)
4,965✔
2600
        }
4,965✔
2601
        if err != nil {
6,081✔
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,081✔
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 {
70✔
2702
        backoff := time.Duration(retryBackOff) * time.Duration(fails*2)
70✔
2703
        if backoff > retryMaximum {
70✔
2704
                backoff = retryMaximum
×
2705
        }
×
2706
        return backoff
70✔
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() {
63✔
2717
        // We are trying to figure out how soon we can retry. setupMirrorConsumer will reject
63✔
2718
        // a retry if last was done less than "sourceConsumerRetryThreshold" ago.
63✔
2719
        next := sourceConsumerRetryThreshold - time.Since(mset.mirror.lreq)
63✔
2720
        if next < 0 {
126✔
2721
                // It means that we have passed the threshold and so we are ready to go.
63✔
2722
                next = 0
63✔
2723
        }
63✔
2724
        // Take into account failures here.
2725
        next += calculateRetryBackoff(mset.mirror.fails)
63✔
2726

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

63✔
2730
        time.AfterFunc(next, func() {
126✔
2731
                mset.mu.Lock()
63✔
2732
                mset.setupMirrorConsumer()
63✔
2733
                mset.mu.Unlock()
63✔
2734
        })
63✔
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 {
65✔
2743
        if mset.closed.Load() {
79✔
2744
                return errStreamClosed
14✔
2745
        }
14✔
2746
        if mset.outq == nil {
51✔
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 {
51✔
2757
                return errors.New("invalid mirror configuration")
×
2758
        }
×
2759

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

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

2773
        mirror := mset.mirror
50✔
2774

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

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

50✔
2787
        if ext != nil && ext.DeliverPrefix != _EMPTY_ {
58✔
2788
                deliverSubject = strings.ReplaceAll(ext.DeliverPrefix+syncSubject(".M"), "..", ".")
8✔
2789
        } else {
50✔
2790
                deliverSubject = syncSubject("$JS.M")
42✔
2791
        }
42✔
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
50✔
2797
        mset.store.FastState(&state)
50✔
2798

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

50✔
2815
        // Only use start optionals on first time.
50✔
2816
        if state.Msgs == 0 && state.FirstSeq == 0 {
89✔
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 {
84✔
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_ {
55✔
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 {
56✔
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)
50✔
2862
        reply := infoReplySubject()
50✔
2863
        crSub, err := mset.subscribeInternal(reply, func(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
99✔
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 {
50✔
2879
                mirror.err = NewJSMirrorConsumerSetupFailedError(err, Unless(err))
×
2880
                mset.scheduleSetupMirrorConsumerRetry()
×
2881
                return nil
×
2882
        }
×
2883

2884
        var subject string
50✔
2885
        if req.Config.FilterSubject != _EMPTY_ {
60✔
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 {
50✔
2889
                subject = fmt.Sprintf(JSApiConsumerCreateT, mset.cfg.Mirror.Name)
40✔
2890
        }
40✔
2891
        if ext != nil {
63✔
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)
50✔
2898

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

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

50✔
2907
        go func() {
100✔
2908

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

50✔
2933
                select {
50✔
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) {
6,151✔
2958
                                        hdr, msg := c.msgParts(copyBytes(rmsg)) // Need to copy.
6,102✔
2959
                                        mset.queueInbound(msgs, subject, reply, hdr, msg, nil, nil)
6,102✔
2960
                                        mirror.last.Store(time.Now().UnixNano())
6,102✔
2961
                                })
6,102✔
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):
1✔
3010
                        mset.unsubscribe(crSub)
1✔
3011
                        // We already waited 30 seconds, let's retry now.
1✔
3012
                        retry = true
1✔
3013
                }
3014
        }()
3015

3016
        return nil
50✔
3017
}
3018

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

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

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

100✔
3034
        // setupSourceConsumer will check that the source is still configured.
100✔
3035
        mset.setupSourceConsumer(iName, seq, time.Time{})
100✔
3036
}
100✔
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) {
648✔
3053
        if si.sub != nil {
789✔
3054
                mset.unsubscribe(si.sub)
141✔
3055
                si.sub = nil
141✔
3056
        }
141✔
3057
        // In case we had a mirror direct subscription.
3058
        if si.dsub != nil {
652✔
3059
                mset.unsubscribe(si.dsub)
4✔
3060
                si.dsub = nil
4✔
3061
        }
4✔
3062
        mset.removeInternalConsumer(si)
648✔
3063
        if si.qch != nil {
789✔
3064
                close(si.qch)
141✔
3065
                si.qch = nil
141✔
3066
        }
141✔
3067
        if si.msgs != nil {
699✔
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 {
671✔
3073
                t.Stop()
23✔
3074
                delete(mset.sourceSetupSchedules, si.iname)
23✔
3075
        }
23✔
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) {
208✔
3085
        if mset.sourceSetupSchedules == nil {
272✔
3086
                mset.sourceSetupSchedules = map[string]*time.Timer{}
64✔
3087
        }
64✔
3088

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

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

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

122✔
3102
        if !si.lreq.IsZero() { // it's not the very first time we are called, compute the delay
144✔
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 {
39✔
3105
                        scheduleDelay = sourceConsumerRetryThreshold - sinceLast
17✔
3106
                }
17✔
3107
                // Is it a retry? If so, add a backoff
3108
                if si.fails > 0 {
29✔
3109
                        scheduleDelay += calculateRetryBackoff(si.fails)
7✔
3110
                }
7✔
3111
        }
3112

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

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

99✔
3121
                delete(mset.sourceSetupSchedules, iname)
99✔
3122
                mset.trySetupSourceConsumer(iname, seq, startTime)
99✔
3123
        })
99✔
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) {
99✔
3129
        // Ignore if closed or not leader.
99✔
3130
        if mset.closed.Load() || !mset.isLeader() {
99✔
3131
                return
×
3132
        }
×
3133

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

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

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

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

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

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

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

99✔
3173
        // If starting, check any configs.
99✔
3174
        if !startTime.IsZero() && seq > 1 {
99✔
3175
                req.Config.OptStartTime = &startTime
×
3176
                req.Config.DeliverPolicy = DeliverByStartTime
×
3177
        } else if seq <= 1 {
174✔
3178
                if ssi.OptStartSeq > 0 {
78✔
3179
                        req.Config.OptStartSeq = ssi.OptStartSeq
3✔
3180
                        req.Config.DeliverPolicy = DeliverByStartSequence
3✔
3181
                } else {
75✔
3182
                        // We have not recovered state so check that configured time is less that our first seq time.
72✔
3183
                        var state StreamState
72✔
3184
                        mset.store.FastState(&state)
72✔
3185
                        if ssi.OptStartTime != nil {
76✔
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() {
71✔
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_ {
112✔
3204
                req.Config.FilterSubject = ssi.FilterSubject
13✔
3205
        }
13✔
3206

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

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

3234
        var subject string
99✔
3235
        if req.Config.FilterSubject != _EMPTY_ {
112✔
3236
                req.Config.Name = fmt.Sprintf("src-%s", createConsumerName())
13✔
3237
                subject = fmt.Sprintf(JSApiConsumerCreateExT, si.name, req.Config.Name, req.Config.FilterSubject)
13✔
3238
        } else if len(req.Config.FilterSubjects) == 1 {
102✔
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 {
86✔
3246
                subject = fmt.Sprintf(JSApiConsumerCreateT, si.name)
83✔
3247
        }
83✔
3248
        if ext != nil {
109✔
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)
99✔
3255

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

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

99✔
3264
        go func() {
198✔
3265

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

3286
                select {
99✔
3287
                case ccr := <-respCh:
96✔
3288
                        mset.mu.Lock()
96✔
3289
                        // Check that it has not been removed or canceled (si.sub would be nil)
96✔
3290
                        if si := mset.sources[iname]; si != nil {
192✔
3291
                                si.err = nil
96✔
3292
                                if ccr.Error != nil || ccr.ConsumerInfo == nil {
100✔
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 {
96✔
3303
                                        // Check if our shared msg queue and go routine is running or not.
92✔
3304
                                        if mset.smsgs == nil {
141✔
3305
                                                qname := fmt.Sprintf("[ACC:%s] stream sources '%s' msgs", mset.acc.Name, mset.cfg.Name)
49✔
3306
                                                mset.smsgs = newIPQueue[*inMsg](mset.srv, qname)
49✔
3307
                                                mset.srv.startGoRoutine(func() { mset.processAllSourceMsgs() },
98✔
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 {
111✔
3318
                                                si.sseq = ccr.ConsumerInfo.Delivered.Stream + 1
19✔
3319
                                        }
19✔
3320
                                        // Capture consumer name.
3321
                                        si.cname = ccr.ConsumerInfo.Name
92✔
3322

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

92✔
3329
                                        msgs := mset.smsgs
92✔
3330
                                        sub, err := mset.subscribeInternal(deliverSubject, func(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
8,344✔
3331
                                                hdr, msg := c.msgParts(copyBytes(rmsg)) // Need to copy.
8,252✔
3332
                                                mset.queueInbound(msgs, subject, reply, hdr, msg, si, nil)
8,252✔
3333
                                                si.last.Store(time.Now().UnixNano())
8,252✔
3334
                                        })
8,252✔
3335
                                        if err != nil {
92✔
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
92✔
3343
                                }
3344
                        }
3345
                        mset.mu.Unlock()
92✔
3346
                case <-time.After(srcConsumerWaitTime):
3✔
3347
                        mset.unsubscribe(crSub)
3✔
3348
                        // We already waited 30 seconds, let's retry now.
3✔
3349
                        retry = true
3✔
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() {
49✔
3358
        s := mset.srv
49✔
3359
        defer s.grWG.Done()
49✔
3360

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

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

49✔
3368
        // When we detect we are no longer leader, we will cleanup.
49✔
3369
        // Should always return right after this is called.
49✔
3370
        cleanUp := func() {
49✔
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 {
990✔
3382
                select {
941✔
3383
                case <-s.quitCh:
×
3384
                        return
×
3385
                case <-qch:
49✔
3386
                        return
49✔
3387
                case <-msgs.ch:
887✔
3388
                        ims := msgs.pop()
887✔
3389
                        for _, im := range ims {
7,134✔
3390
                                if !mset.processInboundSourceMsg(im.si, im) {
6,347✔
3391
                                        // If we are no longer leader bail.
100✔
3392
                                        if !mset.IsLeader() {
100✔
3393
                                                msgs.recycle(&ims)
×
3394
                                                cleanUp()
×
3395
                                                return
×
3396
                                        }
×
3397
                                        break
100✔
3398
                                }
3399
                                im.returnToPool()
6,147✔
3400
                        }
3401
                        msgs.recycle(&ims)
887✔
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 {
12,349✔
3443
        return len(m.msg) == 0 && len(m.hdr) > 0 && bytes.HasPrefix(m.hdr, []byte("NATS/1.0 100 "))
12,349✔
3444
}
12,349✔
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,247✔
3468
        mset.mu.Lock()
6,247✔
3469
        // If we are no longer the leader cancel this subscriber.
6,247✔
3470
        if !mset.isLeader() {
6,247✔
3471
                mset.cancelSourceConsumer(si.iname)
×
3472
                mset.mu.Unlock()
×
3473
                return false
×
3474
        }
×
3475

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

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

3484
        // Check for heartbeats and flow control messages.
3485
        if isControl {
6,394✔
3486
                var needsRetry bool
147✔
3487
                // Flow controls have reply subjects.
147✔
3488
                if m.rply != _EMPTY_ {
147✔
3489
                        mset.handleFlowControl(m)
×
3490
                } else {
147✔
3491
                        // For idle heartbeats make sure we did not miss anything.
147✔
3492
                        if ldseq := parseInt64(getHeader(JSLastConsumerSeq, m.hdr)); ldseq > 0 && uint64(ldseq) != si.dseq {
173✔
3493
                                needsRetry = true
26✔
3494
                                mset.retrySourceConsumerAtSeq(si.iname, si.sseq+1)
26✔
3495
                        } else if fcReply := getHeader(JSConsumerStalled, m.hdr); len(fcReply) > 0 {
147✔
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()
147✔
3501
                return !needsRetry
147✔
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,139✔
3513
                si.dseq++
6,039✔
3514
                si.sseq = sseq
6,039✔
3515
        } else if dseq > si.dseq {
6,161✔
3516
                if si.cname == _EMPTY_ {
61✔
3517
                        si.cname = tokenAt(m.rply, 4)
×
3518
                        si.dseq, si.sseq = dseq, sseq
×
3519
                } else {
61✔
3520
                        mset.retrySourceConsumerAtSeq(si.iname, si.sseq+1)
61✔
3521
                        mset.mu.Unlock()
61✔
3522
                        return false
61✔
3523
                }
61✔
3524
        } else {
×
3525
                mset.mu.Unlock()
×
3526
                return false
×
3527
        }
×
3528

3529
        if pending == 0 {
6,723✔
3530
                si.lag = 0
684✔
3531
        } else {
6,039✔
3532
                si.lag = pending - 1
5,355✔
3533
        }
5,355✔
3534
        node := mset.node
6,039✔
3535
        mset.mu.Unlock()
6,039✔
3536

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

6,039✔
3539
        // If we are daisy chained here make sure to remove the original one.
6,039✔
3540
        if len(hdr) > 0 {
6,047✔
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,039✔
3547

6,039✔
3548
        // Do the subject transform for the source if there's one
6,039✔
3549
        if len(si.trs) > 0 {
6,119✔
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,039✔
3564
        // If we are clustered we need to propose this message to the underlying raft group.
6,039✔
3565
        if node != nil {
8,266✔
3566
                err = mset.processClusteredInboundMsg(m.subj, _EMPTY_, hdr, msg, nil, true)
2,227✔
3567
        } else {
6,039✔
3568
                err = mset.processJetStreamMsg(m.subj, _EMPTY_, hdr, msg, 0, 0, nil, true)
3,812✔
3569
        }
3,812✔
3570

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

13✔
3581
                        // Can happen temporarily all the time during normal operations when the sourcing stream
13✔
3582
                        // is working queue/interest with a limit and discard new.
13✔
3583
                        // TODO - Improve sourcing to WQ with limit and new to use flow control rather than re-creating the consumer.
13✔
3584
                        if errors.Is(err, ErrMaxMsgs) || errors.Is(err, ErrMaxBytes) {
26✔
3585
                                // Do not need to do a full retry that includes finding the last sequence in the stream
13✔
3586
                                // for that source. Just re-create starting with the seq we couldn't store instead.
13✔
3587
                                mset.mu.Lock()
13✔
3588
                                mset.retrySourceConsumerAtSeq(iName, si.sseq)
13✔
3589
                                mset.mu.Unlock()
13✔
3590
                        } else {
13✔
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
13✔
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,039✔
3616
        var b strings.Builder
6,039✔
3617
        iNameParts := strings.Split(si.iname, " ")
6,039✔
3618

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

6,039✔
3636
        b.WriteByte(' ')
6,039✔
3637
        b.WriteString(iNameParts[1])
6,039✔
3638
        b.WriteByte(' ')
6,039✔
3639
        b.WriteString(iNameParts[2])
6,039✔
3640
        return b.String()
6,039✔
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) {
463✔
3662
        if strings.HasPrefix(shdr, jsAckPre) {
463✔
3663
                return streamAndSeqFromAckReply(shdr)
×
3664
        }
×
3665
        // New version which is stream index name <SPC> sequence
3666
        fields := strings.Split(shdr, " ")
463✔
3667
        nFields := len(fields)
463✔
3668

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

3673
        if nFields >= 4 {
925✔
3674
                return fields[0], strings.Join([]string{fields[0], fields[2], fields[3]}, " "), uint64(parseAckReplyNum(fields[1]))
462✔
3675
        } else {
463✔
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{}) {
14✔
3683
        var state StreamState
14✔
3684
        mset.store.FastState(&state)
14✔
3685

14✔
3686
        // Do not reset sseq here so we can remember when purge/expiration happens.
14✔
3687
        if state.Msgs == 0 {
21✔
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
7✔
3700
        for seq := state.LastSeq; seq >= state.FirstSeq; {
362✔
3701
                sm, err := mset.store.LoadPrevMsg(seq, &smv)
355✔
3702
                if err == ErrStoreEOF || err != nil {
355✔
3703
                        break
×
3704
                }
3705
                seq = sm.seq - 1
355✔
3706
                if len(sm.hdr) == 0 {
355✔
3707
                        continue
×
3708
                }
3709

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

355✔
3716
                if _, ok := iNames[indexName]; ok {
357✔
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_ {
356✔
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 {
360✔
3734
                        break
5✔
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 {
326✔
3747
                if ssi.iname == _EMPTY_ {
307✔
3748
                        ssi.setIndexName()
105✔
3749
                }
105✔
3750

3751
                var si *sourceInfo
202✔
3752

202✔
3753
                if len(ssi.SubjectTransforms) == 0 {
394✔
3754
                        si = &sourceInfo{name: ssi.Name, iname: ssi.iname, sf: ssi.FilterSubject}
192✔
3755
                } else {
202✔
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
202✔
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 {
59✔
3853
        if mset.outq == nil {
59✔
3854
                return errors.New("outq required")
×
3855
        }
×
3856
        // Reset if needed.
3857
        for _, si := range mset.sources {
147✔
3858
                if si.sub != nil {
88✔
3859
                        mset.cancelSourceConsumer(si.iname)
×
3860
                }
×
3861
        }
3862

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

3868
        mset.startingSequenceForSources()
58✔
3869

58✔
3870
        // Setup our consumers at the proper starting position.
58✔
3871
        for _, ssi := range mset.cfg.Sources {
145✔
3872
                if si := mset.sources[ssi.iname]; si != nil {
174✔
3873
                        mset.setupSourceConsumer(ssi.iname, si.sseq+1, time.Time{})
87✔
3874
                }
87✔
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,887✔
3883
        if mset.active {
3,921✔
3884
                return nil
34✔
3885
        }
34✔
3886
        for _, subject := range mset.cfg.Subjects {
7,889✔
3887
                if _, err := mset.subscribeInternal(subject, mset.processInboundJetStreamMsg); err != nil {
4,036✔
3888
                        return err
×
3889
                }
×
3890
        }
3891
        // Check if we need to setup mirroring.
3892
        if mset.cfg.Mirror != nil {
3,915✔
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,857✔
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() {
53✔
3921
                                mset.mu.Lock()
23✔
3922
                                mset.setupSourceConsumers()
23✔
3923
                                mset.mu.Unlock()
23✔
3924
                        })
23✔
3925
                }
3926
        }
3927
        // Check for direct get access.
3928
        // We spin up followers for clustered streams in monitorStream().
3929
        if mset.cfg.AllowDirect {
3,903✔
3930
                if err := mset.subscribeToDirect(); err != nil {
50✔
3931
                        return err
×
3932
                }
×
3933
        }
3934

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

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

3961
        return nil
60✔
3962
}
3963

3964
// Lock should be held.
3965
func (mset *stream) unsubscribeToDirect() {
5,479✔
3966
        if mset.directSub != nil {
5,539✔
3967
                mset.unsubscribe(mset.directSub)
60✔
3968
                mset.directSub = nil
60✔
3969
        }
60✔
3970
        if mset.lastBySub != nil {
5,539✔
3971
                mset.unsubscribe(mset.lastBySub)
60✔
3972
                mset.lastBySub = nil
60✔
3973
        }
60✔
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() {
5,041✔
4009
        for _, si := range mset.sources {
5,350✔
4010
                mset.cancelSourceInfo(si)
309✔
4011
        }
309✔
4012
}
4013

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

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

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

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

4042
        mset.active = false
10,322✔
4043
        return nil
10,322✔
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,354✔
4048
        if mset.closed.Load() {
4,354✔
4049
                return nil, errStreamClosed
×
4050
        }
×
4051
        if cb == nil {
4,354✔
4052
                return nil, errInvalidMsgHandler
×
4053
        }
×
4054
        c := mset.client
4,354✔
4055
        sid := int(mset.sid.Add(1))
4,354✔
4056
        // Now create the subscription
4,354✔
4057
        return c.processSub([]byte(subject), nil, []byte(strconv.Itoa(sid)), cb, false)
4,354✔
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) {
128✔
4062
        if mset.closed.Load() {
128✔
4063
                return nil, errStreamClosed
×
4064
        }
×
4065
        if cb == nil {
128✔
4066
                return nil, errInvalidMsgHandler
×
4067
        }
×
4068
        c := mset.client
128✔
4069
        sid := int(mset.sid.Add(1))
128✔
4070
        // Now create the subscription
128✔
4071
        return c.processSub([]byte(subject), []byte(group), []byte(strconv.Itoa(sid)), cb, false)
128✔
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,745✔
4079
        if mset.closed.Load() {
16,548✔
4080
                return errStreamClosed
5,803✔
4081
        }
5,803✔
4082
        c := mset.client
4,942✔
4083
        var sid []byte
4,942✔
4084
        c.mu.Lock()
4,942✔
4085
        for _, sub := range c.subs {
6,361✔
4086
                if subject == string(sub.subject) {
2,793✔
4087
                        sid = sub.sid
1,374✔
4088
                        break
1,374✔
4089
                }
4090
        }
4091
        c.mu.Unlock()
4,942✔
4092

4,942✔
4093
        if sid != nil {
6,316✔
4094
                return c.processUnsub(sid)
1,374✔
4095
        }
1,374✔
4096
        return nil
3,568✔
4097
}
4098

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

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

5,463✔
4111
        switch mset.cfg.Storage {
5,463✔
4112
        case MemoryStorage:
330✔
4113
                ms, err := newMemStore(&mset.cfg)
330✔
4114
                if err != nil {
330✔
4115
                        mset.mu.Unlock()
×
4116
                        return err
×
4117
                }
×
4118
                mset.store = ms
330✔
4119
        case FileStorage:
5,133✔
4120
                s := mset.srv
5,133✔
4121
                prf := s.jsKeyGen(s.getOpts().JetStreamKey, mset.acc.Name)
5,133✔
4122
                if prf != nil {
5,201✔
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,133✔
4127
                cfg := *fsCfg
5,133✔
4128
                cfg.srv = s
5,133✔
4129
                fs, err := newFileStoreWithCreated(cfg, mset.cfg, mset.created, prf, oldprf)
5,133✔
4130
                if err != nil {
5,134✔
4131
                        mset.mu.Unlock()
1✔
4132
                        return err
1✔
4133
                }
1✔
4134
                mset.store = fs
5,132✔
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,462✔
4138
        mset.store.RegisterStorageRemoveMsg(func(seq uint64) {
5,559✔
4139
                if mset.IsClustered() {
185✔
4140
                        if mset.IsLeader() {
118✔
4141
                                mset.mu.RLock()
30✔
4142
                                md := streamMsgDelete{Seq: seq, NoErase: true, Stream: mset.cfg.Name}
30✔
4143
                                mset.node.Propose(encodeMsgDelete(&md))
30✔
4144
                                mset.mu.RUnlock()
30✔
4145
                        }
30✔
4146
                } else {
9✔
4147
                        mset.removeMsg(seq)
9✔
4148
                }
9✔
4149
        })
4150
        mset.store.RegisterSubjectDeleteMarkerUpdates(func(im *inMsg) {
5,587✔
4151
                if mset.IsClustered() {
235✔
4152
                        if mset.IsLeader() {
148✔
4153
                                mset.processClusteredInboundMsg(im.subj, im.rply, im.hdr, im.msg, im.mt, false)
38✔
4154
                        }
38✔
4155
                } else {
15✔
4156
                        mset.processJetStreamMsg(im.subj, im.rply, im.hdr, im.msg, 0, 0, im.mt, false)
15✔
4157
                }
15✔
4158
        })
4159
        mset.mu.Unlock()
5,462✔
4160

5,462✔
4161
        return nil
5,462✔
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,814,656✔
4169
        // If we have a single negative update then we will process our consumers for stream pending.
1,814,656✔
4170
        // Purge and Store handled separately inside individual calls.
1,814,656✔
4171
        if md == -1 && seq > 0 && subj != _EMPTY_ {
1,997,309✔
4172
                // We use our consumer list mutex here instead of the main stream lock since it may be held already.
182,653✔
4173
                mset.clsMu.RLock()
182,653✔
4174
                if mset.csl != nil {
277,815✔
4175
                        mset.csl.Match(subj, func(o *consumer) {
200,828✔
4176
                                o.decStreamPending(seq, subj)
105,666✔
4177
                        })
105,666✔
4178
                } else {
87,491✔
4179
                        for _, o := range mset.cList {
87,491✔
4180
                                o.decStreamPending(seq, subj)
×
4181
                        }
×
4182
                }
4183
                mset.clsMu.RUnlock()
182,653✔
4184
        } else if md < 0 {
1,632,701✔
4185
                // Batch decrements we need to force consumers to re-calculate num pending.
698✔
4186
                mset.clsMu.RLock()
698✔
4187
                for _, o := range mset.cList {
740✔
4188
                        o.streamNumPendingLocked()
42✔
4189
                }
42✔
4190
                mset.clsMu.RUnlock()
698✔
4191
        }
4192

4193
        if mset.jsa != nil {
3,629,312✔
4194
                mset.jsa.updateUsage(mset.tier, mset.stype, bd)
1,814,656✔
4195
        }
1,814,656✔
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 {
232,184✔
4211
        if !mset.ddloaded {
232,186✔
4212
                mset.rebuildDedupe()
2✔
4213
        }
2✔
4214
        if id == _EMPTY_ || len(mset.ddmap) == 0 {
232,211✔
4215
                return nil
27✔
4216
        }
27✔
4217
        return mset.ddmap[id]
232,157✔
4218
}
4219

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

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

4✔
4230
        for i, dde := range mset.ddarr[mset.ddindex:] {
15✔
4231
                if now-dde.ts >= window {
20✔
4232
                        delete(mset.ddmap, dde.id)
9✔
4233
                } else {
11✔
4234
                        mset.ddindex += i
2✔
4235
                        // Check if we should garbage collect here if we are 1/3 total size.
2✔
4236
                        if cap(mset.ddarr) > 3*(len(mset.ddarr)-mset.ddindex) {
2✔
4237
                                mset.ddarr = append([]*ddentry(nil), mset.ddarr[mset.ddindex:]...)
×
4238
                                mset.ddindex = 0
×
4239
                        }
×
4240
                        tmrNext = time.Duration(window - (now - dde.ts))
2✔
4241
                        break
2✔
4242
                }
4243
        }
4244
        if len(mset.ddmap) > 0 {
6✔
4245
                // Make sure to not fire too quick
2✔
4246
                const minFire = 50 * time.Millisecond
2✔
4247
                if tmrNext < minFire {
3✔
4248
                        tmrNext = minFire
1✔
4249
                }
1✔
4250
                if mset.ddtmr != nil {
4✔
4251
                        mset.ddtmr.Reset(tmrNext)
2✔
4252
                } else {
2✔
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) {
937,530✔
4269
        if mset.ddmap == nil {
937,593✔
4270
                mset.ddmap = make(map[string]*ddentry)
63✔
4271
        }
63✔
4272
        mset.ddmap[dde.id] = dde
937,530✔
4273
        mset.ddarr = append(mset.ddarr, dde)
937,530✔
4274
        if mset.ddtmr == nil {
937,593✔
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,203,035✔
4281
        return string(getHeader(JSMsgId, hdr))
1,203,035✔
4282
}
1,203,035✔
4283

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

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

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

4303
// Fast lookup of rollups.
4304
func getRollup(hdr []byte) string {
531,954✔
4305
        r := getHeader(JSMsgRollup, hdr)
531,954✔
4306
        if len(r) == 0 {
1,063,749✔
4307
                return _EMPTY_
531,795✔
4308
        }
531,795✔
4309
        return strings.ToLower(string(r))
159✔
4310
}
4311

4312
// Fast lookup of expected stream sequence per subject.
4313
func getExpectedLastSeqPerSubject(hdr []byte) (uint64, bool) {
744,567✔
4314
        bseq := getHeader(JSExpectedLastSubjSeq, hdr)
744,567✔
4315
        if len(bseq) == 0 {
1,488,486✔
4316
                return 0, false
743,919✔
4317
        }
743,919✔
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,394,992✔
4331
        ttl := getHeader(JSMessageTTL, hdr)
2,394,992✔
4332
        if len(ttl) == 0 {
4,749,053✔
4333
                return 0, nil
2,354,061✔
4334
        }
2,354,061✔
4335
        return parseMessageTTL(bytesToString(ttl))
40,931✔
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) {
40,931✔
4342
        if strings.ToLower(ttl) == "never" {
40,962✔
4343
                return -1, nil
31✔
4344
        }
31✔
4345
        dur, err := time.ParseDuration(ttl)
40,900✔
4346
        if err == nil {
81,785✔
4347
                if dur < time.Second {
40,890✔
4348
                        return 0, NewJSMessageTTLInvalidError()
5✔
4349
                }
5✔
4350
                return int64(dur.Seconds()), nil
40,880✔
4351
        }
4352
        t := parseInt64(stringToBytes(ttl))
15✔
4353
        if t < 0 {
20✔
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
10✔
4361
}
4362

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

4370
// Lock should be held.
4371
func (mset *stream) isClustered() bool {
3,974,137✔
4372
        return mset.node != nil
3,974,137✔
4373
}
3,974,137✔
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 {
35,674✔
4387
                return &inMsg{}
35,674✔
4388
        },
35,674✔
4389
}
4390

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

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

4410
var dgPool = sync.Pool{
4411
        New: func() any {
8✔
4412
                return &directGetReq{}
8✔
4413
        },
8✔
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) {
60✔
4425
        if len(reply) == 0 {
60✔
4426
                return
×
4427
        }
×
4428
        _, msg := c.msgParts(rmsg)
60✔
4429
        if len(msg) == 0 {
61✔
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
59✔
4435
        err := json.Unmarshal(msg, &req)
59✔
4436
        if err != nil {
59✔
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 {
60✔
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_) ||
58✔
4450
                (req.Seq > 0 && req.StartTime != nil) ||
58✔
4451
                (req.StartTime != nil && req.LastFor != _EMPTY_) ||
58✔
4452
                (req.LastFor != _EMPTY_ && req.NextFor != _EMPTY_) ||
58✔
4453
                (req.LastFor != _EMPTY_ && req.Batch > 0) ||
58✔
4454
                (req.LastFor != _EMPTY_ && len(req.MultiLastFor) > 0) ||
58✔
4455
                (req.NextFor != _EMPTY_ && len(req.MultiLastFor) > 0) ||
58✔
4456
                (req.UpToSeq > 0 && req.UpToTime != nil) {
62✔
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
54✔
4463
        if !inlineOk {
56✔
4464
                dg := dgPool.Get().(*directGetReq)
2✔
4465
                dg.req, dg.reply = req, reply
2✔
4466
                mset.gets.push(dg)
2✔
4467
        } else {
54✔
4468
                mset.getDirectRequest(&req, reply)
52✔
4469
        }
52✔
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) {
13,053✔
4474
        if len(reply) == 0 {
13,053✔
4475
                return
×
4476
        }
×
4477
        _, msg := c.msgParts(rmsg)
13,053✔
4478
        // This version expects no payload.
13,053✔
4479
        if len(msg) != 0 {
13,053✔
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
13,053✔
4486
        for i, n := 0, 0; i < len(subject); i++ {
365,479✔
4487
                if subject[i] == btsep {
417,691✔
4488
                        if n == 4 {
78,318✔
4489
                                if start := i + 1; start < len(subject) {
26,106✔
4490
                                        key = subject[i+1:]
13,053✔
4491
                                }
13,053✔
4492
                                break
13,053✔
4493
                        }
4494
                        n++
52,212✔
4495
                }
4496
        }
4497
        if len(key) == 0 {
13,053✔
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}
13,053✔
4504

13,053✔
4505
        inlineOk := c.kind != ROUTER && c.kind != GATEWAY && c.kind != LEAF
13,053✔
4506
        if !inlineOk {
23,979✔
4507
                dg := dgPool.Get().(*directGetReq)
10,926✔
4508
                dg.req, dg.reply = req, reply
10,926✔
4509
                mset.gets.push(dg)
10,926✔
4510
        } else {
13,053✔
4511
                mset.getDirectRequest(&req, reply)
2,127✔
4512
        }
2,127✔
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) {
23✔
4525
        // TODO(dlc) - Make configurable?
23✔
4526
        const maxAllowedResponses = 1024
23✔
4527

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

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

4541
        upToSeq := req.UpToSeq
23✔
4542
        // If we have UpToTime set get the proper sequence.
23✔
4543
        if req.UpToTime != nil {
30✔
4544
                upToSeq = store.GetSeqFromTime((*req.UpToTime).UTC())
7✔
4545
                // Avoid selecting a first sequence that will take us to before the stream first
7✔
4546
                // sequence, otherwise we can return messages after the supplied UpToTime.
7✔
4547
                if upToSeq <= mset.state().FirstSeq {
9✔
4548
                        hdr := []byte("NATS/1.0 404 No Results\r\n\r\n")
2✔
4549
                        mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
2✔
4550
                        return
2✔
4551
                }
2✔
4552
                // We need to back off one since this is used to determine start sequence normally,
4553
                // whereas here we want it to be the ceiling.
4554
                upToSeq--
5✔
4555
        }
4556
        // If not set, set to the last sequence and remember that for EOB.
4557
        if upToSeq == 0 {
35✔
4558
                var state StreamState
14✔
4559
                mset.store.FastState(&state)
14✔
4560
                upToSeq = state.LastSeq
14✔
4561
        }
14✔
4562

4563
        seqs, err := store.MultiLastSeqs(req.MultiLastFor, upToSeq, maxAllowedResponses)
21✔
4564
        if err != nil {
22✔
4565
                var hdr []byte
1✔
4566
                if err == ErrTooManyResults {
2✔
4567
                        hdr = []byte("NATS/1.0 413 Too Many Results\r\n\r\n")
1✔
4568
                } else {
1✔
4569
                        hdr = []byte(fmt.Sprintf("NATS/1.0 500 %v\r\n\r\n", err))
×
4570
                }
×
4571
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
1✔
4572
                return
1✔
4573
        }
4574
        if len(seqs) == 0 {
22✔
4575
                hdr := []byte("NATS/1.0 404 No Results\r\n\r\n")
2✔
4576
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
2✔
4577
                return
2✔
4578
        }
2✔
4579

4580
        np, lseq, sentBytes, sent := uint64(len(seqs)-1), uint64(0), 0, 0
18✔
4581
        for _, seq := range seqs {
2,809✔
4582
                if seq < req.Seq {
4,559✔
4583
                        if np > 0 {
3,536✔
4584
                                np--
1,768✔
4585
                        }
1,768✔
4586
                        continue
1,768✔
4587
                }
4588
                var svp StoreMsg
1,023✔
4589
                sm, err := store.LoadMsg(seq, &svp)
1,023✔
4590
                if err != nil {
1,023✔
4591
                        hdr := []byte("NATS/1.0 404 Message Not Found\r\n\r\n")
×
4592
                        mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
×
4593
                        return
×
4594
                }
×
4595

4596
                hdr := sm.hdr
1,023✔
4597
                ts := time.Unix(0, sm.ts).UTC()
1,023✔
4598

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

4629
        // Send out EOB
4630
        hdr := fmt.Appendf(nil, eobm, np, lseq, upToSeq)
18✔
4631
        mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
18✔
4632
}
4633

4634
// Do actual work on a direct msg request.
4635
// This could be called in a Go routine if we are inline for a non-client connection.
4636
func (mset *stream) getDirectRequest(req *JSApiMsgGetRequest, reply string) {
13,107✔
4637
        // Handle multi in separate function.
13,107✔
4638
        if len(req.MultiLastFor) > 0 {
13,130✔
4639
                mset.getDirectMulti(req, reply)
23✔
4640
                return
23✔
4641
        }
23✔
4642

4643
        mset.mu.RLock()
13,084✔
4644
        store, name, s := mset.store, mset.cfg.Name, mset.srv
13,084✔
4645
        mset.mu.RUnlock()
13,084✔
4646

13,084✔
4647
        var seq uint64
13,084✔
4648
        // Lookup start seq if AsOfTime is set.
13,084✔
4649
        if req.StartTime != nil {
13,092✔
4650
                seq = store.GetSeqFromTime(*req.StartTime)
8✔
4651
        } else {
13,084✔
4652
                seq = req.Seq
13,076✔
4653
        }
13,076✔
4654

4655
        wc := subjectHasWildcard(req.NextFor)
13,084✔
4656
        // For tracking num pending if we are batch.
13,084✔
4657
        var np, lseq, validThrough uint64
13,084✔
4658
        var isBatchRequest bool
13,084✔
4659
        batch := req.Batch
13,084✔
4660
        if batch == 0 {
26,158✔
4661
                batch = 1
13,074✔
4662
        } else {
13,084✔
4663
                // This is a batch request, capture initial numPending.
10✔
4664
                isBatchRequest = true
10✔
4665
                np, validThrough = store.NumPending(seq, req.NextFor, false)
10✔
4666
        }
10✔
4667

4668
        // Grab MaxBytes
4669
        mb := req.MaxBytes
13,084✔
4670
        if mb == 0 && s != nil {
26,166✔
4671
                // Fill in with the server's MaxPending.
13,082✔
4672
                mb = int(s.opts.MaxPending)
13,082✔
4673
        }
13,082✔
4674
        // Track what we have sent.
4675
        var sentBytes int
13,084✔
4676

13,084✔
4677
        // Loop over batch, which defaults to 1.
13,084✔
4678
        for i := 0; i < batch; i++ {
26,306✔
4679
                var (
13,222✔
4680
                        svp StoreMsg
13,222✔
4681
                        sm  *StoreMsg
13,222✔
4682
                        err error
13,222✔
4683
                )
13,222✔
4684
                if seq > 0 && req.NextFor == _EMPTY_ {
13,362✔
4685
                        // Only do direct lookup for first in a batch.
140✔
4686
                        if i == 0 {
150✔
4687
                                sm, err = store.LoadMsg(seq, &svp)
10✔
4688
                        } else {
140✔
4689
                                // We want to use load next with fwcs to step over deleted msgs.
130✔
4690
                                sm, seq, err = store.LoadNextMsg(fwcs, true, seq, &svp)
130✔
4691
                        }
130✔
4692
                        // Bump for next loop if applicable.
4693
                        seq++
140✔
4694
                } else if req.NextFor != _EMPTY_ {
13,103✔
4695
                        sm, seq, err = store.LoadNextMsg(req.NextFor, wc, seq, &svp)
21✔
4696
                        seq++
21✔
4697
                } else {
13,082✔
4698
                        // Batch is not applicable here, this is checked before we get here.
13,061✔
4699
                        sm, err = store.LoadLastMsg(req.LastFor, &svp)
13,061✔
4700
                }
13,061✔
4701
                if err != nil {
13,235✔
4702
                        // For batches, if we stop early we want to do EOB logic below.
13✔
4703
                        if batch > 1 && i > 0 {
14✔
4704
                                break
1✔
4705
                        }
4706
                        hdr := []byte("NATS/1.0 404 Message Not Found\r\n\r\n")
12✔
4707
                        mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
12✔
4708
                        return
12✔
4709
                }
4710

4711
                hdr := sm.hdr
13,209✔
4712
                ts := time.Unix(0, sm.ts).UTC()
13,209✔
4713

13,209✔
4714
                if isBatchRequest {
13,354✔
4715
                        if len(hdr) == 0 {
290✔
4716
                                hdr = fmt.Appendf(nil, dgb, name, sm.subj, sm.seq, ts.Format(time.RFC3339Nano), np, lseq)
145✔
4717
                        } else {
145✔
4718
                                hdr = copyBytes(hdr)
×
4719
                                hdr = genHeader(hdr, JSStream, name)
×
4720
                                hdr = genHeader(hdr, JSSubject, sm.subj)
×
4721
                                hdr = genHeader(hdr, JSSequence, strconv.FormatUint(sm.seq, 10))
×
4722
                                hdr = genHeader(hdr, JSTimeStamp, ts.Format(time.RFC3339Nano))
×
4723
                                hdr = genHeader(hdr, JSNumPending, strconv.FormatUint(np, 10))
×
4724
                                hdr = genHeader(hdr, JSLastSequence, strconv.FormatUint(lseq, 10))
×
4725
                        }
×
4726
                        // Decrement num pending. This is optimization and we do not continue to look it up for these operations.
4727
                        np--
145✔
4728
                } else {
13,064✔
4729
                        if len(hdr) == 0 {
26,112✔
4730
                                hdr = fmt.Appendf(nil, dg, name, sm.subj, sm.seq, ts.Format(time.RFC3339Nano))
13,048✔
4731
                        } else {
13,064✔
4732
                                hdr = copyBytes(hdr)
16✔
4733
                                hdr = genHeader(hdr, JSStream, name)
16✔
4734
                                hdr = genHeader(hdr, JSSubject, sm.subj)
16✔
4735
                                hdr = genHeader(hdr, JSSequence, strconv.FormatUint(sm.seq, 10))
16✔
4736
                                hdr = genHeader(hdr, JSTimeStamp, ts.Format(time.RFC3339Nano))
16✔
4737
                        }
16✔
4738
                }
4739
                // Track our lseq
4740
                lseq = sm.seq
13,209✔
4741
                // Send out our message.
13,209✔
4742
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, sm.msg, nil, 0))
13,209✔
4743
                // Check if we have exceeded max bytes.
13,209✔
4744
                sentBytes += len(sm.subj) + len(sm.hdr) + len(sm.msg)
13,209✔
4745
                if sentBytes >= mb {
13,212✔
4746
                        break
3✔
4747
                }
4748
        }
4749

4750
        // If batch was requested send EOB.
4751
        if isBatchRequest {
13,080✔
4752
                // Update if the stream's lasts sequence has moved past our validThrough.
8✔
4753
                if mset.lastSeq() > validThrough {
8✔
4754
                        np, _ = store.NumPending(seq, req.NextFor, false)
×
4755
                }
×
4756
                hdr := fmt.Appendf(nil, eob, np, lseq)
8✔
4757
                mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
8✔
4758
        }
4759
}
4760

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

4780
var (
4781
        errLastSeqMismatch   = errors.New("last sequence mismatch")
4782
        errMsgIdDuplicate    = errors.New("msgid is duplicate")
4783
        errStreamClosed      = errors.New("stream closed")
4784
        errInvalidMsgHandler = errors.New("undefined message handler")
4785
        errStreamMismatch    = errors.New("expected stream does not match")
4786
        errMsgTTLDisabled    = errors.New("message TTL disabled")
4787
)
4788

4789
// processJetStreamMsg is where we try to actually process the stream msg.
4790
func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte, lseq uint64, ts int64, mt *msgTrace, sourced bool) (retErr error) {
1,429,852✔
4791
        if mt != nil {
1,429,898✔
4792
                // Only the leader/standalone will have mt!=nil. On exit, send the
46✔
4793
                // message trace event.
46✔
4794
                defer func() {
92✔
4795
                        mt.sendEventFromJetStream(retErr)
46✔
4796
                }()
46✔
4797
        }
4798

4799
        if mset.closed.Load() {
1,429,854✔
4800
                return errStreamClosed
2✔
4801
        }
2✔
4802

4803
        mset.mu.Lock()
1,429,850✔
4804
        s, store := mset.srv, mset.store
1,429,850✔
4805

1,429,850✔
4806
        traceOnly := mt.traceOnly()
1,429,850✔
4807
        bumpCLFS := func() {
1,429,942✔
4808
                // Do not bump if tracing and not doing message delivery.
92✔
4809
                if traceOnly {
129✔
4810
                        return
37✔
4811
                }
37✔
4812
                mset.clMu.Lock()
55✔
4813
                mset.clfs++
55✔
4814
                mset.clMu.Unlock()
55✔
4815
        }
4816

4817
        // Apply the input subject transform if any
4818
        if mset.itr != nil {
1,429,867✔
4819
                ts, err := mset.itr.Match(subject)
17✔
4820
                if err == nil {
34✔
4821
                        // no filtering: if the subject doesn't map the source of the transform, don't change it
17✔
4822
                        subject = ts
17✔
4823
                }
17✔
4824
        }
4825

4826
        var accName string
1,429,850✔
4827
        if mset.acc != nil {
2,859,700✔
4828
                accName = mset.acc.Name
1,429,850✔
4829
        }
1,429,850✔
4830

4831
        js, jsa, doAck := mset.js, mset.jsa, !mset.cfg.NoAck
1,429,850✔
4832
        name, stype := mset.cfg.Name, mset.cfg.Storage
1,429,850✔
4833
        maxMsgSize := int(mset.cfg.MaxMsgSize)
1,429,850✔
4834
        numConsumers := len(mset.consumers)
1,429,850✔
4835
        interestRetention := mset.cfg.Retention == InterestPolicy
1,429,850✔
4836
        // Snapshot if we are the leader and if we can respond.
1,429,850✔
4837
        isLeader, isSealed := mset.isLeaderNodeState(), mset.cfg.Sealed
1,429,850✔
4838
        canRespond := doAck && len(reply) > 0 && isLeader
1,429,850✔
4839

1,429,850✔
4840
        var resp = &JSPubAckResponse{}
1,429,850✔
4841

1,429,850✔
4842
        // Bail here if sealed.
1,429,850✔
4843
        if isSealed {
1,429,855✔
4844
                outq := mset.outq
5✔
4845
                mset.mu.Unlock()
5✔
4846
                bumpCLFS()
5✔
4847
                if canRespond && outq != nil {
10✔
4848
                        resp.PubAck = &PubAck{Stream: name}
5✔
4849
                        resp.Error = ApiErrors[JSStreamSealedErr]
5✔
4850
                        b, _ := json.Marshal(resp)
5✔
4851
                        outq.sendMsg(reply, b)
5✔
4852
                }
5✔
4853
                return ApiErrors[JSStreamSealedErr]
5✔
4854
        }
4855

4856
        var buf [256]byte
1,429,845✔
4857
        pubAck := append(buf[:0], mset.pubAck...)
1,429,845✔
4858

1,429,845✔
4859
        // If this is a non-clustered msg and we are not considered active, meaning no active subscription, do not process.
1,429,845✔
4860
        if lseq == 0 && ts == 0 && !mset.active {
1,429,845✔
4861
                mset.mu.Unlock()
×
4862
                return nil
×
4863
        }
×
4864

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

4893
        // If we have received this message across an account we may have request information attached.
4894
        // For now remove. TODO(dlc) - Should this be opt-in or opt-out?
4895
        if len(hdr) > 0 {
1,961,842✔
4896
                hdr = removeHeaderIfPresent(hdr, ClientInfoHdr)
532,006✔
4897
        }
532,006✔
4898

4899
        // Process additional msg headers if still present.
4900
        var msgId string
1,429,836✔
4901
        var rollupSub, rollupAll bool
1,429,836✔
4902
        isClustered := mset.isClustered()
1,429,836✔
4903

1,429,836✔
4904
        if len(hdr) > 0 {
1,961,832✔
4905
                outq := mset.outq
531,996✔
4906

531,996✔
4907
                // Certain checks have already been performed if in clustered mode, so only check if not.
531,996✔
4908
                // Note, for cluster mode but with message tracing (without message delivery), we need
531,996✔
4909
                // to do this check here since it was not done in processClusteredInboundMsg().
531,996✔
4910
                if !isClustered || traceOnly {
557,079✔
4911
                        // Expected stream.
25,083✔
4912
                        if sname := getExpectedStream(hdr); sname != _EMPTY_ && sname != name {
25,088✔
4913
                                mset.mu.Unlock()
5✔
4914
                                bumpCLFS()
5✔
4915
                                if canRespond {
10✔
4916
                                        resp.PubAck = &PubAck{Stream: name}
5✔
4917
                                        resp.Error = NewJSStreamNotMatchError()
5✔
4918
                                        b, _ := json.Marshal(resp)
5✔
4919
                                        outq.sendMsg(reply, b)
5✔
4920
                                }
5✔
4921
                                return errStreamMismatch
5✔
4922
                        }
4923
                }
4924

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

4940
                // Dedupe detection. This is done at the cluster level for dedupe detectiom above the
4941
                // lower layers. But we still need to pull out the msgId.
4942
                if msgId = getMsgId(hdr); msgId != _EMPTY_ {
1,033,148✔
4943
                        // Do real check only if not clustered or traceOnly flag is set.
501,159✔
4944
                        if !isClustered || traceOnly {
501,216✔
4945
                                if dde := mset.checkMsgId(msgId); dde != nil {
71✔
4946
                                        mset.mu.Unlock()
14✔
4947
                                        bumpCLFS()
14✔
4948
                                        if canRespond {
28✔
4949
                                                response := append(pubAck, strconv.FormatUint(dde.seq, 10)...)
14✔
4950
                                                response = append(response, ",\"duplicate\": true}"...)
14✔
4951
                                                outq.sendMsg(reply, response)
14✔
4952
                                        }
14✔
4953
                                        return errMsgIdDuplicate
14✔
4954
                                }
4955
                        }
4956
                }
4957

4958
                // Expected last sequence per subject.
4959
                if seq, exists := getExpectedLastSeqPerSubject(hdr); exists {
532,506✔
4960
                        // Allow override of the subject used for the check.
531✔
4961
                        seqSubj := subject
531✔
4962
                        if optSubj := getExpectedLastSeqPerSubjectForSubject(hdr); optSubj != _EMPTY_ {
567✔
4963
                                seqSubj = optSubj
36✔
4964
                        }
36✔
4965

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

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

5062
        // Response Ack.
5063
        var (
1,429,786✔
5064
                response []byte
1,429,786✔
5065
                seq      uint64
1,429,786✔
5066
                err      error
1,429,786✔
5067
        )
1,429,786✔
5068

1,429,786✔
5069
        // Check to see if we are over the max msg size.
1,429,786✔
5070
        if maxMsgSize >= 0 && (len(hdr)+len(msg)) > maxMsgSize {
1,429,792✔
5071
                mset.mu.Unlock()
6✔
5072
                bumpCLFS()
6✔
5073
                if canRespond {
12✔
5074
                        resp.PubAck = &PubAck{Stream: name}
6✔
5075
                        resp.Error = NewJSStreamMessageExceedsMaximumError()
6✔
5076
                        response, _ = json.Marshal(resp)
6✔
5077
                        mset.outq.sendMsg(reply, response)
6✔
5078
                }
6✔
5079
                return ErrMaxPayload
6✔
5080
        }
5081

5082
        if len(hdr) > math.MaxUint16 {
1,429,780✔
5083
                mset.mu.Unlock()
×
5084
                bumpCLFS()
×
5085
                if canRespond {
×
5086
                        resp.PubAck = &PubAck{Stream: name}
×
5087
                        resp.Error = NewJSStreamHeaderExceedsMaximumError()
×
5088
                        response, _ = json.Marshal(resp)
×
5089
                        mset.outq.sendMsg(reply, response)
×
5090
                }
×
5091
                return ErrMaxPayload
×
5092
        }
5093

5094
        // Check to see if we have exceeded our limits.
5095
        if js.limitsExceeded(stype) {
1,429,781✔
5096
                s.resourcesExceededError()
1✔
5097
                mset.mu.Unlock()
1✔
5098
                bumpCLFS()
1✔
5099
                if canRespond {
2✔
5100
                        resp.PubAck = &PubAck{Stream: name}
1✔
5101
                        resp.Error = NewJSInsufficientResourcesError()
1✔
5102
                        response, _ = json.Marshal(resp)
1✔
5103
                        mset.outq.sendMsg(reply, response)
1✔
5104
                }
1✔
5105
                // Stepdown regardless.
5106
                if node := mset.raftNode(); node != nil {
1✔
5107
                        node.StepDown()
×
5108
                }
×
5109
                return NewJSInsufficientResourcesError()
1✔
5110
        }
5111

5112
        var noInterest bool
1,429,779✔
5113

1,429,779✔
5114
        // If we are interest based retention and have no consumers then we can skip.
1,429,779✔
5115
        if interestRetention {
1,525,247✔
5116
                mset.clsMu.RLock()
95,468✔
5117
                noInterest = numConsumers == 0 || mset.csl == nil || !mset.csl.HasInterest(subject)
95,468✔
5118
                mset.clsMu.RUnlock()
95,468✔
5119
        }
95,468✔
5120

5121
        // Grab timestamp if not already set.
5122
        if ts == 0 && lseq > 0 {
1,429,779✔
5123
                ts = time.Now().UnixNano()
×
5124
        }
×
5125

5126
        mt.updateJetStreamEvent(subject, noInterest)
1,429,779✔
5127
        if traceOnly {
1,429,784✔
5128
                mset.mu.Unlock()
5✔
5129
                return nil
5✔
5130
        }
5✔
5131

5132
        // Skip msg here.
5133
        if noInterest {
1,474,969✔
5134
                mset.lseq = store.SkipMsg()
45,195✔
5135
                mset.lmsgId = msgId
45,195✔
5136
                // If we have a msgId make sure to save.
45,195✔
5137
                if msgId != _EMPTY_ {
45,196✔
5138
                        mset.storeMsgIdLocked(&ddentry{msgId, mset.lseq, ts})
1✔
5139
                }
1✔
5140
                if canRespond {
56,596✔
5141
                        response = append(pubAck, strconv.FormatUint(mset.lseq, 10)...)
11,401✔
5142
                        response = append(response, '}')
11,401✔
5143
                        mset.outq.sendMsg(reply, response)
11,401✔
5144
                }
11,401✔
5145
                mset.mu.Unlock()
45,195✔
5146
                return nil
45,195✔
5147
        }
5148

5149
        // If here we will attempt to store the message.
5150
        // Assume this will succeed.
5151
        olmsgId := mset.lmsgId
1,384,579✔
5152
        mset.lmsgId = msgId
1,384,579✔
5153
        clfs := mset.clfs
1,384,579✔
5154
        mset.lseq++
1,384,579✔
5155
        tierName := mset.tier
1,384,579✔
5156

1,384,579✔
5157
        // Republish state if needed.
1,384,579✔
5158
        var tsubj string
1,384,579✔
5159
        var tlseq uint64
1,384,579✔
5160
        var thdrsOnly bool
1,384,579✔
5161
        if mset.tr != nil {
1,386,084✔
5162
                tsubj, _ = mset.tr.Match(subject)
1,505✔
5163
                if mset.cfg.RePublish != nil {
3,010✔
5164
                        thdrsOnly = mset.cfg.RePublish.HeadersOnly
1,505✔
5165
                }
1,505✔
5166
        }
5167
        republish := tsubj != _EMPTY_ && isLeader
1,384,579✔
5168

1,384,579✔
5169
        // If we are republishing grab last sequence for this exact subject. Aids in gap detection for lightweight clients.
1,384,579✔
5170
        if republish {
1,385,282✔
5171
                var smv StoreMsg
703✔
5172
                if sm, _ := store.LoadLastMsg(subject, &smv); sm != nil {
1,398✔
5173
                        tlseq = sm.seq
695✔
5174
                }
695✔
5175
        }
5176

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

5195
        // Find the message TTL if any.
5196
        ttl, err := getMessageTTL(hdr)
1,384,546✔
5197
        if err != nil {
1,384,550✔
5198
                if canRespond {
8✔
5199
                        resp.PubAck = &PubAck{Stream: name}
4✔
5200
                        resp.Error = NewJSMessageTTLInvalidError()
4✔
5201
                        response, _ = json.Marshal(resp)
4✔
5202
                        mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0))
4✔
5203
                }
4✔
5204
                mset.mu.Unlock()
4✔
5205
                return err
4✔
5206
        }
5207

5208
        // If subject delete markers are used, ensure message TTL is that at minimum.
5209
        // Otherwise, subject delete markers could be missed if one already exists for this subject.
5210
        // MaxMsgsPer=1 is an exception, because we'll only ever have one message.
5211
        if ttl > 0 && mset.cfg.SubjectDeleteMarkerTTL > 0 && mset.cfg.MaxMsgsPer != 1 {
1,384,797✔
5212
                if minTtl := int64(mset.cfg.SubjectDeleteMarkerTTL.Seconds()); ttl < minTtl {
271✔
5213
                        ttl = minTtl
16✔
5214
                }
16✔
5215
        }
5216

5217
        // Store actual msg.
5218
        if lseq == 0 && ts == 0 {
1,682,853✔
5219
                seq, ts, err = store.StoreMsg(subject, hdr, msg, ttl)
298,311✔
5220
        } else {
1,384,542✔
5221
                // Make sure to take into account any message assignments that we had to skip (clfs).
1,086,231✔
5222
                seq = lseq + 1 - clfs
1,086,231✔
5223
                // Check for preAcks and the need to clear it.
1,086,231✔
5224
                if mset.hasAllPreAcks(seq, subject) {
1,086,281✔
5225
                        mset.clearAllPreAcks(seq)
50✔
5226
                }
50✔
5227
                err = store.StoreRawMsg(subject, hdr, msg, seq, ts, ttl)
1,086,231✔
5228
        }
5229

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

30✔
5247
                switch err {
30✔
5248
                case ErrMaxMsgs, ErrMaxBytes, ErrMaxMsgsPerSubject, ErrMsgTooLarge:
27✔
5249
                        s.RateLimitDebugf("JetStream failed to store a msg on stream '%s > %s': %v", accName, name, err)
27✔
5250
                case ErrStoreClosed:
×
5251
                default:
3✔
5252
                        s.Errorf("JetStream failed to store a msg on stream '%s > %s': %v", accName, name, err)
3✔
5253
                }
5254

5255
                if canRespond {
48✔
5256
                        resp.PubAck = &PubAck{Stream: name}
18✔
5257
                        resp.Error = NewJSStreamStoreFailedError(err, Unless(err))
18✔
5258
                        response, _ = json.Marshal(resp)
18✔
5259
                        mset.outq.sendMsg(reply, response)
18✔
5260
                }
18✔
5261
                return err
30✔
5262
        }
5263

5264
        // If we have a msgId make sure to save.
5265
        // This will replace our estimate from the cluster layer if we are clustered.
5266
        if msgId != _EMPTY_ {
1,885,652✔
5267
                if isClustered && isLeader && mset.ddmap != nil {
711,203✔
5268
                        if dde := mset.ddmap[msgId]; dde != nil {
420,125✔
5269
                                dde.seq, dde.ts = seq, ts
210,062✔
5270
                        } else {
210,063✔
5271
                                mset.storeMsgIdLocked(&ddentry{msgId, seq, ts})
1✔
5272
                        }
1✔
5273
                } else {
291,077✔
5274
                        // R1 or not leader..
291,077✔
5275
                        mset.storeMsgIdLocked(&ddentry{msgId, seq, ts})
291,077✔
5276
                }
291,077✔
5277
        }
5278

5279
        // If here we succeeded in storing the message.
5280
        mset.mu.Unlock()
1,384,512✔
5281

1,384,512✔
5282
        // No errors, this is the normal path.
1,384,512✔
5283
        if rollupSub {
1,384,659✔
5284
                mset.purge(&JSApiStreamPurgeRequest{Subject: subject, Keep: 1})
147✔
5285
        } else if rollupAll {
1,384,514✔
5286
                mset.purge(&JSApiStreamPurgeRequest{Keep: 1})
2✔
5287
        }
2✔
5288

5289
        // Check for republish.
5290
        if republish {
1,385,215✔
5291
                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✔
5292
                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✔
5293
                // When adding to existing headers, will use the fmt.Append version so this skips the headers from above.
703✔
5294
                const hoff = 10
703✔
5295

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

5318
        // Send response here.
5319
        if canRespond {
2,055,947✔
5320
                response = append(pubAck, strconv.FormatUint(seq, 10)...)
671,435✔
5321
                response = append(response, '}')
671,435✔
5322
                mset.outq.sendMsg(reply, response)
671,435✔
5323
        }
671,435✔
5324

5325
        // Signal consumers for new messages.
5326
        if numConsumers > 0 {
2,146,961✔
5327
                mset.sigq.push(newCMsg(subject, seq))
762,449✔
5328
                select {
762,449✔
5329
                case mset.sch <- struct{}{}:
604,065✔
5330
                default:
158,384✔
5331
                }
5332
        }
5333

5334
        return nil
1,384,512✔
5335
}
5336

5337
// Used to signal inbound message to registered consumers.
5338
type cMsg struct {
5339
        seq  uint64
5340
        subj string
5341
}
5342

5343
// Pool to recycle consumer bound msgs.
5344
var cMsgPool sync.Pool
5345

5346
// Used to queue up consumer bound msgs for signaling.
5347
func newCMsg(subj string, seq uint64) *cMsg {
762,449✔
5348
        var m *cMsg
762,449✔
5349
        cm := cMsgPool.Get()
762,449✔
5350
        if cm != nil {
1,513,195✔
5351
                m = cm.(*cMsg)
750,746✔
5352
        } else {
762,449✔
5353
                m = new(cMsg)
11,703✔
5354
        }
11,703✔
5355
        m.subj, m.seq = subj, seq
762,449✔
5356

762,449✔
5357
        return m
762,449✔
5358
}
5359

5360
func (m *cMsg) returnToPool() {
762,449✔
5361
        if m == nil {
762,449✔
5362
                return
×
5363
        }
×
5364
        m.subj, m.seq = _EMPTY_, 0
762,449✔
5365
        cMsgPool.Put(m)
762,449✔
5366
}
5367

5368
// Go routine to signal consumers.
5369
// Offloaded from stream msg processing.
5370
func (mset *stream) signalConsumersLoop() {
5,463✔
5371
        mset.mu.RLock()
5,463✔
5372
        s, qch, sch, msgs := mset.srv, mset.qch, mset.sch, mset.sigq
5,463✔
5373
        mset.mu.RUnlock()
5,463✔
5374

5,463✔
5375
        for {
614,991✔
5376
                select {
609,528✔
5377
                case <-s.quitCh:
4✔
5378
                        return
4✔
5379
                case <-qch:
5,459✔
5380
                        return
5,459✔
5381
                case <-sch:
604,065✔
5382
                        cms := msgs.pop()
604,065✔
5383
                        for _, m := range cms {
1,366,514✔
5384
                                seq, subj := m.seq, m.subj
762,449✔
5385
                                m.returnToPool()
762,449✔
5386
                                // Signal all appropriate consumers.
762,449✔
5387
                                mset.signalConsumers(subj, seq)
762,449✔
5388
                        }
762,449✔
5389
                        msgs.recycle(&cms)
604,065✔
5390
                }
5391
        }
5392
}
5393

5394
// This will update and signal all consumers that match.
5395
func (mset *stream) signalConsumers(subj string, seq uint64) {
762,449✔
5396
        mset.clsMu.RLock()
762,449✔
5397
        defer mset.clsMu.RUnlock()
762,449✔
5398
        csl := mset.csl
762,449✔
5399
        if csl == nil {
762,449✔
5400
                return
×
5401
        }
×
5402
        csl.Match(subj, func(o *consumer) {
1,552,273✔
5403
                o.processStreamSignal(seq)
789,824✔
5404
        })
789,824✔
5405
}
5406

5407
// Internal message for use by jetstream subsystem.
5408
type jsPubMsg struct {
5409
        dsubj string // Subject to send to, e.g. _INBOX.xxx
5410
        reply string
5411
        StoreMsg
5412
        o *consumer
5413
}
5414

5415
var jsPubMsgPool sync.Pool
5416

5417
func newJSPubMsg(dsubj, subj, reply string, hdr, msg []byte, o *consumer, seq uint64) *jsPubMsg {
1,016,202✔
5418
        var m *jsPubMsg
1,016,202✔
5419
        var buf []byte
1,016,202✔
5420
        pm := jsPubMsgPool.Get()
1,016,202✔
5421
        if pm != nil {
2,011,575✔
5422
                m = pm.(*jsPubMsg)
995,373✔
5423
                buf = m.buf[:0]
995,373✔
5424
                if hdr != nil {
1,067,226✔
5425
                        hdr = append(m.hdr[:0], hdr...)
71,853✔
5426
                }
71,853✔
5427
        } else {
20,829✔
5428
                m = new(jsPubMsg)
20,829✔
5429
        }
20,829✔
5430
        // When getting something from a pool it is critical that all fields are
5431
        // initialized. Doing this way guarantees that if someone adds a field to
5432
        // the structure, the compiler will fail the build if this line is not updated.
5433
        (*m) = jsPubMsg{dsubj, reply, StoreMsg{subj, hdr, msg, buf, seq, 0}, o}
1,016,202✔
5434

1,016,202✔
5435
        return m
1,016,202✔
5436
}
5437

5438
// Gets a jsPubMsg from the pool.
5439
func getJSPubMsgFromPool() *jsPubMsg {
530,085✔
5440
        pm := jsPubMsgPool.Get()
530,085✔
5441
        if pm != nil {
1,055,082✔
5442
                return pm.(*jsPubMsg)
524,997✔
5443
        }
524,997✔
5444
        return new(jsPubMsg)
5,088✔
5445
}
5446

5447
func (pm *jsPubMsg) returnToPool() {
1,546,169✔
5448
        if pm == nil {
1,546,169✔
5449
                return
×
5450
        }
×
5451
        pm.subj, pm.dsubj, pm.reply, pm.hdr, pm.msg, pm.o = _EMPTY_, _EMPTY_, _EMPTY_, nil, nil, nil
1,546,169✔
5452
        if len(pm.buf) > 0 {
1,966,276✔
5453
                pm.buf = pm.buf[:0]
420,107✔
5454
        }
420,107✔
5455
        if len(pm.hdr) > 0 {
1,546,169✔
5456
                pm.hdr = pm.hdr[:0]
×
5457
        }
×
5458
        jsPubMsgPool.Put(pm)
1,546,169✔
5459
}
5460

5461
func (pm *jsPubMsg) size() int {
410,396✔
5462
        if pm == nil {
410,396✔
5463
                return 0
×
5464
        }
×
5465
        return len(pm.dsubj) + len(pm.reply) + len(pm.hdr) + len(pm.msg)
410,396✔
5466
}
5467

5468
// Queue of *jsPubMsg for sending internal system messages.
5469
type jsOutQ struct {
5470
        *ipQueue[*jsPubMsg]
5471
}
5472

5473
func (q *jsOutQ) sendMsg(subj string, msg []byte) {
920,286✔
5474
        if q != nil {
1,840,572✔
5475
                q.send(newJSPubMsg(subj, _EMPTY_, _EMPTY_, nil, msg, nil, 0))
920,286✔
5476
        }
920,286✔
5477
}
5478

5479
func (q *jsOutQ) send(msg *jsPubMsg) {
1,426,587✔
5480
        if q == nil || msg == nil {
1,426,587✔
5481
                return
×
5482
        }
×
5483
        q.push(msg)
1,426,587✔
5484
}
5485

5486
func (q *jsOutQ) unregister() {
588✔
5487
        if q == nil {
589✔
5488
                return
1✔
5489
        }
1✔
5490
        q.ipQueue.unregister()
587✔
5491
}
5492

5493
// StoredMsg is for raw access to messages in a stream.
5494
type StoredMsg struct {
5495
        Subject  string    `json:"subject"`
5496
        Sequence uint64    `json:"seq"`
5497
        Header   []byte    `json:"hdrs,omitempty"`
5498
        Data     []byte    `json:"data,omitempty"`
5499
        Time     time.Time `json:"time"`
5500
}
5501

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

5515
// Returns the associated account name.
5516
func (mset *stream) accName() string {
23,706✔
5517
        if mset == nil {
23,713✔
5518
                return _EMPTY_
7✔
5519
        }
7✔
5520
        mset.mu.RLock()
23,699✔
5521
        acc := mset.acc
23,699✔
5522
        mset.mu.RUnlock()
23,699✔
5523
        return acc.Name
23,699✔
5524
}
5525

5526
// Name returns the stream name.
5527
func (mset *stream) name() string {
100,732✔
5528
        if mset == nil {
100,739✔
5529
                return _EMPTY_
7✔
5530
        }
7✔
5531
        mset.mu.RLock()
100,725✔
5532
        defer mset.mu.RUnlock()
100,725✔
5533
        return mset.cfg.Name
100,725✔
5534
}
5535

5536
func (mset *stream) internalLoop() {
5,462✔
5537
        mset.mu.RLock()
5,462✔
5538
        setGoRoutineLabels(pprofLabels{
5,462✔
5539
                "account": mset.acc.Name,
5,462✔
5540
                "stream":  mset.cfg.Name,
5,462✔
5541
        })
5,462✔
5542
        s := mset.srv
5,462✔
5543
        c := s.createInternalJetStreamClient()
5,462✔
5544
        c.registerWithAccount(mset.acc)
5,462✔
5545
        defer c.closeConnection(ClientClosed)
5,462✔
5546
        outq, qch, msgs, gets := mset.outq, mset.qch, mset.msgs, mset.gets
5,462✔
5547

5,462✔
5548
        // For the ack msgs queue for interest retention.
5,462✔
5549
        var (
5,462✔
5550
                amch chan struct{}
5,462✔
5551
                ackq *ipQueue[uint64]
5,462✔
5552
        )
5,462✔
5553
        if mset.ackq != nil {
6,968✔
5554
                ackq, amch = mset.ackq, mset.ackq.ch
1,506✔
5555
        }
1,506✔
5556
        mset.mu.RUnlock()
5,462✔
5557

5,462✔
5558
        // Raw scratch buffer.
5,462✔
5559
        // This should be rarely used now so can be smaller.
5,462✔
5560
        var _r [1024]byte
5,462✔
5561

5,462✔
5562
        // To optimize for not converting a string to a []byte slice.
5,462✔
5563
        var (
5,462✔
5564
                subj  [256]byte
5,462✔
5565
                dsubj [256]byte
5,462✔
5566
                rply  [256]byte
5,462✔
5567
                szb   [10]byte
5,462✔
5568
                hdb   [10]byte
5,462✔
5569
        )
5,462✔
5570

5,462✔
5571
        for {
1,474,500✔
5572
                select {
1,469,038✔
5573
                case <-outq.ch:
879,862✔
5574
                        pms := outq.pop()
879,862✔
5575
                        for _, pm := range pms {
2,306,332✔
5576
                                c.pa.subject = append(dsubj[:0], pm.dsubj...)
1,426,470✔
5577
                                c.pa.deliver = append(subj[:0], pm.subj...)
1,426,470✔
5578
                                c.pa.size = len(pm.msg) + len(pm.hdr)
1,426,470✔
5579
                                c.pa.szb = append(szb[:0], strconv.Itoa(c.pa.size)...)
1,426,470✔
5580
                                if len(pm.reply) > 0 {
1,837,113✔
5581
                                        c.pa.reply = append(rply[:0], pm.reply...)
410,643✔
5582
                                } else {
1,426,470✔
5583
                                        c.pa.reply = nil
1,015,827✔
5584
                                }
1,015,827✔
5585

5586
                                // If we have an underlying buf that is the wire contents for hdr + msg, else construct on the fly.
5587
                                var msg []byte
1,426,470✔
5588
                                if len(pm.buf) > 0 {
1,828,800✔
5589
                                        msg = pm.buf
402,330✔
5590
                                } else {
1,426,470✔
5591
                                        if len(pm.hdr) > 0 {
1,097,682✔
5592
                                                msg = pm.hdr
73,542✔
5593
                                                if len(pm.msg) > 0 {
88,448✔
5594
                                                        msg = _r[:0]
14,906✔
5595
                                                        msg = append(msg, pm.hdr...)
14,906✔
5596
                                                        msg = append(msg, pm.msg...)
14,906✔
5597
                                                }
14,906✔
5598
                                        } else if len(pm.msg) > 0 {
1,681,916✔
5599
                                                // We own this now from a low level buffer perspective so can use directly here.
731,318✔
5600
                                                msg = pm.msg
731,318✔
5601
                                        }
731,318✔
5602
                                }
5603

5604
                                if len(pm.hdr) > 0 {
1,707,653✔
5605
                                        c.pa.hdr = len(pm.hdr)
281,183✔
5606
                                        c.pa.hdb = []byte(strconv.Itoa(c.pa.hdr))
281,183✔
5607
                                        c.pa.hdb = append(hdb[:0], strconv.Itoa(c.pa.hdr)...)
281,183✔
5608
                                } else {
1,426,470✔
5609
                                        c.pa.hdr = -1
1,145,287✔
5610
                                        c.pa.hdb = nil
1,145,287✔
5611
                                }
1,145,287✔
5612

5613
                                msg = append(msg, _CRLF_...)
1,426,470✔
5614

1,426,470✔
5615
                                didDeliver, _ := c.processInboundClientMsg(msg)
1,426,470✔
5616
                                c.pa.szb, c.pa.subject, c.pa.deliver = nil, nil, nil
1,426,470✔
5617

1,426,470✔
5618
                                // Check to see if this is a delivery for a consumer and
1,426,470✔
5619
                                // we failed to deliver the message. If so alert the consumer.
1,426,470✔
5620
                                if pm.o != nil && pm.seq > 0 && !didDeliver {
1,427,885✔
5621
                                        pm.o.didNotDeliver(pm.seq, pm.dsubj)
1,415✔
5622
                                }
1,415✔
5623
                                pm.returnToPool()
1,426,470✔
5624
                        }
5625
                        // TODO: Move in the for-loop?
5626
                        c.flushClients(0)
879,862✔
5627
                        outq.recycle(&pms)
879,862✔
5628
                case <-msgs.ch:
572,574✔
5629
                        // This can possibly change now so needs to be checked here.
572,574✔
5630
                        isClustered := mset.IsClustered()
572,574✔
5631
                        ims := msgs.pop()
572,574✔
5632
                        for _, im := range ims {
1,311,344✔
5633
                                // If we are clustered we need to propose this message to the underlying raft group.
738,770✔
5634
                                if isClustered {
1,182,708✔
5635
                                        mset.processClusteredInboundMsg(im.subj, im.rply, im.hdr, im.msg, im.mt, false)
443,938✔
5636
                                } else {
738,770✔
5637
                                        mset.processJetStreamMsg(im.subj, im.rply, im.hdr, im.msg, 0, 0, im.mt, false)
294,832✔
5638
                                }
294,832✔
5639
                                im.returnToPool()
738,770✔
5640
                        }
5641
                        msgs.recycle(&ims)
572,574✔
5642
                case <-gets.ch:
10,928✔
5643
                        dgs := gets.pop()
10,928✔
5644
                        for _, dg := range dgs {
21,856✔
5645
                                mset.getDirectRequest(&dg.req, dg.reply)
10,928✔
5646
                                dgPool.Put(dg)
10,928✔
5647
                        }
10,928✔
5648
                        gets.recycle(&dgs)
10,928✔
5649

5650
                case <-amch:
212✔
5651
                        seqs := ackq.pop()
212✔
5652
                        for _, seq := range seqs {
426✔
5653
                                mset.ackMsg(nil, seq)
214✔
5654
                        }
214✔
5655
                        ackq.recycle(&seqs)
212✔
5656
                case <-qch:
5,449✔
5657
                        return
5,449✔
5658
                case <-s.quitCh:
13✔
5659
                        return
13✔
5660
                }
5661
        }
5662
}
5663

5664
// Used to break consumers out of their monitorConsumer go routines.
5665
func (mset *stream) resetAndWaitOnConsumers() {
17✔
5666
        mset.mu.RLock()
17✔
5667
        consumers := make([]*consumer, 0, len(mset.consumers))
17✔
5668
        for _, o := range mset.consumers {
18✔
5669
                consumers = append(consumers, o)
1✔
5670
        }
1✔
5671
        mset.mu.RUnlock()
17✔
5672

17✔
5673
        for _, o := range consumers {
18✔
5674
                if node := o.raftNode(); node != nil {
2✔
5675
                        node.StepDown()
1✔
5676
                        node.Stop()
1✔
5677
                }
1✔
5678
                if o.isMonitorRunning() {
2✔
5679
                        o.monitorWg.Wait()
1✔
5680
                }
1✔
5681
        }
5682
}
5683

5684
// Internal function to delete a stream.
5685
func (mset *stream) delete() error {
314✔
5686
        if mset == nil {
315✔
5687
                return nil
1✔
5688
        }
1✔
5689
        return mset.stop(true, true)
313✔
5690
}
5691

5692
// Internal function to stop or delete the stream.
5693
func (mset *stream) stop(deleteFlag, advisory bool) error {
5,477✔
5694
        mset.mu.RLock()
5,477✔
5695
        js, jsa, name := mset.js, mset.jsa, mset.cfg.Name
5,477✔
5696
        mset.mu.RUnlock()
5,477✔
5697

5,477✔
5698
        if jsa == nil {
5,477✔
5699
                return NewJSNotEnabledForAccountError()
×
5700
        }
×
5701

5702
        // Remove from our account map first.
5703
        jsa.mu.Lock()
5,477✔
5704
        delete(jsa.streams, name)
5,477✔
5705
        accName := jsa.account.Name
5,477✔
5706
        jsa.mu.Unlock()
5,477✔
5707

5,477✔
5708
        // Kick monitor and collect consumers first.
5,477✔
5709
        mset.mu.Lock()
5,477✔
5710

5,477✔
5711
        // Mark closed.
5,477✔
5712
        mset.closed.Store(true)
5,477✔
5713

5,477✔
5714
        // Signal to the monitor loop.
5,477✔
5715
        // Can't use qch here.
5,477✔
5716
        if mset.mqch != nil {
10,938✔
5717
                close(mset.mqch)
5,461✔
5718
                mset.mqch = nil
5,461✔
5719
        }
5,461✔
5720

5721
        // Stop responding to sync requests.
5722
        mset.stopClusterSubs()
5,477✔
5723
        // Unsubscribe from direct stream.
5,477✔
5724
        mset.unsubscribeToStream(true)
5,477✔
5725

5,477✔
5726
        // Our info sub if we spun it up.
5,477✔
5727
        if mset.infoSub != nil {
9,264✔
5728
                mset.srv.sysUnsubscribe(mset.infoSub)
3,787✔
5729
                mset.infoSub = nil
3,787✔
5730
        }
3,787✔
5731

5732
        // Clean up consumers.
5733
        var obs []*consumer
5,477✔
5734
        for _, o := range mset.consumers {
7,519✔
5735
                obs = append(obs, o)
2,042✔
5736
        }
2,042✔
5737
        mset.clsMu.Lock()
5,477✔
5738
        mset.consumers, mset.cList, mset.csl = nil, nil, nil
5,477✔
5739
        mset.clsMu.Unlock()
5,477✔
5740

5,477✔
5741
        // Check if we are a mirror.
5,477✔
5742
        if mset.mirror != nil && mset.mirror.sub != nil {
5,477✔
5743
                mset.unsubscribe(mset.mirror.sub)
×
5744
                mset.mirror.sub = nil
×
5745
                mset.removeInternalConsumer(mset.mirror)
×
5746
        }
×
5747
        // Now check for sources.
5748
        if len(mset.sources) > 0 {
5,547✔
5749
                for _, si := range mset.sources {
182✔
5750
                        mset.cancelSourceConsumer(si.iname)
112✔
5751
                }
112✔
5752
        }
5753
        mset.mu.Unlock()
5,477✔
5754

5,477✔
5755
        isShuttingDown := js.isShuttingDown()
5,477✔
5756
        for _, o := range obs {
7,519✔
5757
                if !o.isClosed() {
4,082✔
5758
                        // Third flag says do not broadcast a signal.
2,040✔
5759
                        // TODO(dlc) - If we have an err here we don't want to stop
2,040✔
5760
                        // but should we log?
2,040✔
5761
                        o.stopWithFlags(deleteFlag, deleteFlag, false, advisory)
2,040✔
5762
                        if !isShuttingDown {
2,180✔
5763
                                o.monitorWg.Wait()
140✔
5764
                        }
140✔
5765
                }
5766
        }
5767

5768
        mset.mu.Lock()
5,477✔
5769
        // Send stream delete advisory after the consumers.
5,477✔
5770
        if deleteFlag && advisory {
5,883✔
5771
                mset.sendDeleteAdvisoryLocked()
406✔
5772
        }
406✔
5773

5774
        // Quit channel, do this after sending the delete advisory
5775
        if mset.qch != nil {
10,938✔
5776
                close(mset.qch)
5,461✔
5777
                mset.qch = nil
5,461✔
5778
        }
5,461✔
5779

5780
        // Cluster cleanup
5781
        var sa *streamAssignment
5,477✔
5782
        if n := mset.node; n != nil {
8,502✔
5783
                if deleteFlag {
3,251✔
5784
                        n.Delete()
226✔
5785
                        sa = mset.sa
226✔
5786
                } else {
3,025✔
5787
                        n.Stop()
2,799✔
5788
                }
2,799✔
5789
        }
5790

5791
        // Cleanup duplicate timer if running.
5792
        if mset.ddtmr != nil {
5,538✔
5793
                mset.ddtmr.Stop()
61✔
5794
                mset.ddtmr = nil
61✔
5795
                mset.ddmap = nil
61✔
5796
                mset.ddarr = nil
61✔
5797
                mset.ddindex = 0
61✔
5798
        }
61✔
5799

5800
        sysc := mset.sysc
5,477✔
5801
        mset.sysc = nil
5,477✔
5802

5,477✔
5803
        if deleteFlag {
6,065✔
5804
                // Unregistering ipQueues do not prevent them from push/pop
588✔
5805
                // just will remove them from the central monitoring map
588✔
5806
                mset.msgs.unregister()
588✔
5807
                mset.ackq.unregister()
588✔
5808
                mset.outq.unregister()
588✔
5809
                mset.sigq.unregister()
588✔
5810
                mset.smsgs.unregister()
588✔
5811
        }
588✔
5812

5813
        // Snapshot store.
5814
        store := mset.store
5,477✔
5815
        c := mset.client
5,477✔
5816

5,477✔
5817
        // Clustered cleanup.
5,477✔
5818
        mset.mu.Unlock()
5,477✔
5819

5,477✔
5820
        // Check if the stream assignment has the group node specified.
5,477✔
5821
        // We need this cleared for if the stream gets reassigned here.
5,477✔
5822
        if sa != nil {
5,703✔
5823
                js.mu.Lock()
226✔
5824
                if sa.Group != nil {
452✔
5825
                        sa.Group.node = nil
226✔
5826
                }
226✔
5827
                js.mu.Unlock()
226✔
5828
        }
5829

5830
        if c != nil {
10,954✔
5831
                c.closeConnection(ClientClosed)
5,477✔
5832
        }
5,477✔
5833

5834
        if sysc != nil {
10,938✔
5835
                sysc.closeConnection(ClientClosed)
5,461✔
5836
        }
5,461✔
5837

5838
        if deleteFlag {
6,065✔
5839
                if store != nil {
1,175✔
5840
                        // Ignore errors.
587✔
5841
                        store.Delete()
587✔
5842
                }
587✔
5843
                // Release any resources.
5844
                js.releaseStreamResources(&mset.cfg)
588✔
5845
                // cleanup directories after the stream
588✔
5846
                accDir := filepath.Join(js.config.StoreDir, accName)
588✔
5847
                // Do cleanup in separate go routine similar to how fs will use purge here..
588✔
5848
                go func() {
1,176✔
5849
                        // no op if not empty
588✔
5850
                        os.Remove(filepath.Join(accDir, streamsDir))
588✔
5851
                        os.Remove(accDir)
588✔
5852
                }()
588✔
5853
        } else if store != nil {
9,778✔
5854
                // Ignore errors.
4,889✔
5855
                store.Stop()
4,889✔
5856
        }
4,889✔
5857

5858
        return nil
5,477✔
5859
}
5860

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

5877
// getConsumers will return a copy of all the current consumers for this stream.
5878
func (mset *stream) getConsumers() []*consumer {
6,123✔
5879
        mset.clsMu.RLock()
6,123✔
5880
        defer mset.clsMu.RUnlock()
6,123✔
5881
        return append([]*consumer(nil), mset.cList...)
6,123✔
5882
}
6,123✔
5883

5884
// Lock should be held for this one.
5885
func (mset *stream) numPublicConsumers() int {
69✔
5886
        return len(mset.consumers) - mset.directs
69✔
5887
}
69✔
5888

5889
// This returns all consumers that are not DIRECT.
5890
func (mset *stream) getPublicConsumers() []*consumer {
177✔
5891
        mset.clsMu.RLock()
177✔
5892
        defer mset.clsMu.RUnlock()
177✔
5893

177✔
5894
        var obs []*consumer
177✔
5895
        for _, o := range mset.cList {
364✔
5896
                if !o.cfg.Direct {
369✔
5897
                        obs = append(obs, o)
182✔
5898
                }
182✔
5899
        }
5900
        return obs
177✔
5901
}
5902

5903
// 2 minutes plus up to 30s jitter.
5904
const (
5905
        defaultCheckInterestStateT = 2 * time.Minute
5906
        defaultCheckInterestStateJ = 30
5907
)
5908

5909
var (
5910
        checkInterestStateT = defaultCheckInterestStateT // Interval
5911
        checkInterestStateJ = defaultCheckInterestStateJ // Jitter (secs)
5912
)
5913

5914
// Will check for interest retention and make sure messages
5915
// that have been acked are processed and removed.
5916
// This will check the ack floors of all consumers, and adjust our first sequence accordingly.
5917
func (mset *stream) checkInterestState() {
9,898✔
5918
        if mset == nil || !mset.isInterestRetention() {
14,877✔
5919
                // If we are limits based nothing to do.
4,979✔
5920
                return
4,979✔
5921
        }
4,979✔
5922

5923
        var ss StreamState
4,919✔
5924
        mset.store.FastState(&ss)
4,919✔
5925

4,919✔
5926
        for _, o := range mset.getConsumers() {
5,396✔
5927
                o.checkStateForInterestStream(&ss)
477✔
5928
        }
477✔
5929
}
5930

5931
func (mset *stream) isInterestRetention() bool {
16,059✔
5932
        mset.mu.RLock()
16,059✔
5933
        defer mset.mu.RUnlock()
16,059✔
5934
        return mset.cfg.Retention != LimitsPolicy
16,059✔
5935
}
16,059✔
5936

5937
// NumConsumers reports on number of active consumers for this stream.
5938
func (mset *stream) numConsumers() int {
1,236✔
5939
        mset.mu.RLock()
1,236✔
5940
        defer mset.mu.RUnlock()
1,236✔
5941
        return len(mset.consumers)
1,236✔
5942
}
1,236✔
5943

5944
// Lock should be held.
5945
func (mset *stream) setConsumer(o *consumer) {
9,180✔
5946
        mset.consumers[o.name] = o
9,180✔
5947
        if len(o.subjf) > 0 {
16,819✔
5948
                mset.numFilter++
7,639✔
5949
        }
7,639✔
5950
        if o.cfg.Direct {
9,321✔
5951
                mset.directs++
141✔
5952
        }
141✔
5953
        // Now update consumers list as well
5954
        mset.clsMu.Lock()
9,180✔
5955
        mset.cList = append(mset.cList, o)
9,180✔
5956
        if mset.csl == nil {
10,759✔
5957
                mset.csl = gsl.NewSublist[*consumer]()
1,579✔
5958
        }
1,579✔
5959
        for _, sub := range o.signalSubs() {
18,456✔
5960
                mset.csl.Insert(sub, o)
9,276✔
5961
        }
9,276✔
5962
        mset.clsMu.Unlock()
9,180✔
5963
}
5964

5965
// Lock should be held.
5966
func (mset *stream) removeConsumer(o *consumer) {
9,190✔
5967
        if o.cfg.FilterSubject != _EMPTY_ && mset.numFilter > 0 {
16,770✔
5968
                mset.numFilter--
7,580✔
5969
        }
7,580✔
5970
        if o.cfg.Direct && mset.directs > 0 {
9,331✔
5971
                mset.directs--
141✔
5972
        }
141✔
5973
        if mset.consumers != nil {
16,338✔
5974
                delete(mset.consumers, o.name)
7,148✔
5975
                // Now update consumers list as well
7,148✔
5976
                mset.clsMu.Lock()
7,148✔
5977
                for i, ol := range mset.cList {
139,913✔
5978
                        if ol == o {
139,903✔
5979
                                mset.cList = append(mset.cList[:i], mset.cList[i+1:]...)
7,138✔
5980
                                break
7,138✔
5981
                        }
5982
                }
5983
                // Always remove from the leader sublist.
5984
                if mset.csl != nil {
14,292✔
5985
                        for _, sub := range o.signalSubs() {
14,348✔
5986
                                mset.csl.Remove(sub, o)
7,204✔
5987
                        }
7,204✔
5988
                }
5989
                mset.clsMu.Unlock()
7,148✔
5990
        }
5991
}
5992

5993
// swapSigSubs will update signal Subs for a new subject filter.
5994
// consumer lock should not be held.
5995
func (mset *stream) swapSigSubs(o *consumer, newFilters []string) {
12✔
5996
        mset.clsMu.Lock()
12✔
5997
        o.mu.Lock()
12✔
5998

12✔
5999
        if o.closed || o.mset == nil {
12✔
6000
                o.mu.Unlock()
×
6001
                mset.clsMu.Unlock()
×
6002
                return
×
6003
        }
×
6004

6005
        if o.sigSubs != nil {
24✔
6006
                if mset.csl != nil {
24✔
6007
                        for _, sub := range o.sigSubs {
29✔
6008
                                mset.csl.Remove(sub, o)
17✔
6009
                        }
17✔
6010
                }
6011
                o.sigSubs = nil
12✔
6012
        }
6013

6014
        if o.isLeader() {
22✔
6015
                if mset.csl == nil {
10✔
6016
                        mset.csl = gsl.NewSublist[*consumer]()
×
6017
                }
×
6018
                // If no filters are preset, add fwcs to sublist for that consumer.
6019
                if newFilters == nil {
10✔
6020
                        mset.csl.Insert(fwcs, o)
×
6021
                        o.sigSubs = append(o.sigSubs, fwcs)
×
6022
                        // If there are filters, add their subjects to sublist.
×
6023
                } else {
10✔
6024
                        for _, filter := range newFilters {
22✔
6025
                                mset.csl.Insert(filter, o)
12✔
6026
                                o.sigSubs = append(o.sigSubs, filter)
12✔
6027
                        }
12✔
6028
                }
6029
        }
6030
        o.mu.Unlock()
12✔
6031
        mset.clsMu.Unlock()
12✔
6032

12✔
6033
        mset.mu.Lock()
12✔
6034
        defer mset.mu.Unlock()
12✔
6035

12✔
6036
        if mset.numFilter > 0 && len(o.subjf) > 0 {
24✔
6037
                mset.numFilter--
12✔
6038
        }
12✔
6039
        if len(newFilters) > 0 {
22✔
6040
                mset.numFilter++
10✔
6041
        }
10✔
6042
}
6043

6044
// lookupConsumer will retrieve a consumer by name.
6045
func (mset *stream) lookupConsumer(name string) *consumer {
21,219✔
6046
        mset.mu.RLock()
21,219✔
6047
        defer mset.mu.RUnlock()
21,219✔
6048
        return mset.consumers[name]
21,219✔
6049
}
21,219✔
6050

6051
func (mset *stream) numDirectConsumers() (num int) {
179✔
6052
        mset.clsMu.RLock()
179✔
6053
        defer mset.clsMu.RUnlock()
179✔
6054

179✔
6055
        // Consumers that are direct are not recorded at the store level.
179✔
6056
        for _, o := range mset.cList {
435✔
6057
                o.mu.RLock()
256✔
6058
                if o.cfg.Direct {
512✔
6059
                        num++
256✔
6060
                }
256✔
6061
                o.mu.RUnlock()
256✔
6062
        }
6063
        return num
179✔
6064
}
6065

6066
// State will return the current state for this stream.
6067
func (mset *stream) state() StreamState {
11,202✔
6068
        return mset.stateWithDetail(false)
11,202✔
6069
}
11,202✔
6070

6071
func (mset *stream) stateWithDetail(details bool) StreamState {
26,064✔
6072
        // mset.store does not change once set, so ok to reference here directly.
26,064✔
6073
        // We do this elsewhere as well.
26,064✔
6074
        store := mset.store
26,064✔
6075
        if store == nil {
26,064✔
6076
                return StreamState{}
×
6077
        }
×
6078

6079
        // Currently rely on store for details.
6080
        if details {
26,068✔
6081
                return store.State()
4✔
6082
        }
4✔
6083
        // Here we do the fast version.
6084
        var state StreamState
26,060✔
6085
        store.FastState(&state)
26,060✔
6086
        return state
26,060✔
6087
}
6088

6089
func (mset *stream) Store() StreamStore {
3✔
6090
        mset.mu.RLock()
3✔
6091
        defer mset.mu.RUnlock()
3✔
6092
        return mset.store
3✔
6093
}
3✔
6094

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

6117
// Lock should be held.
6118
func (mset *stream) potentialFilteredConsumers() bool {
62,173✔
6119
        numSubjects := len(mset.cfg.Subjects)
62,173✔
6120
        if len(mset.consumers) == 0 || numSubjects == 0 {
62,176✔
6121
                return false
3✔
6122
        }
3✔
6123
        if numSubjects > 1 || subjectHasWildcard(mset.cfg.Subjects[0]) {
80,200✔
6124
                return true
18,030✔
6125
        }
18,030✔
6126
        return false
44,140✔
6127
}
6128

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

6136
// Check if there is no interest in this sequence number and subject across our consumers.
6137
// The consumer passed is optional if we are processing the ack for that consumer.
6138
// Write lock should be held.
6139
func (mset *stream) noInterestWithSubject(seq uint64, subj string, obs *consumer) bool {
50✔
6140
        return !mset.checkForInterestWithSubject(seq, subj, obs)
50✔
6141
}
50✔
6142

6143
// Write lock should be held here for the stream to avoid race conditions on state.
6144
func (mset *stream) checkForInterest(seq uint64, obs *consumer) bool {
62,173✔
6145
        var subj string
62,173✔
6146
        if mset.potentialFilteredConsumers() {
80,203✔
6147
                pmsg := getJSPubMsgFromPool()
18,030✔
6148
                defer pmsg.returnToPool()
18,030✔
6149
                sm, err := mset.store.LoadMsg(seq, &pmsg.StoreMsg)
18,030✔
6150
                if err != nil {
24,059✔
6151
                        if err == ErrStoreEOF {
6,029✔
6152
                                // Register this as a preAck.
×
6153
                                mset.registerPreAck(obs, seq)
×
6154
                                return true
×
6155
                        }
×
6156
                        mset.clearAllPreAcks(seq)
6,029✔
6157
                        return false
6,029✔
6158
                }
6159
                subj = sm.subj
12,001✔
6160
        }
6161
        return mset.checkForInterestWithSubject(seq, subj, obs)
56,144✔
6162
}
6163

6164
// Checks for interest given a sequence and subject.
6165
func (mset *stream) checkForInterestWithSubject(seq uint64, subj string, obs *consumer) bool {
56,194✔
6166
        for _, o := range mset.consumers {
166,357✔
6167
                // If this is us or we have a registered preAck for this consumer continue inspecting.
110,163✔
6168
                if o == obs || mset.hasPreAck(o, seq) {
164,469✔
6169
                        continue
54,306✔
6170
                }
6171
                // Check if we need an ack.
6172
                if o.needAck(seq, subj) {
58,725✔
6173
                        return true
2,868✔
6174
                }
2,868✔
6175
        }
6176
        mset.clearAllPreAcks(seq)
53,326✔
6177
        return false
53,326✔
6178
}
6179

6180
// Check if we have a pre-registered ack for this sequence.
6181
// Write lock should be held.
6182
func (mset *stream) hasPreAck(o *consumer, seq uint64) bool {
55,907✔
6183
        if o == nil || len(mset.preAcks) == 0 {
111,764✔
6184
                return false
55,857✔
6185
        }
55,857✔
6186
        consumers := mset.preAcks[seq]
50✔
6187
        if len(consumers) == 0 {
50✔
6188
                return false
×
6189
        }
×
6190
        _, found := consumers[o]
50✔
6191
        return found
50✔
6192
}
6193

6194
// Check if we have all consumers pre-acked for this sequence and subject.
6195
// Write lock should be held.
6196
func (mset *stream) hasAllPreAcks(seq uint64, subj string) bool {
1,329,780✔
6197
        if len(mset.preAcks) == 0 || len(mset.preAcks[seq]) == 0 {
2,659,510✔
6198
                return false
1,329,730✔
6199
        }
1,329,730✔
6200
        // Since these can be filtered and mutually exclusive,
6201
        // if we have some preAcks we need to check all interest here.
6202
        return mset.noInterestWithSubject(seq, subj, nil)
50✔
6203
}
6204

6205
// Check if we have all consumers pre-acked.
6206
// Write lock should be held.
6207
func (mset *stream) clearAllPreAcks(seq uint64) {
189,089✔
6208
        delete(mset.preAcks, seq)
189,089✔
6209
}
189,089✔
6210

6211
// Clear all preAcks below floor.
6212
// Write lock should be held.
6213
func (mset *stream) clearAllPreAcksBelowFloor(floor uint64) {
1,170✔
6214
        for seq := range mset.preAcks {
1,193✔
6215
                if seq < floor {
26✔
6216
                        delete(mset.preAcks, seq)
3✔
6217
                }
3✔
6218
        }
6219
}
6220

6221
// This will register an ack for a consumer if it arrives before the actual message.
6222
func (mset *stream) registerPreAckLock(o *consumer, seq uint64) {
9✔
6223
        mset.mu.Lock()
9✔
6224
        defer mset.mu.Unlock()
9✔
6225
        mset.registerPreAck(o, seq)
9✔
6226
}
9✔
6227

6228
// This will register an ack for a consumer if it arrives before
6229
// the actual message.
6230
// Write lock should be held.
6231
func (mset *stream) registerPreAck(o *consumer, seq uint64) {
62✔
6232
        if o == nil {
62✔
6233
                return
×
6234
        }
×
6235
        if mset.preAcks == nil {
72✔
6236
                mset.preAcks = make(map[uint64]map[*consumer]struct{})
10✔
6237
        }
10✔
6238
        if mset.preAcks[seq] == nil {
124✔
6239
                mset.preAcks[seq] = make(map[*consumer]struct{})
62✔
6240
        }
62✔
6241
        mset.preAcks[seq][o] = struct{}{}
62✔
6242
}
6243

6244
// This will clear an ack for a consumer.
6245
// Write lock should be held.
6246
func (mset *stream) clearPreAck(o *consumer, seq uint64) {
73,740✔
6247
        if o == nil || len(mset.preAcks) == 0 {
147,477✔
6248
                return
73,737✔
6249
        }
73,737✔
6250
        if consumers := mset.preAcks[seq]; len(consumers) > 0 {
3✔
6251
                delete(consumers, o)
×
6252
                if len(consumers) == 0 {
×
6253
                        delete(mset.preAcks, seq)
×
6254
                }
×
6255
        }
6256
}
6257

6258
// ackMsg is called into from a consumer when we have a WorkQueue or Interest Retention Policy.
6259
// Returns whether the message at seq was removed as a result of the ACK.
6260
// (Or should be removed in the case of clustered streams, since it requires a message delete proposal)
6261
func (mset *stream) ackMsg(o *consumer, seq uint64) bool {
73,825✔
6262
        if seq == 0 {
73,825✔
6263
                return false
×
6264
        }
×
6265

6266
        // Don't make this RLock(). We need to have only 1 running at a time to gauge interest across all consumers.
6267
        mset.mu.Lock()
73,825✔
6268
        if mset.closed.Load() || mset.cfg.Retention == LimitsPolicy {
73,857✔
6269
                mset.mu.Unlock()
32✔
6270
                return false
32✔
6271
        }
32✔
6272

6273
        store := mset.store
73,793✔
6274
        var state StreamState
73,793✔
6275
        store.FastState(&state)
73,793✔
6276

73,793✔
6277
        // If this has arrived before we have processed the message itself.
73,793✔
6278
        if seq > state.LastSeq {
73,846✔
6279
                mset.registerPreAck(o, seq)
53✔
6280
                mset.mu.Unlock()
53✔
6281
                // We have not removed the message, but should still signal so we could retry later
53✔
6282
                // since we potentially need to remove it then.
53✔
6283
                return true
53✔
6284
        }
53✔
6285

6286
        // Always clear pre-ack if here.
6287
        mset.clearPreAck(o, seq)
73,740✔
6288

73,740✔
6289
        // Make sure this sequence is not below our first sequence.
73,740✔
6290
        if seq < state.FirstSeq {
74,551✔
6291
                mset.mu.Unlock()
811✔
6292
                return false
811✔
6293
        }
811✔
6294

6295
        var shouldRemove bool
72,929✔
6296
        switch mset.cfg.Retention {
72,929✔
6297
        case WorkQueuePolicy:
17,654✔
6298
                // Normally we just remove a message when its ack'd here but if we have direct consumers
17,654✔
6299
                // from sources and/or mirrors we need to make sure they have delivered the msg.
17,654✔
6300
                shouldRemove = mset.directs <= 0 || mset.noInterest(seq, o)
17,654✔
6301
        case InterestPolicy:
55,275✔
6302
                shouldRemove = mset.noInterest(seq, o)
55,275✔
6303
        }
6304

6305
        // If nothing else to do.
6306
        if !shouldRemove {
75,462✔
6307
                mset.mu.Unlock()
2,533✔
6308
                return false
2,533✔
6309
        }
2,533✔
6310

6311
        if !mset.isClustered() {
72,210✔
6312
                mset.mu.Unlock()
1,814✔
6313
                // If we are here we should attempt to remove.
1,814✔
6314
                if _, err := store.RemoveMsg(seq); err == ErrStoreEOF {
1,814✔
6315
                        // This should not happen, but being pedantic.
×
6316
                        mset.registerPreAckLock(o, seq)
×
6317
                }
×
6318
                return true
1,814✔
6319
        }
6320

6321
        // Only propose message deletion to the stream if we're consumer leader, otherwise all followers would also propose.
6322
        // We must be the consumer leader, since we know for sure we've stored the message and don't register as pre-ack.
6323
        if o != nil && !o.IsLeader() {
114,432✔
6324
                mset.mu.Unlock()
45,850✔
6325
                // Must still mark as removal if follower. If we become leader later, we must be able to retry the proposal.
45,850✔
6326
                return true
45,850✔
6327
        }
45,850✔
6328

6329
        md := streamMsgDelete{Seq: seq, NoErase: true, Stream: mset.cfg.Name}
22,732✔
6330
        mset.node.ForwardProposal(encodeMsgDelete(&md))
22,732✔
6331
        mset.mu.Unlock()
22,732✔
6332
        return true
22,732✔
6333
}
6334

6335
// Snapshot creates a snapshot for the stream and possibly consumers.
6336
func (mset *stream) snapshot(deadline time.Duration, checkMsgs, includeConsumers bool) (*SnapshotResult, error) {
14✔
6337
        if mset.closed.Load() {
14✔
6338
                return nil, errStreamClosed
×
6339
        }
×
6340
        store := mset.store
14✔
6341
        return store.Snapshot(deadline, checkMsgs, includeConsumers)
14✔
6342
}
6343

6344
const snapsDir = "__snapshots__"
6345

6346
// RestoreStream will restore a stream from a snapshot.
6347
func (a *Account) RestoreStream(ncfg *StreamConfig, r io.Reader) (*stream, error) {
24✔
6348
        if ncfg == nil {
24✔
6349
                return nil, errors.New("nil config on stream restore")
×
6350
        }
×
6351

6352
        s, jsa, err := a.checkForJetStream()
24✔
6353
        if err != nil {
24✔
6354
                return nil, err
×
6355
        }
×
6356
        js := jsa.js
24✔
6357
        if js == nil {
24✔
6358
                return nil, NewJSNotEnabledForAccountError()
×
6359
        }
×
6360

6361
        cfg, apiErr := s.checkStreamCfg(ncfg, a, false)
24✔
6362
        if apiErr != nil {
24✔
6363
                return nil, apiErr
×
6364
        }
×
6365

6366
        sd := filepath.Join(jsa.storeDir, snapsDir)
24✔
6367
        if _, err := os.Stat(sd); os.IsNotExist(err) {
44✔
6368
                if err := os.MkdirAll(sd, defaultDirPerms); err != nil {
20✔
6369
                        return nil, fmt.Errorf("could not create snapshots directory - %v", err)
×
6370
                }
×
6371
        }
6372
        sdir, err := os.MkdirTemp(sd, "snap-")
24✔
6373
        if err != nil {
24✔
6374
                return nil, err
×
6375
        }
×
6376
        if _, err := os.Stat(sdir); os.IsNotExist(err) {
24✔
6377
                if err := os.MkdirAll(sdir, defaultDirPerms); err != nil {
×
6378
                        return nil, fmt.Errorf("could not create snapshots directory - %v", err)
×
6379
                }
×
6380
        }
6381
        defer os.RemoveAll(sdir)
24✔
6382

24✔
6383
        logAndReturnError := func() error {
25✔
6384
                a.mu.RLock()
1✔
6385
                err := fmt.Errorf("unexpected content (account=%s)", a.Name)
1✔
6386
                if a.srv != nil {
2✔
6387
                        a.srv.Errorf("Stream restore failed due to %v", err)
1✔
6388
                }
1✔
6389
                a.mu.RUnlock()
1✔
6390
                return err
1✔
6391
        }
6392
        sdirCheck := filepath.Clean(sdir) + string(os.PathSeparator)
24✔
6393

24✔
6394
        _, isClustered := jsa.jetStreamAndClustered()
24✔
6395
        jsa.usageMu.RLock()
24✔
6396
        selected, tier, hasTier := jsa.selectLimits(cfg.Replicas)
24✔
6397
        jsa.usageMu.RUnlock()
24✔
6398
        reserved := int64(0)
24✔
6399
        if hasTier {
48✔
6400
                if isClustered {
32✔
6401
                        js.mu.RLock()
8✔
6402
                        _, reserved = tieredStreamAndReservationCount(js.cluster.streams[a.Name], tier, &cfg)
8✔
6403
                        js.mu.RUnlock()
8✔
6404
                } else {
24✔
6405
                        reserved = jsa.tieredReservation(tier, &cfg)
16✔
6406
                }
16✔
6407
        }
6408

6409
        var bc int64
24✔
6410
        tr := tar.NewReader(s2.NewReader(r))
24✔
6411
        for {
310✔
6412
                hdr, err := tr.Next()
286✔
6413
                if err == io.EOF {
309✔
6414
                        break // End of snapshot
23✔
6415
                }
6416
                if err != nil {
263✔
6417
                        return nil, err
×
6418
                }
×
6419
                if hdr.Typeflag != tar.TypeReg {
263✔
6420
                        return nil, logAndReturnError()
×
6421
                }
×
6422
                bc += hdr.Size
263✔
6423
                js.mu.RLock()
263✔
6424
                err = js.checkAllLimits(&selected, &cfg, reserved, bc)
263✔
6425
                js.mu.RUnlock()
263✔
6426
                if err != nil {
263✔
6427
                        return nil, err
×
6428
                }
×
6429
                fpath := filepath.Join(sdir, filepath.Clean(hdr.Name))
263✔
6430
                if !strings.HasPrefix(fpath, sdirCheck) {
264✔
6431
                        return nil, logAndReturnError()
1✔
6432
                }
1✔
6433
                os.MkdirAll(filepath.Dir(fpath), defaultDirPerms)
262✔
6434
                fd, err := os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0600)
262✔
6435
                if err != nil {
262✔
6436
                        return nil, err
×
6437
                }
×
6438
                _, err = io.Copy(fd, tr)
262✔
6439
                fd.Close()
262✔
6440
                if err != nil {
262✔
6441
                        return nil, err
×
6442
                }
×
6443
        }
6444

6445
        // Check metadata.
6446
        // The cfg passed in will be the new identity for the stream.
6447
        var fcfg FileStreamInfo
23✔
6448
        b, err := os.ReadFile(filepath.Join(sdir, JetStreamMetaFile))
23✔
6449
        if err != nil {
23✔
6450
                return nil, err
×
6451
        }
×
6452
        if err := json.Unmarshal(b, &fcfg); err != nil {
23✔
6453
                return nil, err
×
6454
        }
×
6455

6456
        // Check to make sure names match.
6457
        if fcfg.Name != cfg.Name {
24✔
6458
                return nil, errors.New("stream names do not match")
1✔
6459
        }
1✔
6460

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

6480
        if cfg.Template != _EMPTY_ {
21✔
6481
                if err := jsa.addStreamNameToTemplate(cfg.Template, cfg.Name); err != nil {
×
6482
                        return nil, err
×
6483
                }
×
6484
        }
6485
        mset, err := a.addStream(&cfg)
21✔
6486
        if err != nil {
22✔
6487
                // Make sure to clean up after ourselves here.
1✔
6488
                os.RemoveAll(ndir)
1✔
6489
                return nil, err
1✔
6490
        }
1✔
6491
        if !fcfg.Created.IsZero() {
38✔
6492
                mset.setCreatedTime(fcfg.Created)
18✔
6493
        }
18✔
6494

6495
        // Make sure we do an update if the configs have changed.
6496
        if !reflect.DeepEqual(fcfg.StreamConfig, cfg) {
25✔
6497
                if err := mset.update(&cfg); err != nil {
5✔
6498
                        return nil, err
×
6499
                }
×
6500
        }
6501

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

6554
// This is to check for dangling messages on interest retention streams. Only called on account enable.
6555
// Issue https://github.com/nats-io/nats-server/issues/3612
6556
func (mset *stream) checkForOrphanMsgs() {
50✔
6557
        mset.mu.RLock()
50✔
6558
        consumers := make([]*consumer, 0, len(mset.consumers))
50✔
6559
        for _, o := range mset.consumers {
64✔
6560
                consumers = append(consumers, o)
14✔
6561
        }
14✔
6562
        accName, stream := mset.acc.Name, mset.cfg.Name
50✔
6563

50✔
6564
        var ss StreamState
50✔
6565
        mset.store.FastState(&ss)
50✔
6566
        mset.mu.RUnlock()
50✔
6567

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

6582
// Check on startup to make sure that consumers replication matches us.
6583
// Interest retention requires replication matches.
6584
func (mset *stream) checkConsumerReplication() {
50✔
6585
        mset.mu.RLock()
50✔
6586
        defer mset.mu.RUnlock()
50✔
6587

50✔
6588
        if mset.cfg.Retention != InterestPolicy {
50✔
6589
                return
×
6590
        }
×
6591

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

6605
// Will check if we are running in the monitor already and if not set the appropriate flag.
6606
func (mset *stream) checkInMonitor() bool {
3,035✔
6607
        mset.mu.Lock()
3,035✔
6608
        defer mset.mu.Unlock()
3,035✔
6609

3,035✔
6610
        if mset.inMonitor {
3,035✔
6611
                return true
×
6612
        }
×
6613
        mset.inMonitor = true
3,035✔
6614
        return false
3,035✔
6615
}
6616

6617
// Clear us being in the monitor routine.
6618
func (mset *stream) clearMonitorRunning() {
3,035✔
6619
        mset.mu.Lock()
3,035✔
6620
        defer mset.mu.Unlock()
3,035✔
6621
        mset.inMonitor = false
3,035✔
6622
}
3,035✔
6623

6624
// Check if our monitor is running.
6625
func (mset *stream) isMonitorRunning() bool {
830✔
6626
        mset.mu.RLock()
830✔
6627
        defer mset.mu.RUnlock()
830✔
6628
        return mset.inMonitor
830✔
6629
}
830✔
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