github.com/nats-io/nats-server/v2@v2.11.0-preview.2/server/jetstream_api.go (about)

     1  // Copyright 2020-2023 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  	"bytes"
    18  	"encoding/json"
    19  	"errors"
    20  	"fmt"
    21  	"math/rand"
    22  	"os"
    23  	"path/filepath"
    24  	"runtime"
    25  	"sort"
    26  	"strconv"
    27  	"strings"
    28  	"sync/atomic"
    29  	"time"
    30  	"unicode"
    31  
    32  	"github.com/nats-io/nuid"
    33  )
    34  
    35  // Request API subjects for JetStream.
    36  const (
    37  	// All API endpoints.
    38  	jsAllAPI = "$JS.API.>"
    39  
    40  	// For constructing JetStream domain prefixes.
    41  	jsDomainAPI = "$JS.%s.API.>"
    42  
    43  	JSApiPrefix = "$JS.API"
    44  
    45  	// JSApiAccountInfo is for obtaining general information about JetStream for this account.
    46  	// Will return JSON response.
    47  	JSApiAccountInfo = "$JS.API.INFO"
    48  
    49  	// JSApiTemplateCreate is the endpoint to create new stream templates.
    50  	// Will return JSON response.
    51  	JSApiTemplateCreate  = "$JS.API.STREAM.TEMPLATE.CREATE.*"
    52  	JSApiTemplateCreateT = "$JS.API.STREAM.TEMPLATE.CREATE.%s"
    53  
    54  	// JSApiTemplates is the endpoint to list all stream template names for this account.
    55  	// Will return JSON response.
    56  	JSApiTemplates = "$JS.API.STREAM.TEMPLATE.NAMES"
    57  
    58  	// JSApiTemplateInfo is for obtaining general information about a named stream template.
    59  	// Will return JSON response.
    60  	JSApiTemplateInfo  = "$JS.API.STREAM.TEMPLATE.INFO.*"
    61  	JSApiTemplateInfoT = "$JS.API.STREAM.TEMPLATE.INFO.%s"
    62  
    63  	// JSApiTemplateDelete is the endpoint to delete stream templates.
    64  	// Will return JSON response.
    65  	JSApiTemplateDelete  = "$JS.API.STREAM.TEMPLATE.DELETE.*"
    66  	JSApiTemplateDeleteT = "$JS.API.STREAM.TEMPLATE.DELETE.%s"
    67  
    68  	// JSApiStreamCreate is the endpoint to create new streams.
    69  	// Will return JSON response.
    70  	JSApiStreamCreate  = "$JS.API.STREAM.CREATE.*"
    71  	JSApiStreamCreateT = "$JS.API.STREAM.CREATE.%s"
    72  
    73  	// JSApiStreamUpdate is the endpoint to update existing streams.
    74  	// Will return JSON response.
    75  	JSApiStreamUpdate  = "$JS.API.STREAM.UPDATE.*"
    76  	JSApiStreamUpdateT = "$JS.API.STREAM.UPDATE.%s"
    77  
    78  	// JSApiStreams is the endpoint to list all stream names for this account.
    79  	// Will return JSON response.
    80  	JSApiStreams = "$JS.API.STREAM.NAMES"
    81  	// JSApiStreamList is the endpoint that will return all detailed stream information
    82  	JSApiStreamList = "$JS.API.STREAM.LIST"
    83  
    84  	// JSApiStreamInfo is for obtaining general information about a named stream.
    85  	// Will return JSON response.
    86  	JSApiStreamInfo  = "$JS.API.STREAM.INFO.*"
    87  	JSApiStreamInfoT = "$JS.API.STREAM.INFO.%s"
    88  
    89  	// JSApiStreamDelete is the endpoint to delete streams.
    90  	// Will return JSON response.
    91  	JSApiStreamDelete  = "$JS.API.STREAM.DELETE.*"
    92  	JSApiStreamDeleteT = "$JS.API.STREAM.DELETE.%s"
    93  
    94  	// JSApiStreamPurge is the endpoint to purge streams.
    95  	// Will return JSON response.
    96  	JSApiStreamPurge  = "$JS.API.STREAM.PURGE.*"
    97  	JSApiStreamPurgeT = "$JS.API.STREAM.PURGE.%s"
    98  
    99  	// JSApiStreamSnapshot is the endpoint to snapshot streams.
   100  	// Will return a stream of chunks with a nil chunk as EOF to
   101  	// the deliver subject. Caller should respond to each chunk
   102  	// with a nil body response for ack flow.
   103  	JSApiStreamSnapshot  = "$JS.API.STREAM.SNAPSHOT.*"
   104  	JSApiStreamSnapshotT = "$JS.API.STREAM.SNAPSHOT.%s"
   105  
   106  	// JSApiStreamRestore is the endpoint to restore a stream from a snapshot.
   107  	// Caller should respond to each chunk with a nil body response.
   108  	JSApiStreamRestore  = "$JS.API.STREAM.RESTORE.*"
   109  	JSApiStreamRestoreT = "$JS.API.STREAM.RESTORE.%s"
   110  
   111  	// JSApiMsgDelete is the endpoint to delete messages from a stream.
   112  	// Will return JSON response.
   113  	JSApiMsgDelete  = "$JS.API.STREAM.MSG.DELETE.*"
   114  	JSApiMsgDeleteT = "$JS.API.STREAM.MSG.DELETE.%s"
   115  
   116  	// JSApiMsgGet is the template for direct requests for a message by its stream sequence number.
   117  	// Will return JSON response.
   118  	JSApiMsgGet  = "$JS.API.STREAM.MSG.GET.*"
   119  	JSApiMsgGetT = "$JS.API.STREAM.MSG.GET.%s"
   120  
   121  	// JSDirectMsgGet is the template for non-api layer direct requests for a message by its stream sequence number or last by subject.
   122  	// Will return the message similar to how a consumer receives the message, no JSON processing.
   123  	// If the message can not be found we will use a status header of 404. If the stream does not exist the client will get a no-responders or timeout.
   124  	JSDirectMsgGet  = "$JS.API.DIRECT.GET.*"
   125  	JSDirectMsgGetT = "$JS.API.DIRECT.GET.%s"
   126  
   127  	// This is a direct version of get last by subject, which will be the dominant pattern for KV access once 2.9 is released.
   128  	// The stream and the key will be part of the subject to allow for no-marshal payloads and subject based security permissions.
   129  	JSDirectGetLastBySubject  = "$JS.API.DIRECT.GET.*.>"
   130  	JSDirectGetLastBySubjectT = "$JS.API.DIRECT.GET.%s.%s"
   131  
   132  	// jsDirectGetPre
   133  	jsDirectGetPre = "$JS.API.DIRECT.GET"
   134  
   135  	// JSApiConsumerCreate is the endpoint to create consumers for streams.
   136  	// This was also the legacy endpoint for ephemeral consumers.
   137  	// It now can take consumer name and optional filter subject, which when part of the subject controls access.
   138  	// Will return JSON response.
   139  	JSApiConsumerCreate    = "$JS.API.CONSUMER.CREATE.*"
   140  	JSApiConsumerCreateT   = "$JS.API.CONSUMER.CREATE.%s"
   141  	JSApiConsumerCreateEx  = "$JS.API.CONSUMER.CREATE.*.>"
   142  	JSApiConsumerCreateExT = "$JS.API.CONSUMER.CREATE.%s.%s.%s"
   143  
   144  	// JSApiDurableCreate is the endpoint to create durable consumers for streams.
   145  	// You need to include the stream and consumer name in the subject.
   146  	JSApiDurableCreate  = "$JS.API.CONSUMER.DURABLE.CREATE.*.*"
   147  	JSApiDurableCreateT = "$JS.API.CONSUMER.DURABLE.CREATE.%s.%s"
   148  
   149  	// JSApiConsumers is the endpoint to list all consumer names for the stream.
   150  	// Will return JSON response.
   151  	JSApiConsumers  = "$JS.API.CONSUMER.NAMES.*"
   152  	JSApiConsumersT = "$JS.API.CONSUMER.NAMES.%s"
   153  
   154  	// JSApiConsumerList is the endpoint that will return all detailed consumer information
   155  	JSApiConsumerList  = "$JS.API.CONSUMER.LIST.*"
   156  	JSApiConsumerListT = "$JS.API.CONSUMER.LIST.%s"
   157  
   158  	// JSApiConsumerInfo is for obtaining general information about a consumer.
   159  	// Will return JSON response.
   160  	JSApiConsumerInfo  = "$JS.API.CONSUMER.INFO.*.*"
   161  	JSApiConsumerInfoT = "$JS.API.CONSUMER.INFO.%s.%s"
   162  
   163  	// JSApiConsumerDelete is the endpoint to delete consumers.
   164  	// Will return JSON response.
   165  	JSApiConsumerDelete  = "$JS.API.CONSUMER.DELETE.*.*"
   166  	JSApiConsumerDeleteT = "$JS.API.CONSUMER.DELETE.%s.%s"
   167  
   168  	// JSApiConsumerPause is the endpoint to pause or unpause consumers.
   169  	// Will return JSON response.
   170  	JSApiConsumerPause  = "$JS.API.CONSUMER.PAUSE.*.*"
   171  	JSApiConsumerPauseT = "$JS.API.CONSUMER.PAUSE.%s.%s"
   172  
   173  	// JSApiRequestNextT is the prefix for the request next message(s) for a consumer in worker/pull mode.
   174  	JSApiRequestNextT = "$JS.API.CONSUMER.MSG.NEXT.%s.%s"
   175  
   176  	// jsRequestNextPre
   177  	jsRequestNextPre = "$JS.API.CONSUMER.MSG.NEXT."
   178  
   179  	// For snapshots and restores. The ack will have additional tokens.
   180  	jsSnapshotAckT    = "$JS.SNAPSHOT.ACK.%s.%s"
   181  	jsRestoreDeliverT = "$JS.SNAPSHOT.RESTORE.%s.%s"
   182  
   183  	// JSApiStreamRemovePeer is the endpoint to remove a peer from a clustered stream and its consumers.
   184  	// Will return JSON response.
   185  	JSApiStreamRemovePeer  = "$JS.API.STREAM.PEER.REMOVE.*"
   186  	JSApiStreamRemovePeerT = "$JS.API.STREAM.PEER.REMOVE.%s"
   187  
   188  	// JSApiStreamLeaderStepDown is the endpoint to have stream leader stepdown.
   189  	// Will return JSON response.
   190  	JSApiStreamLeaderStepDown  = "$JS.API.STREAM.LEADER.STEPDOWN.*"
   191  	JSApiStreamLeaderStepDownT = "$JS.API.STREAM.LEADER.STEPDOWN.%s"
   192  
   193  	// JSApiConsumerLeaderStepDown is the endpoint to have consumer leader stepdown.
   194  	// Will return JSON response.
   195  	JSApiConsumerLeaderStepDown  = "$JS.API.CONSUMER.LEADER.STEPDOWN.*.*"
   196  	JSApiConsumerLeaderStepDownT = "$JS.API.CONSUMER.LEADER.STEPDOWN.%s.%s"
   197  
   198  	// JSApiLeaderStepDown is the endpoint to have our metaleader stepdown.
   199  	// Only works from system account.
   200  	// Will return JSON response.
   201  	JSApiLeaderStepDown = "$JS.API.META.LEADER.STEPDOWN"
   202  
   203  	// JSApiRemoveServer is the endpoint to remove a peer server from the cluster.
   204  	// Only works from system account.
   205  	// Will return JSON response.
   206  	JSApiRemoveServer = "$JS.API.SERVER.REMOVE"
   207  
   208  	// JSApiAccountPurge is the endpoint to purge the js content of an account
   209  	// Only works from system account.
   210  	// Will return JSON response.
   211  	JSApiAccountPurge  = "$JS.API.ACCOUNT.PURGE.*"
   212  	JSApiAccountPurgeT = "$JS.API.ACCOUNT.PURGE.%s"
   213  
   214  	// JSApiServerStreamMove is the endpoint to move streams off a server
   215  	// Only works from system account.
   216  	// Will return JSON response.
   217  	JSApiServerStreamMove  = "$JS.API.ACCOUNT.STREAM.MOVE.*.*"
   218  	JSApiServerStreamMoveT = "$JS.API.ACCOUNT.STREAM.MOVE.%s.%s"
   219  
   220  	// JSApiServerStreamCancelMove is the endpoint to cancel a stream move
   221  	// Only works from system account.
   222  	// Will return JSON response.
   223  	JSApiServerStreamCancelMove  = "$JS.API.ACCOUNT.STREAM.CANCEL_MOVE.*.*"
   224  	JSApiServerStreamCancelMoveT = "$JS.API.ACCOUNT.STREAM.CANCEL_MOVE.%s.%s"
   225  
   226  	// The prefix for system level account API.
   227  	jsAPIAccountPre = "$JS.API.ACCOUNT."
   228  
   229  	// jsAckT is the template for the ack message stream coming back from a consumer
   230  	// when they ACK/NAK, etc a message.
   231  	jsAckT      = "$JS.ACK.%s.%s"
   232  	jsAckPre    = "$JS.ACK."
   233  	jsAckPreLen = len(jsAckPre)
   234  
   235  	// jsFlowControl is for flow control subjects.
   236  	jsFlowControlPre = "$JS.FC."
   237  	// jsFlowControl is for FC responses.
   238  	jsFlowControl = "$JS.FC.%s.%s.*"
   239  
   240  	// JSAdvisoryPrefix is a prefix for all JetStream advisories.
   241  	JSAdvisoryPrefix = "$JS.EVENT.ADVISORY"
   242  
   243  	// JSMetricPrefix is a prefix for all JetStream metrics.
   244  	JSMetricPrefix = "$JS.EVENT.METRIC"
   245  
   246  	// JSMetricConsumerAckPre is a metric containing ack latency.
   247  	JSMetricConsumerAckPre = "$JS.EVENT.METRIC.CONSUMER.ACK"
   248  
   249  	// JSAdvisoryConsumerMaxDeliveryExceedPre is a notification published when a message exceeds its delivery threshold.
   250  	JSAdvisoryConsumerMaxDeliveryExceedPre = "$JS.EVENT.ADVISORY.CONSUMER.MAX_DELIVERIES"
   251  
   252  	// JSAdvisoryConsumerMsgNakPre is a notification published when a message has been naked
   253  	JSAdvisoryConsumerMsgNakPre = "$JS.EVENT.ADVISORY.CONSUMER.MSG_NAKED"
   254  
   255  	// JSAdvisoryConsumerMsgTerminatedPre is a notification published when a message has been terminated.
   256  	JSAdvisoryConsumerMsgTerminatedPre = "$JS.EVENT.ADVISORY.CONSUMER.MSG_TERMINATED"
   257  
   258  	// JSAdvisoryStreamCreatedPre notification that a stream was created.
   259  	JSAdvisoryStreamCreatedPre = "$JS.EVENT.ADVISORY.STREAM.CREATED"
   260  
   261  	// JSAdvisoryStreamDeletedPre notification that a stream was deleted.
   262  	JSAdvisoryStreamDeletedPre = "$JS.EVENT.ADVISORY.STREAM.DELETED"
   263  
   264  	// JSAdvisoryStreamUpdatedPre notification that a stream was updated.
   265  	JSAdvisoryStreamUpdatedPre = "$JS.EVENT.ADVISORY.STREAM.UPDATED"
   266  
   267  	// JSAdvisoryConsumerCreatedPre notification that a template created.
   268  	JSAdvisoryConsumerCreatedPre = "$JS.EVENT.ADVISORY.CONSUMER.CREATED"
   269  
   270  	// JSAdvisoryConsumerDeletedPre notification that a template deleted.
   271  	JSAdvisoryConsumerDeletedPre = "$JS.EVENT.ADVISORY.CONSUMER.DELETED"
   272  
   273  	// JSAdvisoryConsumerPausePre notification that a consumer paused/unpaused.
   274  	JSAdvisoryConsumerPausePre = "$JS.EVENT.ADVISORY.CONSUMER.PAUSE"
   275  
   276  	// JSAdvisoryStreamSnapshotCreatePre notification that a snapshot was created.
   277  	JSAdvisoryStreamSnapshotCreatePre = "$JS.EVENT.ADVISORY.STREAM.SNAPSHOT_CREATE"
   278  
   279  	// JSAdvisoryStreamSnapshotCompletePre notification that a snapshot was completed.
   280  	JSAdvisoryStreamSnapshotCompletePre = "$JS.EVENT.ADVISORY.STREAM.SNAPSHOT_COMPLETE"
   281  
   282  	// JSAdvisoryStreamRestoreCreatePre notification that a restore was start.
   283  	JSAdvisoryStreamRestoreCreatePre = "$JS.EVENT.ADVISORY.STREAM.RESTORE_CREATE"
   284  
   285  	// JSAdvisoryStreamRestoreCompletePre notification that a restore was completed.
   286  	JSAdvisoryStreamRestoreCompletePre = "$JS.EVENT.ADVISORY.STREAM.RESTORE_COMPLETE"
   287  
   288  	// JSAdvisoryDomainLeaderElectedPre notification that a jetstream domain has elected a leader.
   289  	JSAdvisoryDomainLeaderElected = "$JS.EVENT.ADVISORY.DOMAIN.LEADER_ELECTED"
   290  
   291  	// JSAdvisoryStreamLeaderElectedPre notification that a replicated stream has elected a leader.
   292  	JSAdvisoryStreamLeaderElectedPre = "$JS.EVENT.ADVISORY.STREAM.LEADER_ELECTED"
   293  
   294  	// JSAdvisoryStreamQuorumLostPre notification that a stream and its consumers are stalled.
   295  	JSAdvisoryStreamQuorumLostPre = "$JS.EVENT.ADVISORY.STREAM.QUORUM_LOST"
   296  
   297  	// JSAdvisoryConsumerLeaderElectedPre notification that a replicated consumer has elected a leader.
   298  	JSAdvisoryConsumerLeaderElectedPre = "$JS.EVENT.ADVISORY.CONSUMER.LEADER_ELECTED"
   299  
   300  	// JSAdvisoryConsumerQuorumLostPre notification that a consumer is stalled.
   301  	JSAdvisoryConsumerQuorumLostPre = "$JS.EVENT.ADVISORY.CONSUMER.QUORUM_LOST"
   302  
   303  	// JSAdvisoryServerOutOfStorage notification that a server has no more storage.
   304  	JSAdvisoryServerOutOfStorage = "$JS.EVENT.ADVISORY.SERVER.OUT_OF_STORAGE"
   305  
   306  	// JSAdvisoryServerRemoved notification that a server has been removed from the system.
   307  	JSAdvisoryServerRemoved = "$JS.EVENT.ADVISORY.SERVER.REMOVED"
   308  
   309  	// JSAuditAdvisory is a notification about JetStream API access.
   310  	// FIXME - Add in details about who..
   311  	JSAuditAdvisory = "$JS.EVENT.ADVISORY.API"
   312  )
   313  
   314  var denyAllClientJs = []string{jsAllAPI, "$KV.>", "$OBJ.>"}
   315  var denyAllJs = []string{jscAllSubj, raftAllSubj, jsAllAPI, "$KV.>", "$OBJ.>"}
   316  
   317  func generateJSMappingTable(domain string) map[string]string {
   318  	mappings := map[string]string{}
   319  	// This set of mappings is very very very ugly.
   320  	// It is a consequence of what we defined the domain prefix to be "$JS.domain.API" and it's mapping to "$JS.API"
   321  	// For optics $KV and $OBJ where made to be independent subject spaces.
   322  	// As materialized views of JS, they did not simply extend that subject space to say "$JS.API.KV" "$JS.API.OBJ"
   323  	// This is very unfortunate!!!
   324  	// Furthermore, it seemed bad to require different domain prefixes for JS/KV/OBJ.
   325  	// Especially since the actual API for say KV, does use stream create from JS.
   326  	// To avoid overlaps KV and OBJ views append the prefix to their API.
   327  	// (Replacing $KV with the prefix allows users to create collisions with say the bucket name)
   328  	// This mapping therefore needs to have extra token so that the mapping can properly discern between $JS, $KV, $OBJ
   329  	for srcMappingSuffix, to := range map[string]string{
   330  		"INFO":       JSApiAccountInfo,
   331  		"STREAM.>":   "$JS.API.STREAM.>",
   332  		"CONSUMER.>": "$JS.API.CONSUMER.>",
   333  		"DIRECT.>":   "$JS.API.DIRECT.>",
   334  		"META.>":     "$JS.API.META.>",
   335  		"SERVER.>":   "$JS.API.SERVER.>",
   336  		"ACCOUNT.>":  "$JS.API.ACCOUNT.>",
   337  		"$KV.>":      "$KV.>",
   338  		"$OBJ.>":     "$OBJ.>",
   339  	} {
   340  		mappings[fmt.Sprintf("$JS.%s.API.%s", domain, srcMappingSuffix)] = to
   341  	}
   342  	return mappings
   343  }
   344  
   345  // JSMaxDescription is the maximum description length for streams and consumers.
   346  const JSMaxDescriptionLen = 4 * 1024
   347  
   348  // JSMaxMetadataLen is the maximum length for streams and consumers metadata map.
   349  // It's calculated by summing length of all keys and values.
   350  const JSMaxMetadataLen = 128 * 1024
   351  
   352  // JSMaxNameLen is the maximum name lengths for streams, consumers and templates.
   353  // Picked 255 as it seems to be a widely used file name limit
   354  const JSMaxNameLen = 255
   355  
   356  // Responses for API calls.
   357  
   358  // ApiResponse is a standard response from the JetStream JSON API
   359  type ApiResponse struct {
   360  	Type  string    `json:"type"`
   361  	Error *ApiError `json:"error,omitempty"`
   362  }
   363  
   364  const JSApiSystemResponseType = "io.nats.jetstream.api.v1.system_response"
   365  
   366  // When passing back to the clients generalize store failures.
   367  var (
   368  	errStreamStoreFailed   = errors.New("error creating store for stream")
   369  	errConsumerStoreFailed = errors.New("error creating store for consumer")
   370  )
   371  
   372  // ToError checks if the response has a error and if it does converts it to an error avoiding
   373  // the pitfalls described by https://yourbasic.org/golang/gotcha-why-nil-error-not-equal-nil/
   374  func (r *ApiResponse) ToError() error {
   375  	if r.Error == nil {
   376  		return nil
   377  	}
   378  
   379  	return r.Error
   380  }
   381  
   382  const JSApiOverloadedType = "io.nats.jetstream.api.v1.system_overloaded"
   383  
   384  // ApiPaged includes variables used to create paged responses from the JSON API
   385  type ApiPaged struct {
   386  	Total  int `json:"total"`
   387  	Offset int `json:"offset"`
   388  	Limit  int `json:"limit"`
   389  }
   390  
   391  // ApiPagedRequest includes parameters allowing specific pages to be requests from APIs responding with ApiPaged
   392  type ApiPagedRequest struct {
   393  	Offset int `json:"offset"`
   394  }
   395  
   396  // JSApiAccountInfoResponse reports back information on jetstream for this account.
   397  type JSApiAccountInfoResponse struct {
   398  	ApiResponse
   399  	*JetStreamAccountStats
   400  }
   401  
   402  const JSApiAccountInfoResponseType = "io.nats.jetstream.api.v1.account_info_response"
   403  
   404  // JSApiStreamCreateResponse stream creation.
   405  type JSApiStreamCreateResponse struct {
   406  	ApiResponse
   407  	*StreamInfo
   408  	DidCreate bool `json:"did_create,omitempty"`
   409  }
   410  
   411  const JSApiStreamCreateResponseType = "io.nats.jetstream.api.v1.stream_create_response"
   412  
   413  // JSApiStreamDeleteResponse stream removal.
   414  type JSApiStreamDeleteResponse struct {
   415  	ApiResponse
   416  	Success bool `json:"success,omitempty"`
   417  }
   418  
   419  const JSApiStreamDeleteResponseType = "io.nats.jetstream.api.v1.stream_delete_response"
   420  
   421  // JSMaxSubjectDetails The limit of the number of subject details we will send in a stream info response.
   422  const JSMaxSubjectDetails = 100_000
   423  
   424  type JSApiStreamInfoRequest struct {
   425  	ApiPagedRequest
   426  	DeletedDetails bool   `json:"deleted_details,omitempty"`
   427  	SubjectsFilter string `json:"subjects_filter,omitempty"`
   428  }
   429  
   430  type JSApiStreamInfoResponse struct {
   431  	ApiResponse
   432  	ApiPaged
   433  	*StreamInfo
   434  }
   435  
   436  const JSApiStreamInfoResponseType = "io.nats.jetstream.api.v1.stream_info_response"
   437  
   438  // JSApiNamesLimit is the maximum entries we will return for streams or consumers lists.
   439  // TODO(dlc) - with header or request support could request chunked response.
   440  const JSApiNamesLimit = 1024
   441  const JSApiListLimit = 256
   442  
   443  type JSApiStreamNamesRequest struct {
   444  	ApiPagedRequest
   445  	// These are filters that can be applied to the list.
   446  	Subject string `json:"subject,omitempty"`
   447  }
   448  
   449  // JSApiStreamNamesResponse list of streams.
   450  // A nil request is valid and means all streams.
   451  type JSApiStreamNamesResponse struct {
   452  	ApiResponse
   453  	ApiPaged
   454  	Streams []string `json:"streams"`
   455  }
   456  
   457  const JSApiStreamNamesResponseType = "io.nats.jetstream.api.v1.stream_names_response"
   458  
   459  type JSApiStreamListRequest struct {
   460  	ApiPagedRequest
   461  	// These are filters that can be applied to the list.
   462  	Subject string `json:"subject,omitempty"`
   463  }
   464  
   465  // JSApiStreamListResponse list of detailed stream information.
   466  // A nil request is valid and means all streams.
   467  type JSApiStreamListResponse struct {
   468  	ApiResponse
   469  	ApiPaged
   470  	Streams []*StreamInfo `json:"streams"`
   471  	Missing []string      `json:"missing,omitempty"`
   472  }
   473  
   474  const JSApiStreamListResponseType = "io.nats.jetstream.api.v1.stream_list_response"
   475  
   476  // JSApiStreamPurgeRequest is optional request information to the purge API.
   477  // Subject will filter the purge request to only messages that match the subject, which can have wildcards.
   478  // Sequence will purge up to but not including this sequence and can be combined with subject filtering.
   479  // Keep will specify how many messages to keep. This can also be combined with subject filtering.
   480  // Note that Sequence and Keep are mutually exclusive, so both can not be set at the same time.
   481  type JSApiStreamPurgeRequest struct {
   482  	// Purge up to but not including sequence.
   483  	Sequence uint64 `json:"seq,omitempty"`
   484  	// Subject to match against messages for the purge command.
   485  	Subject string `json:"filter,omitempty"`
   486  	// Number of messages to keep.
   487  	Keep uint64 `json:"keep,omitempty"`
   488  }
   489  
   490  type JSApiStreamPurgeResponse struct {
   491  	ApiResponse
   492  	Success bool   `json:"success,omitempty"`
   493  	Purged  uint64 `json:"purged"`
   494  }
   495  
   496  const JSApiStreamPurgeResponseType = "io.nats.jetstream.api.v1.stream_purge_response"
   497  
   498  // JSApiStreamUpdateResponse for updating a stream.
   499  type JSApiStreamUpdateResponse struct {
   500  	ApiResponse
   501  	*StreamInfo
   502  }
   503  
   504  const JSApiStreamUpdateResponseType = "io.nats.jetstream.api.v1.stream_update_response"
   505  
   506  // JSApiMsgDeleteRequest delete message request.
   507  type JSApiMsgDeleteRequest struct {
   508  	Seq     uint64 `json:"seq"`
   509  	NoErase bool   `json:"no_erase,omitempty"`
   510  }
   511  
   512  type JSApiMsgDeleteResponse struct {
   513  	ApiResponse
   514  	Success bool `json:"success,omitempty"`
   515  }
   516  
   517  const JSApiMsgDeleteResponseType = "io.nats.jetstream.api.v1.stream_msg_delete_response"
   518  
   519  type JSApiStreamSnapshotRequest struct {
   520  	// Subject to deliver the chunks to for the snapshot.
   521  	DeliverSubject string `json:"deliver_subject"`
   522  	// Do not include consumers in the snapshot.
   523  	NoConsumers bool `json:"no_consumers,omitempty"`
   524  	// Optional chunk size preference.
   525  	// Best to just let server select.
   526  	ChunkSize int `json:"chunk_size,omitempty"`
   527  	// Check all message's checksums prior to snapshot.
   528  	CheckMsgs bool `json:"jsck,omitempty"`
   529  }
   530  
   531  // JSApiStreamSnapshotResponse is the direct response to the snapshot request.
   532  type JSApiStreamSnapshotResponse struct {
   533  	ApiResponse
   534  	// Configuration of the given stream.
   535  	Config *StreamConfig `json:"config,omitempty"`
   536  	// Current State for the given stream.
   537  	State *StreamState `json:"state,omitempty"`
   538  }
   539  
   540  const JSApiStreamSnapshotResponseType = "io.nats.jetstream.api.v1.stream_snapshot_response"
   541  
   542  // JSApiStreamRestoreRequest is the required restore request.
   543  type JSApiStreamRestoreRequest struct {
   544  	// Configuration of the given stream.
   545  	Config StreamConfig `json:"config"`
   546  	// Current State for the given stream.
   547  	State StreamState `json:"state"`
   548  }
   549  
   550  // JSApiStreamRestoreResponse is the direct response to the restore request.
   551  type JSApiStreamRestoreResponse struct {
   552  	ApiResponse
   553  	// Subject to deliver the chunks to for the snapshot restore.
   554  	DeliverSubject string `json:"deliver_subject"`
   555  }
   556  
   557  const JSApiStreamRestoreResponseType = "io.nats.jetstream.api.v1.stream_restore_response"
   558  
   559  // JSApiStreamRemovePeerRequest is the required remove peer request.
   560  type JSApiStreamRemovePeerRequest struct {
   561  	// Server name of the peer to be removed.
   562  	Peer string `json:"peer"`
   563  }
   564  
   565  // JSApiStreamRemovePeerResponse is the response to a remove peer request.
   566  type JSApiStreamRemovePeerResponse struct {
   567  	ApiResponse
   568  	Success bool `json:"success,omitempty"`
   569  }
   570  
   571  const JSApiStreamRemovePeerResponseType = "io.nats.jetstream.api.v1.stream_remove_peer_response"
   572  
   573  // JSApiStreamLeaderStepDownResponse is the response to a leader stepdown request.
   574  type JSApiStreamLeaderStepDownResponse struct {
   575  	ApiResponse
   576  	Success bool `json:"success,omitempty"`
   577  }
   578  
   579  const JSApiStreamLeaderStepDownResponseType = "io.nats.jetstream.api.v1.stream_leader_stepdown_response"
   580  
   581  // JSApiConsumerLeaderStepDownResponse is the response to a consumer leader stepdown request.
   582  type JSApiConsumerLeaderStepDownResponse struct {
   583  	ApiResponse
   584  	Success bool `json:"success,omitempty"`
   585  }
   586  
   587  const JSApiConsumerLeaderStepDownResponseType = "io.nats.jetstream.api.v1.consumer_leader_stepdown_response"
   588  
   589  // JSApiLeaderStepdownRequest allows placement control over the meta leader placement.
   590  type JSApiLeaderStepdownRequest struct {
   591  	Placement *Placement `json:"placement,omitempty"`
   592  }
   593  
   594  // JSApiLeaderStepDownResponse is the response to a meta leader stepdown request.
   595  type JSApiLeaderStepDownResponse struct {
   596  	ApiResponse
   597  	Success bool `json:"success,omitempty"`
   598  }
   599  
   600  const JSApiLeaderStepDownResponseType = "io.nats.jetstream.api.v1.meta_leader_stepdown_response"
   601  
   602  // JSApiMetaServerRemoveRequest will remove a peer from the meta group.
   603  type JSApiMetaServerRemoveRequest struct {
   604  	// Server name of the peer to be removed.
   605  	Server string `json:"peer"`
   606  	// Peer ID of the peer to be removed. If specified this is used
   607  	// instead of the server name.
   608  	Peer string `json:"peer_id,omitempty"`
   609  }
   610  
   611  // JSApiMetaServerRemoveResponse is the response to a peer removal request in the meta group.
   612  type JSApiMetaServerRemoveResponse struct {
   613  	ApiResponse
   614  	Success bool `json:"success,omitempty"`
   615  }
   616  
   617  const JSApiMetaServerRemoveResponseType = "io.nats.jetstream.api.v1.meta_server_remove_response"
   618  
   619  // JSApiMetaServerStreamMoveRequest will move a stream on a server to another
   620  // response to this will come as JSApiStreamUpdateResponse/JSApiStreamUpdateResponseType
   621  type JSApiMetaServerStreamMoveRequest struct {
   622  	// Server name of the peer to be evacuated.
   623  	Server string `json:"server,omitempty"`
   624  	// Cluster the server is in
   625  	Cluster string `json:"cluster,omitempty"`
   626  	// Domain the sever is in
   627  	Domain string `json:"domain,omitempty"`
   628  	// Ephemeral placement tags for the move
   629  	Tags []string `json:"tags,omitempty"`
   630  }
   631  
   632  const JSApiAccountPurgeResponseType = "io.nats.jetstream.api.v1.account_purge_response"
   633  
   634  // JSApiAccountPurgeResponse is the response to a purge request in the meta group.
   635  type JSApiAccountPurgeResponse struct {
   636  	ApiResponse
   637  	Initiated bool `json:"initiated,omitempty"`
   638  }
   639  
   640  // JSApiMsgGetRequest get a message request.
   641  type JSApiMsgGetRequest struct {
   642  	Seq     uint64 `json:"seq,omitempty"`
   643  	LastFor string `json:"last_by_subj,omitempty"`
   644  	NextFor string `json:"next_by_subj,omitempty"`
   645  
   646  	// Batch support. Used to request more then one msg at a time.
   647  	// Can be used with simple starting seq, but also NextFor with wildcards.
   648  	Batch int `json:"batch,omitempty"`
   649  	// This will make sure we limit how much data we blast out. If not set we will
   650  	// inherit the slow consumer default max setting of the server. Default is MAX_PENDING_SIZE.
   651  	MaxBytes int `json:"max_bytes,omitempty"`
   652  	// Return messages as of this start time.
   653  	StartTime *time.Time `json:"start_time,omitempty"`
   654  
   655  	// Multiple response support. Will get the last msgs matching the subjects. These can include wildcards.
   656  	MultiLastFor []string `json:"multi_last,omitempty"`
   657  	// Only return messages up to this sequence. If not set, will be last sequence for the stream.
   658  	UpToSeq uint64 `json:"up_to_seq,omitempty"`
   659  	// Only return messages up to this time.
   660  	UpToTime *time.Time `json:"up_to_time,omitempty"`
   661  }
   662  
   663  type JSApiMsgGetResponse struct {
   664  	ApiResponse
   665  	Message *StoredMsg `json:"message,omitempty"`
   666  }
   667  
   668  const JSApiMsgGetResponseType = "io.nats.jetstream.api.v1.stream_msg_get_response"
   669  
   670  // JSWaitQueueDefaultMax is the default max number of outstanding requests for pull consumers.
   671  const JSWaitQueueDefaultMax = 512
   672  
   673  type JSApiConsumerCreateResponse struct {
   674  	ApiResponse
   675  	*ConsumerInfo
   676  }
   677  
   678  const JSApiConsumerCreateResponseType = "io.nats.jetstream.api.v1.consumer_create_response"
   679  
   680  type JSApiConsumerDeleteResponse struct {
   681  	ApiResponse
   682  	Success bool `json:"success,omitempty"`
   683  }
   684  
   685  const JSApiConsumerDeleteResponseType = "io.nats.jetstream.api.v1.consumer_delete_response"
   686  
   687  type JSApiConsumerPauseRequest struct {
   688  	PauseUntil time.Time `json:"pause_until,omitempty"`
   689  }
   690  
   691  const JSApiConsumerPauseResponseType = "io.nats.jetstream.api.v1.consumer_pause_response"
   692  
   693  type JSApiConsumerPauseResponse struct {
   694  	ApiResponse
   695  	Paused         bool          `json:"paused"`
   696  	PauseUntil     time.Time     `json:"pause_until"`
   697  	PauseRemaining time.Duration `json:"pause_remaining,omitempty"`
   698  }
   699  
   700  type JSApiConsumerInfoResponse struct {
   701  	ApiResponse
   702  	*ConsumerInfo
   703  }
   704  
   705  const JSApiConsumerInfoResponseType = "io.nats.jetstream.api.v1.consumer_info_response"
   706  
   707  type JSApiConsumersRequest struct {
   708  	ApiPagedRequest
   709  }
   710  
   711  type JSApiConsumerNamesResponse struct {
   712  	ApiResponse
   713  	ApiPaged
   714  	Consumers []string `json:"consumers"`
   715  }
   716  
   717  const JSApiConsumerNamesResponseType = "io.nats.jetstream.api.v1.consumer_names_response"
   718  
   719  type JSApiConsumerListResponse struct {
   720  	ApiResponse
   721  	ApiPaged
   722  	Consumers []*ConsumerInfo `json:"consumers"`
   723  	Missing   []string        `json:"missing,omitempty"`
   724  }
   725  
   726  const JSApiConsumerListResponseType = "io.nats.jetstream.api.v1.consumer_list_response"
   727  
   728  // JSApiConsumerGetNextRequest is for getting next messages for pull based consumers.
   729  type JSApiConsumerGetNextRequest struct {
   730  	Expires   time.Duration `json:"expires,omitempty"`
   731  	Batch     int           `json:"batch,omitempty"`
   732  	MaxBytes  int           `json:"max_bytes,omitempty"`
   733  	NoWait    bool          `json:"no_wait,omitempty"`
   734  	Heartbeat time.Duration `json:"idle_heartbeat,omitempty"`
   735  }
   736  
   737  // JSApiStreamTemplateCreateResponse for creating templates.
   738  type JSApiStreamTemplateCreateResponse struct {
   739  	ApiResponse
   740  	*StreamTemplateInfo
   741  }
   742  
   743  const JSApiStreamTemplateCreateResponseType = "io.nats.jetstream.api.v1.stream_template_create_response"
   744  
   745  type JSApiStreamTemplateDeleteResponse struct {
   746  	ApiResponse
   747  	Success bool `json:"success,omitempty"`
   748  }
   749  
   750  const JSApiStreamTemplateDeleteResponseType = "io.nats.jetstream.api.v1.stream_template_delete_response"
   751  
   752  // JSApiStreamTemplateInfoResponse for information about stream templates.
   753  type JSApiStreamTemplateInfoResponse struct {
   754  	ApiResponse
   755  	*StreamTemplateInfo
   756  }
   757  
   758  const JSApiStreamTemplateInfoResponseType = "io.nats.jetstream.api.v1.stream_template_info_response"
   759  
   760  type JSApiStreamTemplatesRequest struct {
   761  	ApiPagedRequest
   762  }
   763  
   764  // JSApiStreamTemplateNamesResponse list of templates
   765  type JSApiStreamTemplateNamesResponse struct {
   766  	ApiResponse
   767  	ApiPaged
   768  	Templates []string `json:"streams"`
   769  }
   770  
   771  const JSApiStreamTemplateNamesResponseType = "io.nats.jetstream.api.v1.stream_template_names_response"
   772  
   773  // Structure that holds state for a JetStream API request that is processed
   774  // in a separate long-lived go routine. This is to avoid possibly blocking
   775  // ROUTE and GATEWAY connections.
   776  type jsAPIRoutedReq struct {
   777  	jsub    *subscription
   778  	sub     *subscription
   779  	acc     *Account
   780  	subject string
   781  	reply   string
   782  	msg     []byte
   783  	pa      pubArg
   784  }
   785  
   786  func (js *jetStream) apiDispatch(sub *subscription, c *client, acc *Account, subject, reply string, rmsg []byte) {
   787  	// Ignore system level directives meta stepdown and peer remove requests here.
   788  	if subject == JSApiLeaderStepDown ||
   789  		subject == JSApiRemoveServer ||
   790  		strings.HasPrefix(subject, jsAPIAccountPre) {
   791  		return
   792  	}
   793  	// No lock needed, those are immutable.
   794  	s, rr := js.srv, js.apiSubs.Match(subject)
   795  
   796  	hdr, msg := c.msgParts(rmsg)
   797  	if len(getHeader(ClientInfoHdr, hdr)) == 0 {
   798  		// Check if this is the system account. We will let these through for the account info only.
   799  		sacc := s.SystemAccount()
   800  		if sacc != acc {
   801  			return
   802  		}
   803  		if subject != JSApiAccountInfo {
   804  			// Only respond from the initial server entry to the NATS system.
   805  			if c.kind == CLIENT || c.kind == LEAF {
   806  				var resp = ApiResponse{
   807  					Type:  JSApiSystemResponseType,
   808  					Error: NewJSNotEnabledForAccountError(),
   809  				}
   810  				s.sendAPIErrResponse(nil, acc, subject, reply, string(msg), s.jsonResponse(&resp))
   811  			}
   812  			return
   813  		}
   814  	}
   815  
   816  	// Short circuit for no interest.
   817  	if len(rr.psubs)+len(rr.qsubs) == 0 {
   818  		if (c.kind == CLIENT || c.kind == LEAF) && acc != s.SystemAccount() {
   819  			ci, acc, _, _, _ := s.getRequestInfo(c, rmsg)
   820  			var resp = ApiResponse{
   821  				Type:  JSApiSystemResponseType,
   822  				Error: NewJSBadRequestError(),
   823  			}
   824  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
   825  		}
   826  		return
   827  	}
   828  
   829  	// We should only have psubs and only 1 per result.
   830  	if len(rr.psubs) != 1 {
   831  		s.Warnf("Malformed JetStream API Request: [%s] %q", subject, rmsg)
   832  		if c.kind == CLIENT || c.kind == LEAF {
   833  			ci, acc, _, _, _ := s.getRequestInfo(c, rmsg)
   834  			var resp = ApiResponse{
   835  				Type:  JSApiSystemResponseType,
   836  				Error: NewJSBadRequestError(),
   837  			}
   838  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
   839  		}
   840  		return
   841  	}
   842  	jsub := rr.psubs[0]
   843  
   844  	// If this is directly from a client connection ok to do in place.
   845  	if c.kind != ROUTER && c.kind != GATEWAY && c.kind != LEAF {
   846  		start := time.Now()
   847  		jsub.icb(sub, c, acc, subject, reply, rmsg)
   848  		if dur := time.Since(start); dur >= readLoopReportThreshold {
   849  			s.Warnf("Internal subscription on %q took too long: %v", subject, dur)
   850  		}
   851  		return
   852  	}
   853  
   854  	// If we are here we have received this request over a non-client connection.
   855  	// We need to make sure not to block. We will send the request to a long-lived
   856  	// pool of go routines.
   857  
   858  	// Increment inflight. Do this before queueing.
   859  	atomic.AddInt64(&js.apiInflight, 1)
   860  
   861  	// Copy the state. Note the JSAPI only uses the hdr index to piece apart the
   862  	// header from the msg body. No other references are needed.
   863  	// Check pending and warn if getting backed up.
   864  	const warnThresh = 32
   865  	pending := s.jsAPIRoutedReqs.push(&jsAPIRoutedReq{jsub, sub, acc, subject, reply, copyBytes(rmsg), c.pa})
   866  	if pending > warnThresh {
   867  		s.RateLimitWarnf("JetStream request queue has high pending count: %d", pending)
   868  	}
   869  }
   870  
   871  func (s *Server) processJSAPIRoutedRequests() {
   872  	defer s.grWG.Done()
   873  
   874  	s.mu.RLock()
   875  	queue := s.jsAPIRoutedReqs
   876  	client := &client{srv: s, kind: JETSTREAM}
   877  	s.mu.RUnlock()
   878  
   879  	js := s.getJetStream()
   880  
   881  	for {
   882  		select {
   883  		case <-queue.ch:
   884  			reqs := queue.pop()
   885  			for _, r := range reqs {
   886  				client.pa = r.pa
   887  				start := time.Now()
   888  				r.jsub.icb(r.sub, client, r.acc, r.subject, r.reply, r.msg)
   889  				if dur := time.Since(start); dur >= readLoopReportThreshold {
   890  					s.Warnf("Internal subscription on %q took too long: %v", r.subject, dur)
   891  				}
   892  				atomic.AddInt64(&js.apiInflight, -1)
   893  			}
   894  			queue.recycle(&reqs)
   895  		case <-s.quitCh:
   896  			return
   897  		}
   898  	}
   899  }
   900  
   901  func (s *Server) setJetStreamExportSubs() error {
   902  	js := s.getJetStream()
   903  	if js == nil {
   904  		return NewJSNotEnabledError()
   905  	}
   906  
   907  	// Start the go routine that will process API requests received by the
   908  	// subscription below when they are coming from routes, etc..
   909  	const maxProcs = 16
   910  	mp := runtime.GOMAXPROCS(0)
   911  	// Cap at 16 max for now on larger core setups.
   912  	if mp > maxProcs {
   913  		mp = maxProcs
   914  	}
   915  	s.jsAPIRoutedReqs = newIPQueue[*jsAPIRoutedReq](s, "Routed JS API Requests")
   916  	for i := 0; i < mp; i++ {
   917  		s.startGoRoutine(s.processJSAPIRoutedRequests)
   918  	}
   919  
   920  	// This is the catch all now for all JetStream API calls.
   921  	if _, err := s.sysSubscribe(jsAllAPI, js.apiDispatch); err != nil {
   922  		return err
   923  	}
   924  
   925  	if err := s.SystemAccount().AddServiceExport(jsAllAPI, nil); err != nil {
   926  		s.Warnf("Error setting up jetstream service exports: %v", err)
   927  		return err
   928  	}
   929  
   930  	// API handles themselves.
   931  	pairs := []struct {
   932  		subject string
   933  		handler msgHandler
   934  	}{
   935  		{JSApiAccountInfo, s.jsAccountInfoRequest},
   936  		{JSApiTemplateCreate, s.jsTemplateCreateRequest},
   937  		{JSApiTemplates, s.jsTemplateNamesRequest},
   938  		{JSApiTemplateInfo, s.jsTemplateInfoRequest},
   939  		{JSApiTemplateDelete, s.jsTemplateDeleteRequest},
   940  		{JSApiStreamCreate, s.jsStreamCreateRequest},
   941  		{JSApiStreamUpdate, s.jsStreamUpdateRequest},
   942  		{JSApiStreams, s.jsStreamNamesRequest},
   943  		{JSApiStreamList, s.jsStreamListRequest},
   944  		{JSApiStreamInfo, s.jsStreamInfoRequest},
   945  		{JSApiStreamDelete, s.jsStreamDeleteRequest},
   946  		{JSApiStreamPurge, s.jsStreamPurgeRequest},
   947  		{JSApiStreamSnapshot, s.jsStreamSnapshotRequest},
   948  		{JSApiStreamRestore, s.jsStreamRestoreRequest},
   949  		{JSApiStreamRemovePeer, s.jsStreamRemovePeerRequest},
   950  		{JSApiStreamLeaderStepDown, s.jsStreamLeaderStepDownRequest},
   951  		{JSApiConsumerLeaderStepDown, s.jsConsumerLeaderStepDownRequest},
   952  		{JSApiMsgDelete, s.jsMsgDeleteRequest},
   953  		{JSApiMsgGet, s.jsMsgGetRequest},
   954  		{JSApiConsumerCreateEx, s.jsConsumerCreateRequest},
   955  		{JSApiConsumerCreate, s.jsConsumerCreateRequest},
   956  		{JSApiDurableCreate, s.jsConsumerCreateRequest},
   957  		{JSApiConsumers, s.jsConsumerNamesRequest},
   958  		{JSApiConsumerList, s.jsConsumerListRequest},
   959  		{JSApiConsumerInfo, s.jsConsumerInfoRequest},
   960  		{JSApiConsumerDelete, s.jsConsumerDeleteRequest},
   961  		{JSApiConsumerPause, s.jsConsumerPauseRequest},
   962  	}
   963  
   964  	js.mu.Lock()
   965  	defer js.mu.Unlock()
   966  
   967  	for _, p := range pairs {
   968  		sub := &subscription{subject: []byte(p.subject), icb: p.handler}
   969  		if err := js.apiSubs.Insert(sub); err != nil {
   970  			return err
   971  		}
   972  	}
   973  
   974  	return nil
   975  }
   976  
   977  func (s *Server) sendAPIResponse(ci *ClientInfo, acc *Account, subject, reply, request, response string) {
   978  	acc.trackAPI()
   979  	if reply != _EMPTY_ {
   980  		s.sendInternalAccountMsg(nil, reply, response)
   981  	}
   982  	s.sendJetStreamAPIAuditAdvisory(ci, acc, subject, request, response)
   983  }
   984  
   985  func (s *Server) sendAPIErrResponse(ci *ClientInfo, acc *Account, subject, reply, request, response string) {
   986  	acc.trackAPIErr()
   987  	if reply != _EMPTY_ {
   988  		s.sendInternalAccountMsg(nil, reply, response)
   989  	}
   990  	s.sendJetStreamAPIAuditAdvisory(ci, acc, subject, request, response)
   991  }
   992  
   993  const errRespDelay = 500 * time.Millisecond
   994  
   995  func (s *Server) sendDelayedAPIErrResponse(ci *ClientInfo, acc *Account, subject, reply, request, response string, rg *raftGroup) {
   996  	js := s.getJetStream()
   997  	if js == nil {
   998  		return
   999  	}
  1000  	var quitCh <-chan struct{}
  1001  	js.mu.RLock()
  1002  	if rg != nil && rg.node != nil {
  1003  		quitCh = rg.node.QuitC()
  1004  	}
  1005  	js.mu.RUnlock()
  1006  
  1007  	s.startGoRoutine(func() {
  1008  		defer s.grWG.Done()
  1009  		select {
  1010  		case <-quitCh:
  1011  		case <-s.quitCh:
  1012  		case <-time.After(errRespDelay):
  1013  			acc.trackAPIErr()
  1014  			if reply != _EMPTY_ {
  1015  				s.sendInternalAccountMsg(nil, reply, response)
  1016  			}
  1017  			s.sendJetStreamAPIAuditAdvisory(ci, acc, subject, request, response)
  1018  		}
  1019  	})
  1020  }
  1021  
  1022  func (s *Server) getRequestInfo(c *client, raw []byte) (pci *ClientInfo, acc *Account, hdr, msg []byte, err error) {
  1023  	hdr, msg = c.msgParts(raw)
  1024  	var ci ClientInfo
  1025  
  1026  	if len(hdr) > 0 {
  1027  		if err := json.Unmarshal(getHeader(ClientInfoHdr, hdr), &ci); err != nil {
  1028  			return nil, nil, nil, nil, err
  1029  		}
  1030  	}
  1031  
  1032  	if ci.Service != _EMPTY_ {
  1033  		acc, _ = s.LookupAccount(ci.Service)
  1034  	} else if ci.Account != _EMPTY_ {
  1035  		acc, _ = s.LookupAccount(ci.Account)
  1036  	} else {
  1037  		// Direct $SYS access.
  1038  		acc = c.acc
  1039  		if acc == nil {
  1040  			acc = s.SystemAccount()
  1041  		}
  1042  	}
  1043  	if acc == nil {
  1044  		return nil, nil, nil, nil, ErrMissingAccount
  1045  	}
  1046  	return &ci, acc, hdr, msg, nil
  1047  }
  1048  
  1049  func (a *Account) trackAPI() {
  1050  	a.mu.RLock()
  1051  	jsa := a.js
  1052  	a.mu.RUnlock()
  1053  	if jsa != nil {
  1054  		jsa.usageMu.Lock()
  1055  		jsa.usageApi++
  1056  		jsa.apiTotal++
  1057  		jsa.sendClusterUsageUpdate()
  1058  		atomic.AddInt64(&jsa.js.apiTotal, 1)
  1059  		jsa.usageMu.Unlock()
  1060  	}
  1061  }
  1062  
  1063  func (a *Account) trackAPIErr() {
  1064  	a.mu.RLock()
  1065  	jsa := a.js
  1066  	a.mu.RUnlock()
  1067  	if jsa != nil {
  1068  		jsa.usageMu.Lock()
  1069  		jsa.usageApi++
  1070  		jsa.apiTotal++
  1071  		jsa.usageErr++
  1072  		jsa.apiErrors++
  1073  		jsa.sendClusterUsageUpdate()
  1074  		atomic.AddInt64(&jsa.js.apiTotal, 1)
  1075  		atomic.AddInt64(&jsa.js.apiErrors, 1)
  1076  		jsa.usageMu.Unlock()
  1077  	}
  1078  }
  1079  
  1080  const badAPIRequestT = "Malformed JetStream API Request: %q"
  1081  
  1082  // Helper function to check on JetStream being enabled but also on status of leafnodes
  1083  // If the local account is not enabled but does have leafnode connectivity we will not
  1084  // want to error immediately and let the other side decide.
  1085  func (a *Account) checkJetStream() (enabled, shouldError bool) {
  1086  	a.mu.RLock()
  1087  	defer a.mu.RUnlock()
  1088  	return a.js != nil, a.nleafs+a.nrleafs == 0
  1089  }
  1090  
  1091  // Request for current usage and limits for this account.
  1092  func (s *Server) jsAccountInfoRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  1093  	if c == nil || !s.JetStreamEnabled() {
  1094  		return
  1095  	}
  1096  
  1097  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  1098  	if err != nil {
  1099  		s.Warnf(badAPIRequestT, msg)
  1100  		return
  1101  	}
  1102  
  1103  	var resp = JSApiAccountInfoResponse{ApiResponse: ApiResponse{Type: JSApiAccountInfoResponseType}}
  1104  
  1105  	// Determine if we should proceed here when we are in clustered mode.
  1106  	if s.JetStreamIsClustered() {
  1107  		js, cc := s.getJetStreamCluster()
  1108  		if js == nil || cc == nil {
  1109  			return
  1110  		}
  1111  		if js.isLeaderless() {
  1112  			resp.Error = NewJSClusterNotAvailError()
  1113  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1114  			return
  1115  		}
  1116  		// Make sure we are meta leader.
  1117  		if !s.JetStreamIsLeader() {
  1118  			return
  1119  		}
  1120  	}
  1121  
  1122  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  1123  		if !doErr {
  1124  			return
  1125  		}
  1126  		resp.Error = NewJSNotEnabledForAccountError()
  1127  	} else {
  1128  		stats := acc.JetStreamUsage()
  1129  		resp.JetStreamAccountStats = &stats
  1130  	}
  1131  	b, err := json.Marshal(resp)
  1132  	if err != nil {
  1133  		return
  1134  	}
  1135  
  1136  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), string(b))
  1137  }
  1138  
  1139  // Helpers for token extraction.
  1140  func templateNameFromSubject(subject string) string {
  1141  	return tokenAt(subject, 6)
  1142  }
  1143  
  1144  func streamNameFromSubject(subject string) string {
  1145  	return tokenAt(subject, 5)
  1146  }
  1147  
  1148  func consumerNameFromSubject(subject string) string {
  1149  	return tokenAt(subject, 6)
  1150  }
  1151  
  1152  // Request to create a new template.
  1153  func (s *Server) jsTemplateCreateRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  1154  	if c == nil {
  1155  		return
  1156  	}
  1157  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  1158  	if err != nil {
  1159  		s.Warnf(badAPIRequestT, msg)
  1160  		return
  1161  	}
  1162  
  1163  	var resp = JSApiStreamTemplateCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateCreateResponseType}}
  1164  	if !acc.JetStreamEnabled() {
  1165  		resp.Error = NewJSNotEnabledForAccountError()
  1166  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1167  		return
  1168  	}
  1169  
  1170  	// Not supported for now.
  1171  	if s.JetStreamIsClustered() {
  1172  		resp.Error = NewJSClusterUnSupportFeatureError()
  1173  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1174  		return
  1175  	}
  1176  
  1177  	var cfg StreamTemplateConfig
  1178  	if err := json.Unmarshal(msg, &cfg); err != nil {
  1179  		resp.Error = NewJSInvalidJSONError()
  1180  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1181  		return
  1182  	}
  1183  	templateName := templateNameFromSubject(subject)
  1184  	if templateName != cfg.Name {
  1185  		resp.Error = NewJSTemplateNameNotMatchSubjectError()
  1186  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1187  		return
  1188  	}
  1189  
  1190  	t, err := acc.addStreamTemplate(&cfg)
  1191  	if err != nil {
  1192  		resp.Error = NewJSStreamTemplateCreateError(err, Unless(err))
  1193  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1194  		return
  1195  	}
  1196  	t.mu.Lock()
  1197  	tcfg := t.StreamTemplateConfig.deepCopy()
  1198  	streams := t.streams
  1199  	if streams == nil {
  1200  		streams = []string{}
  1201  	}
  1202  	t.mu.Unlock()
  1203  	resp.StreamTemplateInfo = &StreamTemplateInfo{Config: tcfg, Streams: streams}
  1204  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  1205  }
  1206  
  1207  // Request for the list of all template names.
  1208  func (s *Server) jsTemplateNamesRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  1209  	if c == nil {
  1210  		return
  1211  	}
  1212  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  1213  	if err != nil {
  1214  		s.Warnf(badAPIRequestT, msg)
  1215  		return
  1216  	}
  1217  
  1218  	var resp = JSApiStreamTemplateNamesResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateNamesResponseType}}
  1219  	if !acc.JetStreamEnabled() {
  1220  		resp.Error = NewJSNotEnabledForAccountError()
  1221  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1222  		return
  1223  	}
  1224  
  1225  	// Not supported for now.
  1226  	if s.JetStreamIsClustered() {
  1227  		resp.Error = NewJSClusterUnSupportFeatureError()
  1228  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1229  		return
  1230  	}
  1231  
  1232  	var offset int
  1233  	if !isEmptyRequest(msg) {
  1234  		var req JSApiStreamTemplatesRequest
  1235  		if err := json.Unmarshal(msg, &req); err != nil {
  1236  			resp.Error = NewJSInvalidJSONError()
  1237  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1238  			return
  1239  		}
  1240  		offset = req.Offset
  1241  	}
  1242  
  1243  	ts := acc.templates()
  1244  	sort.Slice(ts, func(i, j int) bool {
  1245  		return strings.Compare(ts[i].StreamTemplateConfig.Name, ts[j].StreamTemplateConfig.Name) < 0
  1246  	})
  1247  
  1248  	tcnt := len(ts)
  1249  	if offset > tcnt {
  1250  		offset = tcnt
  1251  	}
  1252  
  1253  	for _, t := range ts[offset:] {
  1254  		t.mu.Lock()
  1255  		name := t.Name
  1256  		t.mu.Unlock()
  1257  		resp.Templates = append(resp.Templates, name)
  1258  		if len(resp.Templates) >= JSApiNamesLimit {
  1259  			break
  1260  		}
  1261  	}
  1262  	resp.Total = tcnt
  1263  	resp.Limit = JSApiNamesLimit
  1264  	resp.Offset = offset
  1265  	if resp.Templates == nil {
  1266  		resp.Templates = []string{}
  1267  	}
  1268  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  1269  }
  1270  
  1271  // Request for information about a stream template.
  1272  func (s *Server) jsTemplateInfoRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  1273  	if c == nil {
  1274  		return
  1275  	}
  1276  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  1277  	if err != nil {
  1278  		s.Warnf(badAPIRequestT, msg)
  1279  		return
  1280  	}
  1281  
  1282  	var resp = JSApiStreamTemplateInfoResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateInfoResponseType}}
  1283  	if !acc.JetStreamEnabled() {
  1284  		resp.Error = NewJSNotEnabledForAccountError()
  1285  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1286  		return
  1287  	}
  1288  	if !isEmptyRequest(msg) {
  1289  		resp.Error = NewJSNotEmptyRequestError()
  1290  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1291  		return
  1292  	}
  1293  	name := templateNameFromSubject(subject)
  1294  	t, err := acc.lookupStreamTemplate(name)
  1295  	if err != nil {
  1296  		resp.Error = NewJSStreamTemplateNotFoundError()
  1297  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1298  		return
  1299  	}
  1300  	t.mu.Lock()
  1301  	cfg := t.StreamTemplateConfig.deepCopy()
  1302  	streams := t.streams
  1303  	if streams == nil {
  1304  		streams = []string{}
  1305  	}
  1306  	t.mu.Unlock()
  1307  
  1308  	resp.StreamTemplateInfo = &StreamTemplateInfo{Config: cfg, Streams: streams}
  1309  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  1310  }
  1311  
  1312  // Request to delete a stream template.
  1313  func (s *Server) jsTemplateDeleteRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  1314  	if c == nil {
  1315  		return
  1316  	}
  1317  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  1318  	if err != nil {
  1319  		s.Warnf(badAPIRequestT, msg)
  1320  		return
  1321  	}
  1322  
  1323  	var resp = JSApiStreamTemplateDeleteResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateDeleteResponseType}}
  1324  	if !acc.JetStreamEnabled() {
  1325  		resp.Error = NewJSNotEnabledForAccountError()
  1326  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1327  		return
  1328  	}
  1329  	if !isEmptyRequest(msg) {
  1330  		resp.Error = NewJSNotEmptyRequestError()
  1331  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1332  		return
  1333  	}
  1334  	name := templateNameFromSubject(subject)
  1335  	err = acc.deleteStreamTemplate(name)
  1336  	if err != nil {
  1337  		resp.Error = NewJSStreamTemplateDeleteError(err, Unless(err))
  1338  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1339  		return
  1340  	}
  1341  	resp.Success = true
  1342  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  1343  }
  1344  
  1345  func (s *Server) jsonResponse(v any) string {
  1346  	b, err := json.Marshal(v)
  1347  	if err != nil {
  1348  		s.Warnf("Problem marshaling JSON for JetStream API:", err)
  1349  		return ""
  1350  	}
  1351  	return string(b)
  1352  }
  1353  
  1354  // Read lock must be held
  1355  func (jsa *jsAccount) tieredReservation(tier string, cfg *StreamConfig) int64 {
  1356  	reservation := int64(0)
  1357  	if tier == _EMPTY_ {
  1358  		for _, sa := range jsa.streams {
  1359  			if sa.cfg.MaxBytes > 0 {
  1360  				if sa.cfg.Storage == cfg.Storage && sa.cfg.Name != cfg.Name {
  1361  					reservation += (int64(sa.cfg.Replicas) * sa.cfg.MaxBytes)
  1362  				}
  1363  			}
  1364  		}
  1365  	} else {
  1366  		for _, sa := range jsa.streams {
  1367  			if sa.cfg.Replicas == cfg.Replicas {
  1368  				if sa.cfg.MaxBytes > 0 {
  1369  					if isSameTier(&sa.cfg, cfg) && sa.cfg.Name != cfg.Name {
  1370  						reservation += (int64(sa.cfg.Replicas) * sa.cfg.MaxBytes)
  1371  					}
  1372  				}
  1373  			}
  1374  		}
  1375  	}
  1376  	return reservation
  1377  }
  1378  
  1379  // Request to create a stream.
  1380  func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  1381  	if c == nil || !s.JetStreamEnabled() {
  1382  		return
  1383  	}
  1384  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  1385  	if err != nil {
  1386  		s.Warnf(badAPIRequestT, msg)
  1387  		return
  1388  	}
  1389  
  1390  	var resp = JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}}
  1391  
  1392  	// Determine if we should proceed here when we are in clustered mode.
  1393  	if s.JetStreamIsClustered() {
  1394  		js, cc := s.getJetStreamCluster()
  1395  		if js == nil || cc == nil {
  1396  			return
  1397  		}
  1398  		if js.isLeaderless() {
  1399  			resp.Error = NewJSClusterNotAvailError()
  1400  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1401  			return
  1402  		}
  1403  		// Make sure we are meta leader.
  1404  		if !s.JetStreamIsLeader() {
  1405  			return
  1406  		}
  1407  	}
  1408  
  1409  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  1410  		if doErr {
  1411  			resp.Error = NewJSNotEnabledForAccountError()
  1412  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1413  		}
  1414  		return
  1415  	}
  1416  
  1417  	var cfg StreamConfig
  1418  	if err := json.Unmarshal(msg, &cfg); err != nil {
  1419  		resp.Error = NewJSInvalidJSONError()
  1420  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1421  		return
  1422  	}
  1423  
  1424  	streamName := streamNameFromSubject(subject)
  1425  	if streamName != cfg.Name {
  1426  		resp.Error = NewJSStreamMismatchError()
  1427  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1428  		return
  1429  	}
  1430  
  1431  	// Check for path like separators in the name.
  1432  	if strings.ContainsAny(streamName, `\/`) {
  1433  		resp.Error = NewJSStreamNameContainsPathSeparatorsError()
  1434  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1435  		return
  1436  	}
  1437  
  1438  	// Can't create a stream with a sealed state.
  1439  	if cfg.Sealed {
  1440  		resp.Error = NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration for create can not be sealed"))
  1441  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1442  		return
  1443  	}
  1444  
  1445  	// If we are told to do mirror direct but are not mirroring, error.
  1446  	if cfg.MirrorDirect && cfg.Mirror == nil {
  1447  		resp.Error = NewJSStreamInvalidConfigError(fmt.Errorf("stream has no mirror but does have mirror direct"))
  1448  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1449  		return
  1450  	}
  1451  
  1452  	// Hand off to cluster for processing.
  1453  	if s.JetStreamIsClustered() {
  1454  		s.jsClusteredStreamRequest(ci, acc, subject, reply, rmsg, &cfg)
  1455  		return
  1456  	}
  1457  
  1458  	if err := acc.jsNonClusteredStreamLimitsCheck(&cfg); err != nil {
  1459  		resp.Error = err
  1460  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1461  		return
  1462  	}
  1463  
  1464  	mset, err := acc.addStream(&cfg)
  1465  	if err != nil {
  1466  		if IsNatsErr(err, JSStreamStoreFailedF) {
  1467  			s.Warnf("Stream create failed for '%s > %s': %v", acc, streamName, err)
  1468  			err = errStreamStoreFailed
  1469  		}
  1470  		resp.Error = NewJSStreamCreateError(err, Unless(err))
  1471  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1472  		return
  1473  	}
  1474  	resp.StreamInfo = &StreamInfo{
  1475  		Created:   mset.createdTime(),
  1476  		State:     mset.state(),
  1477  		Config:    mset.config(),
  1478  		TimeStamp: time.Now().UTC(),
  1479  		Mirror:    mset.mirrorInfo(),
  1480  		Sources:   mset.sourcesInfo(),
  1481  	}
  1482  	resp.DidCreate = true
  1483  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  1484  }
  1485  
  1486  // Request to update a stream.
  1487  func (s *Server) jsStreamUpdateRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  1488  	if c == nil || !s.JetStreamEnabled() {
  1489  		return
  1490  	}
  1491  
  1492  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  1493  	if err != nil {
  1494  		s.Warnf(badAPIRequestT, msg)
  1495  		return
  1496  	}
  1497  
  1498  	var resp = JSApiStreamUpdateResponse{ApiResponse: ApiResponse{Type: JSApiStreamUpdateResponseType}}
  1499  
  1500  	// Determine if we should proceed here when we are in clustered mode.
  1501  	if s.JetStreamIsClustered() {
  1502  		js, cc := s.getJetStreamCluster()
  1503  		if js == nil || cc == nil {
  1504  			return
  1505  		}
  1506  		if js.isLeaderless() {
  1507  			resp.Error = NewJSClusterNotAvailError()
  1508  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1509  			return
  1510  		}
  1511  		// Make sure we are meta leader.
  1512  		if !s.JetStreamIsLeader() {
  1513  			return
  1514  		}
  1515  	}
  1516  
  1517  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  1518  		if doErr {
  1519  			resp.Error = NewJSNotEnabledForAccountError()
  1520  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1521  		}
  1522  		return
  1523  	}
  1524  	var ncfg StreamConfig
  1525  	if err := json.Unmarshal(msg, &ncfg); err != nil {
  1526  		resp.Error = NewJSInvalidJSONError()
  1527  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1528  		return
  1529  	}
  1530  
  1531  	cfg, apiErr := s.checkStreamCfg(&ncfg, acc)
  1532  	if apiErr != nil {
  1533  		resp.Error = apiErr
  1534  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1535  		return
  1536  	}
  1537  
  1538  	streamName := streamNameFromSubject(subject)
  1539  	if streamName != cfg.Name {
  1540  		resp.Error = NewJSStreamMismatchError()
  1541  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1542  		return
  1543  	}
  1544  
  1545  	// Handle clustered version here.
  1546  	if s.JetStreamIsClustered() {
  1547  		// Always do in separate Go routine.
  1548  		go s.jsClusteredStreamUpdateRequest(ci, acc, subject, reply, copyBytes(rmsg), &cfg, nil)
  1549  		return
  1550  	}
  1551  
  1552  	mset, err := acc.lookupStream(streamName)
  1553  	if err != nil {
  1554  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  1555  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1556  		return
  1557  	}
  1558  
  1559  	if err := mset.update(&cfg); err != nil {
  1560  		resp.Error = NewJSStreamUpdateError(err, Unless(err))
  1561  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1562  		return
  1563  	}
  1564  
  1565  	resp.StreamInfo = &StreamInfo{
  1566  		Created:   mset.createdTime(),
  1567  		State:     mset.state(),
  1568  		Config:    mset.config(),
  1569  		Domain:    s.getOpts().JetStreamDomain,
  1570  		Mirror:    mset.mirrorInfo(),
  1571  		Sources:   mset.sourcesInfo(),
  1572  		TimeStamp: time.Now().UTC(),
  1573  	}
  1574  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  1575  }
  1576  
  1577  // Request for the list of all stream names.
  1578  func (s *Server) jsStreamNamesRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  1579  	if c == nil || !s.JetStreamEnabled() {
  1580  		return
  1581  	}
  1582  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  1583  	if err != nil {
  1584  		s.Warnf(badAPIRequestT, msg)
  1585  		return
  1586  	}
  1587  
  1588  	var resp = JSApiStreamNamesResponse{ApiResponse: ApiResponse{Type: JSApiStreamNamesResponseType}}
  1589  
  1590  	// Determine if we should proceed here when we are in clustered mode.
  1591  	if s.JetStreamIsClustered() {
  1592  		js, cc := s.getJetStreamCluster()
  1593  		if js == nil || cc == nil {
  1594  			return
  1595  		}
  1596  		if js.isLeaderless() {
  1597  			resp.Error = NewJSClusterNotAvailError()
  1598  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1599  			return
  1600  		}
  1601  		// Make sure we are meta leader.
  1602  		if !s.JetStreamIsLeader() {
  1603  			return
  1604  		}
  1605  	}
  1606  
  1607  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  1608  		if doErr {
  1609  			resp.Error = NewJSNotEnabledForAccountError()
  1610  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1611  		}
  1612  		return
  1613  	}
  1614  
  1615  	var offset int
  1616  	var filter string
  1617  
  1618  	if !isEmptyRequest(msg) {
  1619  		var req JSApiStreamNamesRequest
  1620  		if err := json.Unmarshal(msg, &req); err != nil {
  1621  			resp.Error = NewJSInvalidJSONError()
  1622  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1623  			return
  1624  		}
  1625  		offset = req.Offset
  1626  		if req.Subject != _EMPTY_ {
  1627  			filter = req.Subject
  1628  		}
  1629  	}
  1630  
  1631  	// TODO(dlc) - Maybe hold these results for large results that we expect to be paged.
  1632  	// TODO(dlc) - If this list is long maybe do this in a Go routine?
  1633  	var numStreams int
  1634  	if s.JetStreamIsClustered() {
  1635  		js, cc := s.getJetStreamCluster()
  1636  		if js == nil || cc == nil {
  1637  			// TODO(dlc) - Debug or Warn?
  1638  			return
  1639  		}
  1640  		js.mu.RLock()
  1641  		for stream, sa := range cc.streams[acc.Name] {
  1642  			if IsNatsErr(sa.err, JSClusterNotAssignedErr) {
  1643  				continue
  1644  			}
  1645  			if filter != _EMPTY_ {
  1646  				// These could not have subjects auto-filled in since they are raw and unprocessed.
  1647  				if len(sa.Config.Subjects) == 0 {
  1648  					if SubjectsCollide(filter, sa.Config.Name) {
  1649  						resp.Streams = append(resp.Streams, stream)
  1650  					}
  1651  				} else {
  1652  					for _, subj := range sa.Config.Subjects {
  1653  						if SubjectsCollide(filter, subj) {
  1654  							resp.Streams = append(resp.Streams, stream)
  1655  							break
  1656  						}
  1657  					}
  1658  				}
  1659  			} else {
  1660  				resp.Streams = append(resp.Streams, stream)
  1661  			}
  1662  		}
  1663  		js.mu.RUnlock()
  1664  		if len(resp.Streams) > 1 {
  1665  			sort.Slice(resp.Streams, func(i, j int) bool { return strings.Compare(resp.Streams[i], resp.Streams[j]) < 0 })
  1666  		}
  1667  		numStreams = len(resp.Streams)
  1668  		if offset > numStreams {
  1669  			offset = numStreams
  1670  		}
  1671  		if offset > 0 {
  1672  			resp.Streams = resp.Streams[offset:]
  1673  		}
  1674  		if len(resp.Streams) > JSApiNamesLimit {
  1675  			resp.Streams = resp.Streams[:JSApiNamesLimit]
  1676  		}
  1677  	} else {
  1678  		msets := acc.filteredStreams(filter)
  1679  		// Since we page results order matters.
  1680  		if len(msets) > 1 {
  1681  			sort.Slice(msets, func(i, j int) bool {
  1682  				return strings.Compare(msets[i].cfg.Name, msets[j].cfg.Name) < 0
  1683  			})
  1684  		}
  1685  
  1686  		numStreams = len(msets)
  1687  		if offset > numStreams {
  1688  			offset = numStreams
  1689  		}
  1690  
  1691  		for _, mset := range msets[offset:] {
  1692  			resp.Streams = append(resp.Streams, mset.cfg.Name)
  1693  			if len(resp.Streams) >= JSApiNamesLimit {
  1694  				break
  1695  			}
  1696  		}
  1697  	}
  1698  	resp.Total = numStreams
  1699  	resp.Limit = JSApiNamesLimit
  1700  	resp.Offset = offset
  1701  
  1702  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  1703  }
  1704  
  1705  // Request for the list of all detailed stream info.
  1706  // TODO(dlc) - combine with above long term
  1707  func (s *Server) jsStreamListRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  1708  	if c == nil || !s.JetStreamEnabled() {
  1709  		return
  1710  	}
  1711  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  1712  	if err != nil {
  1713  		s.Warnf(badAPIRequestT, msg)
  1714  		return
  1715  	}
  1716  
  1717  	var resp = JSApiStreamListResponse{
  1718  		ApiResponse: ApiResponse{Type: JSApiStreamListResponseType},
  1719  		Streams:     []*StreamInfo{},
  1720  	}
  1721  
  1722  	// Determine if we should proceed here when we are in clustered mode.
  1723  	if s.JetStreamIsClustered() {
  1724  		js, cc := s.getJetStreamCluster()
  1725  		if js == nil || cc == nil {
  1726  			return
  1727  		}
  1728  		if js.isLeaderless() {
  1729  			resp.Error = NewJSClusterNotAvailError()
  1730  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1731  			return
  1732  		}
  1733  		// Make sure we are meta leader.
  1734  		if !s.JetStreamIsLeader() {
  1735  			return
  1736  		}
  1737  	}
  1738  
  1739  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  1740  		if doErr {
  1741  			resp.Error = NewJSNotEnabledForAccountError()
  1742  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1743  		}
  1744  		return
  1745  	}
  1746  
  1747  	var offset int
  1748  	var filter string
  1749  
  1750  	if !isEmptyRequest(msg) {
  1751  		var req JSApiStreamListRequest
  1752  		if err := json.Unmarshal(msg, &req); err != nil {
  1753  			resp.Error = NewJSInvalidJSONError()
  1754  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1755  			return
  1756  		}
  1757  		offset = req.Offset
  1758  		if req.Subject != _EMPTY_ {
  1759  			filter = req.Subject
  1760  		}
  1761  	}
  1762  
  1763  	// Clustered mode will invoke a scatter and gather.
  1764  	if s.JetStreamIsClustered() {
  1765  		// Need to copy these off before sending.. don't move this inside startGoRoutine!!!
  1766  		msg = copyBytes(msg)
  1767  		s.startGoRoutine(func() { s.jsClusteredStreamListRequest(acc, ci, filter, offset, subject, reply, msg) })
  1768  		return
  1769  	}
  1770  
  1771  	// TODO(dlc) - Maybe hold these results for large results that we expect to be paged.
  1772  	// TODO(dlc) - If this list is long maybe do this in a Go routine?
  1773  	var msets []*stream
  1774  	if filter == _EMPTY_ {
  1775  		msets = acc.streams()
  1776  	} else {
  1777  		msets = acc.filteredStreams(filter)
  1778  	}
  1779  
  1780  	sort.Slice(msets, func(i, j int) bool {
  1781  		return strings.Compare(msets[i].cfg.Name, msets[j].cfg.Name) < 0
  1782  	})
  1783  
  1784  	scnt := len(msets)
  1785  	if offset > scnt {
  1786  		offset = scnt
  1787  	}
  1788  
  1789  	for _, mset := range msets[offset:] {
  1790  		config := mset.config()
  1791  		resp.Streams = append(resp.Streams, &StreamInfo{
  1792  			Created:   mset.createdTime(),
  1793  			State:     mset.state(),
  1794  			Config:    config,
  1795  			Domain:    s.getOpts().JetStreamDomain,
  1796  			Mirror:    mset.mirrorInfo(),
  1797  			Sources:   mset.sourcesInfo(),
  1798  			TimeStamp: time.Now().UTC(),
  1799  		})
  1800  		if len(resp.Streams) >= JSApiListLimit {
  1801  			break
  1802  		}
  1803  	}
  1804  	resp.Total = scnt
  1805  	resp.Limit = JSApiListLimit
  1806  	resp.Offset = offset
  1807  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  1808  }
  1809  
  1810  // Request for information about a stream.
  1811  func (s *Server) jsStreamInfoRequest(sub *subscription, c *client, a *Account, subject, reply string, rmsg []byte) {
  1812  	if c == nil || !s.JetStreamEnabled() {
  1813  		return
  1814  	}
  1815  	ci, acc, hdr, msg, err := s.getRequestInfo(c, rmsg)
  1816  	if err != nil {
  1817  		s.Warnf(badAPIRequestT, msg)
  1818  		return
  1819  	}
  1820  
  1821  	streamName := streamNameFromSubject(subject)
  1822  
  1823  	var resp = JSApiStreamInfoResponse{ApiResponse: ApiResponse{Type: JSApiStreamInfoResponseType}}
  1824  
  1825  	// If someone creates a duplicate stream that is identical we will get this request forwarded to us.
  1826  	// Make sure the response type is for a create call.
  1827  	if rt := getHeader(JSResponseType, hdr); len(rt) > 0 && string(rt) == jsCreateResponse {
  1828  		resp.ApiResponse.Type = JSApiStreamCreateResponseType
  1829  	}
  1830  
  1831  	var clusterWideConsCount int
  1832  
  1833  	js, cc := s.getJetStreamCluster()
  1834  	if js == nil {
  1835  		return
  1836  	}
  1837  	// If we are in clustered mode we need to be the stream leader to proceed.
  1838  	if cc != nil {
  1839  		// Check to make sure the stream is assigned.
  1840  		js.mu.RLock()
  1841  		isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, streamName)
  1842  		var offline bool
  1843  		if sa != nil {
  1844  			clusterWideConsCount = len(sa.consumers)
  1845  			offline = s.allPeersOffline(sa.Group)
  1846  		}
  1847  		js.mu.RUnlock()
  1848  
  1849  		if isLeader && sa == nil {
  1850  			// We can't find the stream, so mimic what would be the errors below.
  1851  			if hasJS, doErr := acc.checkJetStream(); !hasJS {
  1852  				if doErr {
  1853  					resp.Error = NewJSNotEnabledForAccountError()
  1854  					s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1855  				}
  1856  				return
  1857  			}
  1858  			// No stream present.
  1859  			resp.Error = NewJSStreamNotFoundError()
  1860  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1861  			return
  1862  		} else if sa == nil {
  1863  			if js.isLeaderless() {
  1864  				resp.Error = NewJSClusterNotAvailError()
  1865  				// Delaying an error response gives the leader a chance to respond before us
  1866  				s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil)
  1867  			}
  1868  			return
  1869  		} else if isLeader && offline {
  1870  			resp.Error = NewJSStreamOfflineError()
  1871  			s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil)
  1872  			return
  1873  		}
  1874  
  1875  		// Check to see if we are a member of the group and if the group has no leader.
  1876  		isLeaderless := js.isGroupLeaderless(sa.Group)
  1877  
  1878  		// We have the stream assigned and a leader, so only the stream leader should answer.
  1879  		if !acc.JetStreamIsStreamLeader(streamName) && !isLeaderless {
  1880  			if js.isLeaderless() {
  1881  				resp.Error = NewJSClusterNotAvailError()
  1882  				// Delaying an error response gives the leader a chance to respond before us
  1883  				s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), sa.Group)
  1884  				return
  1885  			}
  1886  
  1887  			// We may be in process of electing a leader, but if this is a scale up from 1 we will still be the state leader
  1888  			// while the new members work through the election and catchup process.
  1889  			// Double check for that instead of exiting here and being silent. e.g. nats stream update test --replicas=3
  1890  			js.mu.RLock()
  1891  			rg := sa.Group
  1892  			var ourID string
  1893  			if cc.meta != nil {
  1894  				ourID = cc.meta.ID()
  1895  			}
  1896  			// We have seen cases where rg or rg.node is nil at this point,
  1897  			// so check explicitly on those conditions and bail if that is
  1898  			// the case.
  1899  			bail := rg == nil || rg.node == nil || !rg.isMember(ourID)
  1900  			if !bail {
  1901  				// We know we are a member here, if this group is new and we are preferred allow us to answer.
  1902  				bail = rg.Preferred != ourID || time.Since(rg.node.Created()) > lostQuorumIntervalDefault
  1903  			}
  1904  			js.mu.RUnlock()
  1905  			if bail {
  1906  				return
  1907  			}
  1908  		}
  1909  	}
  1910  
  1911  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  1912  		if doErr {
  1913  			resp.Error = NewJSNotEnabledForAccountError()
  1914  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1915  		}
  1916  		return
  1917  	}
  1918  
  1919  	var details bool
  1920  	var subjects string
  1921  	var offset int
  1922  	if !isEmptyRequest(msg) {
  1923  		var req JSApiStreamInfoRequest
  1924  		if err := json.Unmarshal(msg, &req); err != nil {
  1925  			resp.Error = NewJSInvalidJSONError()
  1926  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1927  			return
  1928  		}
  1929  		details, subjects = req.DeletedDetails, req.SubjectsFilter
  1930  		offset = req.Offset
  1931  	}
  1932  
  1933  	mset, err := acc.lookupStream(streamName)
  1934  	// Error is not to be expected at this point, but could happen if same stream trying to be created.
  1935  	if err != nil {
  1936  		if cc != nil {
  1937  			// This could be inflight, pause for a short bit and try again.
  1938  			// This will not be inline, so ok.
  1939  			time.Sleep(10 * time.Millisecond)
  1940  			mset, err = acc.lookupStream(streamName)
  1941  		}
  1942  		// Check again.
  1943  		if err != nil {
  1944  			resp.Error = NewJSStreamNotFoundError(Unless(err))
  1945  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  1946  			return
  1947  		}
  1948  	}
  1949  
  1950  	config := mset.config()
  1951  
  1952  	resp.StreamInfo = &StreamInfo{
  1953  		Created:    mset.createdTime(),
  1954  		State:      mset.stateWithDetail(details),
  1955  		Config:     config,
  1956  		Domain:     s.getOpts().JetStreamDomain,
  1957  		Cluster:    js.clusterInfo(mset.raftGroup()),
  1958  		Mirror:     mset.mirrorInfo(),
  1959  		Sources:    mset.sourcesInfo(),
  1960  		Alternates: js.streamAlternates(ci, config.Name),
  1961  		TimeStamp:  time.Now().UTC(),
  1962  	}
  1963  	if clusterWideConsCount > 0 {
  1964  		resp.StreamInfo.State.Consumers = clusterWideConsCount
  1965  	}
  1966  
  1967  	// Check if they have asked for subject details.
  1968  	if subjects != _EMPTY_ {
  1969  		st := mset.store.SubjectsTotals(subjects)
  1970  		if lst := len(st); lst > 0 {
  1971  			// Common for both cases.
  1972  			resp.Offset = offset
  1973  			resp.Limit = JSMaxSubjectDetails
  1974  			resp.Total = lst
  1975  
  1976  			if offset == 0 && lst <= JSMaxSubjectDetails {
  1977  				resp.StreamInfo.State.Subjects = st
  1978  			} else {
  1979  				// Here we have to filter list due to offset or maximum constraints.
  1980  				subjs := make([]string, 0, len(st))
  1981  				for subj := range st {
  1982  					subjs = append(subjs, subj)
  1983  				}
  1984  				// Sort it
  1985  				sort.Strings(subjs)
  1986  
  1987  				if offset > len(subjs) {
  1988  					offset = len(subjs)
  1989  				}
  1990  
  1991  				end := offset + JSMaxSubjectDetails
  1992  				if end > len(subjs) {
  1993  					end = len(subjs)
  1994  				}
  1995  				actualSize := end - offset
  1996  				var sd map[string]uint64
  1997  
  1998  				if actualSize > 0 {
  1999  					sd = make(map[string]uint64, actualSize)
  2000  					for _, ss := range subjs[offset:end] {
  2001  						sd[ss] = st[ss]
  2002  					}
  2003  				}
  2004  				resp.StreamInfo.State.Subjects = sd
  2005  			}
  2006  		}
  2007  	}
  2008  	// Check for out of band catchups.
  2009  	if mset.hasCatchupPeers() {
  2010  		mset.checkClusterInfo(resp.StreamInfo.Cluster)
  2011  	}
  2012  
  2013  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  2014  }
  2015  
  2016  // Request to have a stream leader stepdown.
  2017  func (s *Server) jsStreamLeaderStepDownRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  2018  	if c == nil || !s.JetStreamEnabled() {
  2019  		return
  2020  	}
  2021  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  2022  	if err != nil {
  2023  		s.Warnf(badAPIRequestT, msg)
  2024  		return
  2025  	}
  2026  
  2027  	// Have extra token for this one.
  2028  	name := tokenAt(subject, 6)
  2029  
  2030  	var resp = JSApiStreamLeaderStepDownResponse{ApiResponse: ApiResponse{Type: JSApiStreamLeaderStepDownResponseType}}
  2031  
  2032  	// If we are not in clustered mode this is a failed request.
  2033  	if !s.JetStreamIsClustered() {
  2034  		resp.Error = NewJSClusterRequiredError()
  2035  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2036  		return
  2037  	}
  2038  
  2039  	// If we are here we are clustered. See if we are the stream leader in order to proceed.
  2040  	js, cc := s.getJetStreamCluster()
  2041  	if js == nil || cc == nil {
  2042  		return
  2043  	}
  2044  	if js.isLeaderless() {
  2045  		resp.Error = NewJSClusterNotAvailError()
  2046  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2047  		return
  2048  	}
  2049  
  2050  	js.mu.RLock()
  2051  	isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, name)
  2052  	js.mu.RUnlock()
  2053  
  2054  	if isLeader && sa == nil {
  2055  		resp.Error = NewJSStreamNotFoundError()
  2056  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2057  		return
  2058  	} else if sa == nil {
  2059  		return
  2060  	}
  2061  
  2062  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  2063  		if doErr {
  2064  			resp.Error = NewJSNotEnabledForAccountError()
  2065  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2066  		}
  2067  		return
  2068  	}
  2069  	if !isEmptyRequest(msg) {
  2070  		resp.Error = NewJSBadRequestError()
  2071  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2072  		return
  2073  	}
  2074  
  2075  	// Check to see if we are a member of the group and if the group has no leader.
  2076  	if js.isGroupLeaderless(sa.Group) {
  2077  		resp.Error = NewJSClusterNotAvailError()
  2078  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2079  		return
  2080  	}
  2081  
  2082  	// We have the stream assigned and a leader, so only the stream leader should answer.
  2083  	if !acc.JetStreamIsStreamLeader(name) {
  2084  		return
  2085  	}
  2086  
  2087  	mset, err := acc.lookupStream(name)
  2088  	if err != nil {
  2089  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  2090  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2091  		return
  2092  	}
  2093  
  2094  	if mset == nil {
  2095  		resp.Success = true
  2096  		s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  2097  		return
  2098  	}
  2099  
  2100  	// Call actual stepdown. Do this in a Go routine.
  2101  	go func() {
  2102  		if node := mset.raftNode(); node != nil {
  2103  			mset.setLeader(false)
  2104  			// TODO (mh) eventually make sure all go routines exited and all channels are cleared
  2105  			time.Sleep(250 * time.Millisecond)
  2106  			node.StepDown()
  2107  		}
  2108  
  2109  		resp.Success = true
  2110  		s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  2111  	}()
  2112  }
  2113  
  2114  // Request to have a consumer leader stepdown.
  2115  func (s *Server) jsConsumerLeaderStepDownRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  2116  	if c == nil || !s.JetStreamEnabled() {
  2117  		return
  2118  	}
  2119  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  2120  	if err != nil {
  2121  		s.Warnf(badAPIRequestT, msg)
  2122  		return
  2123  	}
  2124  
  2125  	var resp = JSApiConsumerLeaderStepDownResponse{ApiResponse: ApiResponse{Type: JSApiConsumerLeaderStepDownResponseType}}
  2126  
  2127  	// If we are not in clustered mode this is a failed request.
  2128  	if !s.JetStreamIsClustered() {
  2129  		resp.Error = NewJSClusterRequiredError()
  2130  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2131  		return
  2132  	}
  2133  
  2134  	// If we are here we are clustered. See if we are the stream leader in order to proceed.
  2135  	js, cc := s.getJetStreamCluster()
  2136  	if js == nil || cc == nil {
  2137  		return
  2138  	}
  2139  	if js.isLeaderless() {
  2140  		resp.Error = NewJSClusterNotAvailError()
  2141  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2142  		return
  2143  	}
  2144  
  2145  	// Have extra token for this one.
  2146  	stream := tokenAt(subject, 6)
  2147  	consumer := tokenAt(subject, 7)
  2148  
  2149  	js.mu.RLock()
  2150  	isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, stream)
  2151  	js.mu.RUnlock()
  2152  
  2153  	if isLeader && sa == nil {
  2154  		resp.Error = NewJSStreamNotFoundError()
  2155  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2156  		return
  2157  	} else if sa == nil {
  2158  		return
  2159  	}
  2160  	var ca *consumerAssignment
  2161  	if sa.consumers != nil {
  2162  		ca = sa.consumers[consumer]
  2163  	}
  2164  	if ca == nil {
  2165  		resp.Error = NewJSConsumerNotFoundError()
  2166  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2167  		return
  2168  	}
  2169  	// Check to see if we are a member of the group and if the group has no leader.
  2170  	if js.isGroupLeaderless(ca.Group) {
  2171  		resp.Error = NewJSClusterNotAvailError()
  2172  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2173  		return
  2174  	}
  2175  
  2176  	if !acc.JetStreamIsConsumerLeader(stream, consumer) {
  2177  		return
  2178  	}
  2179  
  2180  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  2181  		if doErr {
  2182  			resp.Error = NewJSNotEnabledForAccountError()
  2183  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2184  		}
  2185  		return
  2186  	}
  2187  	if !isEmptyRequest(msg) {
  2188  		resp.Error = NewJSBadRequestError()
  2189  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2190  		return
  2191  	}
  2192  
  2193  	mset, err := acc.lookupStream(stream)
  2194  	if err != nil {
  2195  		resp.Error = NewJSStreamNotFoundError()
  2196  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2197  		return
  2198  	}
  2199  	o := mset.lookupConsumer(consumer)
  2200  	if o == nil {
  2201  		resp.Error = NewJSConsumerNotFoundError()
  2202  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2203  		return
  2204  	}
  2205  
  2206  	n := o.raftNode()
  2207  	if n == nil {
  2208  		resp.Success = true
  2209  		s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  2210  		return
  2211  	}
  2212  
  2213  	// Call actual stepdown. Do this in a Go routine.
  2214  	go func() {
  2215  		o.setLeader(false)
  2216  		// TODO (mh) eventually make sure all go routines exited and all channels are cleared
  2217  		time.Sleep(250 * time.Millisecond)
  2218  		n.StepDown()
  2219  
  2220  		resp.Success = true
  2221  		s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  2222  	}()
  2223  }
  2224  
  2225  // Request to remove a peer from a clustered stream.
  2226  func (s *Server) jsStreamRemovePeerRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  2227  	if c == nil || !s.JetStreamEnabled() {
  2228  		return
  2229  	}
  2230  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  2231  	if err != nil {
  2232  		s.Warnf(badAPIRequestT, msg)
  2233  		return
  2234  	}
  2235  
  2236  	// Have extra token for this one.
  2237  	name := tokenAt(subject, 6)
  2238  
  2239  	var resp = JSApiStreamRemovePeerResponse{ApiResponse: ApiResponse{Type: JSApiStreamRemovePeerResponseType}}
  2240  
  2241  	// If we are not in clustered mode this is a failed request.
  2242  	if !s.JetStreamIsClustered() {
  2243  		resp.Error = NewJSClusterRequiredError()
  2244  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2245  		return
  2246  	}
  2247  
  2248  	// If we are here we are clustered. See if we are the stream leader in order to proceed.
  2249  	js, cc := s.getJetStreamCluster()
  2250  	if js == nil || cc == nil {
  2251  		return
  2252  	}
  2253  	if js.isLeaderless() {
  2254  		resp.Error = NewJSClusterNotAvailError()
  2255  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2256  		return
  2257  	}
  2258  
  2259  	js.mu.RLock()
  2260  	isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, name)
  2261  	js.mu.RUnlock()
  2262  
  2263  	// Make sure we are meta leader.
  2264  	if !isLeader {
  2265  		return
  2266  	}
  2267  
  2268  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  2269  		if doErr {
  2270  			resp.Error = NewJSNotEnabledForAccountError()
  2271  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2272  		}
  2273  		return
  2274  	}
  2275  	if isEmptyRequest(msg) {
  2276  		resp.Error = NewJSBadRequestError()
  2277  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2278  		return
  2279  	}
  2280  
  2281  	var req JSApiStreamRemovePeerRequest
  2282  	if err := json.Unmarshal(msg, &req); err != nil {
  2283  		resp.Error = NewJSInvalidJSONError()
  2284  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2285  		return
  2286  	}
  2287  	if req.Peer == _EMPTY_ {
  2288  		resp.Error = NewJSBadRequestError()
  2289  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2290  		return
  2291  	}
  2292  
  2293  	if sa == nil {
  2294  		// No stream present.
  2295  		resp.Error = NewJSStreamNotFoundError()
  2296  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2297  		return
  2298  	}
  2299  
  2300  	// Check to see if we are a member of the group and if the group has no leader.
  2301  	// Peers here is a server name, convert to node name.
  2302  	nodeName := getHash(req.Peer)
  2303  
  2304  	js.mu.RLock()
  2305  	rg := sa.Group
  2306  	isMember := rg.isMember(nodeName)
  2307  	js.mu.RUnlock()
  2308  
  2309  	// Make sure we are a member.
  2310  	if !isMember {
  2311  		resp.Error = NewJSClusterPeerNotMemberError()
  2312  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2313  		return
  2314  	}
  2315  
  2316  	// If we are here we have a valid peer member set for removal.
  2317  	if !js.removePeerFromStream(sa, nodeName) {
  2318  		resp.Error = NewJSPeerRemapError()
  2319  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2320  		return
  2321  	}
  2322  
  2323  	resp.Success = true
  2324  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  2325  }
  2326  
  2327  // Request to have the metaleader remove a peer from the system.
  2328  func (s *Server) jsLeaderServerRemoveRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  2329  	if c == nil || !s.JetStreamEnabled() {
  2330  		return
  2331  	}
  2332  
  2333  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  2334  	if err != nil {
  2335  		s.Warnf(badAPIRequestT, msg)
  2336  		return
  2337  	}
  2338  
  2339  	js, cc := s.getJetStreamCluster()
  2340  	if js == nil || cc == nil || cc.meta == nil {
  2341  		return
  2342  	}
  2343  
  2344  	// Extra checks here but only leader is listening.
  2345  	js.mu.RLock()
  2346  	isLeader := cc.isLeader()
  2347  	js.mu.RUnlock()
  2348  
  2349  	if !isLeader {
  2350  		return
  2351  	}
  2352  
  2353  	var resp = JSApiMetaServerRemoveResponse{ApiResponse: ApiResponse{Type: JSApiMetaServerRemoveResponseType}}
  2354  
  2355  	if isEmptyRequest(msg) {
  2356  		resp.Error = NewJSBadRequestError()
  2357  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2358  		return
  2359  	}
  2360  
  2361  	var req JSApiMetaServerRemoveRequest
  2362  	if err := json.Unmarshal(msg, &req); err != nil {
  2363  		resp.Error = NewJSInvalidJSONError()
  2364  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2365  		return
  2366  	}
  2367  
  2368  	var found string
  2369  	js.mu.RLock()
  2370  	for _, p := range cc.meta.Peers() {
  2371  		// If Peer is specified, it takes precedence
  2372  		if req.Peer != _EMPTY_ {
  2373  			if p.ID == req.Peer {
  2374  				found = req.Peer
  2375  				break
  2376  			}
  2377  			continue
  2378  		}
  2379  		si, ok := s.nodeToInfo.Load(p.ID)
  2380  		if ok && si.(nodeInfo).name == req.Server {
  2381  			found = p.ID
  2382  			break
  2383  		}
  2384  	}
  2385  	js.mu.RUnlock()
  2386  
  2387  	if found == _EMPTY_ {
  2388  		resp.Error = NewJSClusterServerNotMemberError()
  2389  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2390  		return
  2391  	}
  2392  
  2393  	// So we have a valid peer.
  2394  	js.mu.Lock()
  2395  	cc.meta.ProposeRemovePeer(found)
  2396  	js.mu.Unlock()
  2397  
  2398  	resp.Success = true
  2399  	s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2400  }
  2401  
  2402  func (s *Server) peerSetToNames(ps []string) []string {
  2403  	names := make([]string, len(ps))
  2404  	for i := 0; i < len(ps); i++ {
  2405  		if si, ok := s.nodeToInfo.Load(ps[i]); !ok {
  2406  			names[i] = ps[i]
  2407  		} else {
  2408  			names[i] = si.(nodeInfo).name
  2409  		}
  2410  	}
  2411  	return names
  2412  }
  2413  
  2414  // looks up the peer id for a given server name. Cluster and domain name are optional filter criteria
  2415  func (s *Server) nameToPeer(js *jetStream, serverName, clusterName, domainName string) string {
  2416  	js.mu.RLock()
  2417  	defer js.mu.RUnlock()
  2418  	if cc := js.cluster; cc != nil {
  2419  		for _, p := range cc.meta.Peers() {
  2420  			si, ok := s.nodeToInfo.Load(p.ID)
  2421  			if ok && si.(nodeInfo).name == serverName {
  2422  				if clusterName == _EMPTY_ || clusterName == si.(nodeInfo).cluster {
  2423  					if domainName == _EMPTY_ || domainName == si.(nodeInfo).domain {
  2424  						return p.ID
  2425  					}
  2426  				}
  2427  			}
  2428  		}
  2429  	}
  2430  	return _EMPTY_
  2431  }
  2432  
  2433  // Request to have the metaleader move a stream on a peer to another
  2434  func (s *Server) jsLeaderServerStreamMoveRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  2435  	if c == nil || !s.JetStreamEnabled() {
  2436  		return
  2437  	}
  2438  
  2439  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  2440  	if err != nil {
  2441  		s.Warnf(badAPIRequestT, msg)
  2442  		return
  2443  	}
  2444  
  2445  	js, cc := s.getJetStreamCluster()
  2446  	if js == nil || cc == nil || cc.meta == nil {
  2447  		return
  2448  	}
  2449  
  2450  	// Extra checks here but only leader is listening.
  2451  	js.mu.RLock()
  2452  	isLeader := cc.isLeader()
  2453  	js.mu.RUnlock()
  2454  
  2455  	if !isLeader {
  2456  		return
  2457  	}
  2458  
  2459  	accName := tokenAt(subject, 6)
  2460  	streamName := tokenAt(subject, 7)
  2461  
  2462  	var resp = JSApiStreamUpdateResponse{ApiResponse: ApiResponse{Type: JSApiStreamUpdateResponseType}}
  2463  
  2464  	var req JSApiMetaServerStreamMoveRequest
  2465  	if err := json.Unmarshal(msg, &req); err != nil {
  2466  		resp.Error = NewJSInvalidJSONError()
  2467  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2468  		return
  2469  	}
  2470  
  2471  	srcPeer := _EMPTY_
  2472  	if req.Server != _EMPTY_ {
  2473  		srcPeer = s.nameToPeer(js, req.Server, req.Cluster, req.Domain)
  2474  	}
  2475  
  2476  	targetAcc, ok := s.accounts.Load(accName)
  2477  	if !ok {
  2478  		resp.Error = NewJSNoAccountError()
  2479  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2480  		return
  2481  	}
  2482  
  2483  	var streamFound bool
  2484  	cfg := StreamConfig{}
  2485  	currPeers := []string{}
  2486  	currCluster := _EMPTY_
  2487  	js.mu.Lock()
  2488  	streams, ok := cc.streams[accName]
  2489  	if ok {
  2490  		sa, ok := streams[streamName]
  2491  		if ok {
  2492  			cfg = *sa.Config
  2493  			streamFound = true
  2494  			currPeers = sa.Group.Peers
  2495  			currCluster = sa.Group.Cluster
  2496  		}
  2497  	}
  2498  	js.mu.Unlock()
  2499  
  2500  	if !streamFound {
  2501  		resp.Error = NewJSStreamNotFoundError()
  2502  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2503  		return
  2504  	}
  2505  
  2506  	// if server was picked, make sure src peer exists and move it to first position.
  2507  	// removal will drop peers from the left
  2508  	if req.Server != _EMPTY_ {
  2509  		if srcPeer == _EMPTY_ {
  2510  			resp.Error = NewJSClusterServerNotMemberError()
  2511  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2512  			return
  2513  		}
  2514  		var peerFound bool
  2515  		for i := 0; i < len(currPeers); i++ {
  2516  			if currPeers[i] == srcPeer {
  2517  				copy(currPeers[1:], currPeers[:i])
  2518  				currPeers[0] = srcPeer
  2519  				peerFound = true
  2520  				break
  2521  			}
  2522  		}
  2523  		if !peerFound {
  2524  			resp.Error = NewJSClusterPeerNotMemberError()
  2525  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2526  			return
  2527  		}
  2528  	}
  2529  
  2530  	// make sure client is scoped to requested account
  2531  	ciNew := *(ci)
  2532  	ciNew.Account = accName
  2533  
  2534  	// backup placement such that peers can be looked up with modified tag list
  2535  	var origPlacement *Placement
  2536  	if cfg.Placement != nil {
  2537  		tmp := *cfg.Placement
  2538  		origPlacement = &tmp
  2539  	}
  2540  
  2541  	if len(req.Tags) > 0 {
  2542  		if cfg.Placement == nil {
  2543  			cfg.Placement = &Placement{}
  2544  		}
  2545  		cfg.Placement.Tags = append(cfg.Placement.Tags, req.Tags...)
  2546  	}
  2547  
  2548  	peers, e := cc.selectPeerGroup(cfg.Replicas+1, currCluster, &cfg, currPeers, 1, nil)
  2549  	if len(peers) <= cfg.Replicas {
  2550  		// since expanding in the same cluster did not yield a result, try in different cluster
  2551  		peers = nil
  2552  
  2553  		clusters := map[string]struct{}{}
  2554  		s.nodeToInfo.Range(func(_, ni any) bool {
  2555  			if currCluster != ni.(nodeInfo).cluster {
  2556  				clusters[ni.(nodeInfo).cluster] = struct{}{}
  2557  			}
  2558  			return true
  2559  		})
  2560  		errs := &selectPeerError{}
  2561  		errs.accumulate(e)
  2562  		for cluster := range clusters {
  2563  			newPeers, e := cc.selectPeerGroup(cfg.Replicas, cluster, &cfg, nil, 0, nil)
  2564  			if len(newPeers) >= cfg.Replicas {
  2565  				peers = append([]string{}, currPeers...)
  2566  				peers = append(peers, newPeers[:cfg.Replicas]...)
  2567  				break
  2568  			}
  2569  			errs.accumulate(e)
  2570  		}
  2571  		if peers == nil {
  2572  			resp.Error = NewJSClusterNoPeersError(errs)
  2573  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2574  			return
  2575  		}
  2576  	}
  2577  
  2578  	cfg.Placement = origPlacement
  2579  
  2580  	s.Noticef("Requested move for stream '%s > %s' R=%d from %+v to %+v",
  2581  		streamName, accName, cfg.Replicas, s.peerSetToNames(currPeers), s.peerSetToNames(peers))
  2582  
  2583  	// We will always have peers and therefore never do a callout, therefore it is safe to call inline
  2584  	s.jsClusteredStreamUpdateRequest(&ciNew, targetAcc.(*Account), subject, reply, rmsg, &cfg, peers)
  2585  }
  2586  
  2587  // Request to have the metaleader move a stream on a peer to another
  2588  func (s *Server) jsLeaderServerStreamCancelMoveRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  2589  	if c == nil || !s.JetStreamEnabled() {
  2590  		return
  2591  	}
  2592  
  2593  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  2594  	if err != nil {
  2595  		s.Warnf(badAPIRequestT, msg)
  2596  		return
  2597  	}
  2598  
  2599  	js, cc := s.getJetStreamCluster()
  2600  	if js == nil || cc == nil || cc.meta == nil {
  2601  		return
  2602  	}
  2603  
  2604  	// Extra checks here but only leader is listening.
  2605  	js.mu.RLock()
  2606  	isLeader := cc.isLeader()
  2607  	js.mu.RUnlock()
  2608  
  2609  	if !isLeader {
  2610  		return
  2611  	}
  2612  
  2613  	var resp = JSApiStreamUpdateResponse{ApiResponse: ApiResponse{Type: JSApiStreamUpdateResponseType}}
  2614  
  2615  	accName := tokenAt(subject, 6)
  2616  	streamName := tokenAt(subject, 7)
  2617  
  2618  	targetAcc, ok := s.accounts.Load(accName)
  2619  	if !ok {
  2620  		resp.Error = NewJSNoAccountError()
  2621  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2622  		return
  2623  	}
  2624  
  2625  	streamFound := false
  2626  	cfg := StreamConfig{}
  2627  	currPeers := []string{}
  2628  	js.mu.Lock()
  2629  	streams, ok := cc.streams[accName]
  2630  	if ok {
  2631  		sa, ok := streams[streamName]
  2632  		if ok {
  2633  			cfg = *sa.Config
  2634  			streamFound = true
  2635  			currPeers = sa.Group.Peers
  2636  		}
  2637  	}
  2638  	js.mu.Unlock()
  2639  
  2640  	if !streamFound {
  2641  		resp.Error = NewJSStreamNotFoundError()
  2642  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2643  		return
  2644  	}
  2645  
  2646  	if len(currPeers) <= cfg.Replicas {
  2647  		resp.Error = NewJSStreamMoveNotInProgressError()
  2648  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2649  		return
  2650  	}
  2651  
  2652  	// make sure client is scoped to requested account
  2653  	ciNew := *(ci)
  2654  	ciNew.Account = accName
  2655  
  2656  	peers := currPeers[:cfg.Replicas]
  2657  
  2658  	// Remove placement in case tags don't match
  2659  	// This can happen if the move was initiated by modifying the tags.
  2660  	// This is an account operation.
  2661  	// This can NOT happen when the move was initiated by the system account.
  2662  	// There move honors the original tag list.
  2663  	if cfg.Placement != nil && len(cfg.Placement.Tags) != 0 {
  2664  	FOR_TAGCHECK:
  2665  		for _, peer := range peers {
  2666  			si, ok := s.nodeToInfo.Load(peer)
  2667  			if !ok {
  2668  				// can't verify tags, do the safe thing and error
  2669  				resp.Error = NewJSStreamGeneralError(
  2670  					fmt.Errorf("peer %s not present for tag validation", peer))
  2671  				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2672  				return
  2673  			}
  2674  			nodeTags := si.(nodeInfo).tags
  2675  			for _, tag := range cfg.Placement.Tags {
  2676  				if !nodeTags.Contains(tag) {
  2677  					// clear placement as tags don't match
  2678  					cfg.Placement = nil
  2679  					break FOR_TAGCHECK
  2680  				}
  2681  			}
  2682  
  2683  		}
  2684  	}
  2685  
  2686  	s.Noticef("Requested cancel of move: R=%d '%s > %s' to peer set %+v and restore previous peer set %+v",
  2687  		cfg.Replicas, streamName, accName, s.peerSetToNames(currPeers), s.peerSetToNames(peers))
  2688  
  2689  	// We will always have peers and therefore never do a callout, therefore it is safe to call inline
  2690  	s.jsClusteredStreamUpdateRequest(&ciNew, targetAcc.(*Account), subject, reply, rmsg, &cfg, peers)
  2691  }
  2692  
  2693  // Request to have an account purged
  2694  func (s *Server) jsLeaderAccountPurgeRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  2695  	if c == nil || !s.JetStreamEnabled() {
  2696  		return
  2697  	}
  2698  
  2699  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  2700  	if err != nil {
  2701  		s.Warnf(badAPIRequestT, msg)
  2702  		return
  2703  	}
  2704  
  2705  	js := s.getJetStream()
  2706  	if js == nil {
  2707  		return
  2708  	}
  2709  
  2710  	accName := tokenAt(subject, 5)
  2711  
  2712  	var resp = JSApiAccountPurgeResponse{ApiResponse: ApiResponse{Type: JSApiAccountPurgeResponseType}}
  2713  
  2714  	if !s.JetStreamIsClustered() {
  2715  		var streams []*stream
  2716  		var ac *Account
  2717  		if ac, err = s.lookupAccount(accName); err == nil && ac != nil {
  2718  			streams = ac.streams()
  2719  		}
  2720  
  2721  		s.Noticef("Purge request for account %s (streams: %d, hasAccount: %t)",
  2722  			accName, len(streams), ac != nil)
  2723  
  2724  		for _, mset := range streams {
  2725  			err := mset.delete()
  2726  			if err != nil {
  2727  				resp.Error = NewJSStreamDeleteError(err)
  2728  				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2729  				return
  2730  			}
  2731  		}
  2732  		if err := os.RemoveAll(filepath.Join(js.config.StoreDir, accName)); err != nil {
  2733  			resp.Error = NewJSStreamGeneralError(err)
  2734  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2735  			return
  2736  		}
  2737  		resp.Initiated = true
  2738  		s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2739  		return
  2740  	}
  2741  
  2742  	_, cc := s.getJetStreamCluster()
  2743  	if cc == nil || cc.meta == nil || !cc.isLeader() {
  2744  		return
  2745  	}
  2746  
  2747  	if js.isMetaRecovering() {
  2748  		// While in recovery mode, the data structures are not fully initialized
  2749  		resp.Error = NewJSClusterNotAvailError()
  2750  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2751  		return
  2752  	}
  2753  
  2754  	js.mu.RLock()
  2755  	ns, nc := 0, 0
  2756  	streams, hasAccount := cc.streams[accName]
  2757  	for _, osa := range streams {
  2758  		for _, oca := range osa.consumers {
  2759  			oca.deleted = true
  2760  			ca := &consumerAssignment{Group: oca.Group, Stream: oca.Stream, Name: oca.Name, Config: oca.Config, Subject: subject, Client: oca.Client}
  2761  			cc.meta.Propose(encodeDeleteConsumerAssignment(ca))
  2762  			nc++
  2763  		}
  2764  		sa := &streamAssignment{Group: osa.Group, Config: osa.Config, Subject: subject, Client: osa.Client}
  2765  		cc.meta.Propose(encodeDeleteStreamAssignment(sa))
  2766  		ns++
  2767  	}
  2768  	js.mu.RUnlock()
  2769  
  2770  	s.Noticef("Purge request for account %s (streams: %d, consumer: %d, hasAccount: %t)", accName, ns, nc, hasAccount)
  2771  
  2772  	resp.Initiated = true
  2773  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2774  }
  2775  
  2776  // Request to have the meta leader stepdown.
  2777  // These will only be received by the meta leader, so less checking needed.
  2778  func (s *Server) jsLeaderStepDownRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  2779  	if c == nil || !s.JetStreamEnabled() {
  2780  		return
  2781  	}
  2782  
  2783  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  2784  	if err != nil {
  2785  		s.Warnf(badAPIRequestT, msg)
  2786  		return
  2787  	}
  2788  
  2789  	js, cc := s.getJetStreamCluster()
  2790  	if js == nil || cc == nil || cc.meta == nil {
  2791  		return
  2792  	}
  2793  
  2794  	// Extra checks here but only leader is listening.
  2795  	js.mu.RLock()
  2796  	isLeader := cc.isLeader()
  2797  	js.mu.RUnlock()
  2798  
  2799  	if !isLeader {
  2800  		return
  2801  	}
  2802  
  2803  	var preferredLeader string
  2804  	var resp = JSApiLeaderStepDownResponse{ApiResponse: ApiResponse{Type: JSApiLeaderStepDownResponseType}}
  2805  
  2806  	if !isEmptyRequest(msg) {
  2807  		var req JSApiLeaderStepdownRequest
  2808  		if err := json.Unmarshal(msg, &req); err != nil {
  2809  			resp.Error = NewJSInvalidJSONError()
  2810  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2811  			return
  2812  		}
  2813  		if len(req.Placement.Tags) > 0 {
  2814  			// Tags currently not supported.
  2815  			resp.Error = NewJSClusterTagsError()
  2816  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2817  			return
  2818  		}
  2819  		cn := req.Placement.Cluster
  2820  		var peers []string
  2821  		ourID := cc.meta.ID()
  2822  		for _, p := range cc.meta.Peers() {
  2823  			if si, ok := s.nodeToInfo.Load(p.ID); ok && si != nil {
  2824  				if ni := si.(nodeInfo); ni.offline || ni.cluster != cn || p.ID == ourID {
  2825  					continue
  2826  				}
  2827  				peers = append(peers, p.ID)
  2828  			}
  2829  		}
  2830  		if len(peers) == 0 {
  2831  			resp.Error = NewJSClusterNoPeersError(fmt.Errorf("no replacement peer connected"))
  2832  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2833  			return
  2834  		}
  2835  		// Randomize and select.
  2836  		if len(peers) > 1 {
  2837  			rand.Shuffle(len(peers), func(i, j int) { peers[i], peers[j] = peers[j], peers[i] })
  2838  		}
  2839  		preferredLeader = peers[0]
  2840  	}
  2841  
  2842  	// Call actual stepdown.
  2843  	err = cc.meta.StepDown(preferredLeader)
  2844  	if err != nil {
  2845  		resp.Error = NewJSRaftGeneralError(err, Unless(err))
  2846  	} else {
  2847  		resp.Success = true
  2848  	}
  2849  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  2850  }
  2851  
  2852  func isEmptyRequest(req []byte) bool {
  2853  	if len(req) == 0 {
  2854  		return true
  2855  	}
  2856  	if bytes.Equal(req, []byte("{}")) {
  2857  		return true
  2858  	}
  2859  	// If we are here we didn't get our simple match, but still could be valid.
  2860  	var v any
  2861  	if err := json.Unmarshal(req, &v); err != nil {
  2862  		return false
  2863  	}
  2864  	vm, ok := v.(map[string]any)
  2865  	if !ok {
  2866  		return false
  2867  	}
  2868  	return len(vm) == 0
  2869  }
  2870  
  2871  // Request to delete a stream.
  2872  func (s *Server) jsStreamDeleteRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  2873  	if c == nil || !s.JetStreamEnabled() {
  2874  		return
  2875  	}
  2876  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  2877  	if err != nil {
  2878  		s.Warnf(badAPIRequestT, msg)
  2879  		return
  2880  	}
  2881  
  2882  	var resp = JSApiStreamDeleteResponse{ApiResponse: ApiResponse{Type: JSApiStreamDeleteResponseType}}
  2883  
  2884  	// Determine if we should proceed here when we are in clustered mode.
  2885  	if s.JetStreamIsClustered() {
  2886  		js, cc := s.getJetStreamCluster()
  2887  		if js == nil || cc == nil {
  2888  			return
  2889  		}
  2890  		if js.isLeaderless() {
  2891  			resp.Error = NewJSClusterNotAvailError()
  2892  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2893  			return
  2894  		}
  2895  		// Make sure we are meta leader.
  2896  		if !s.JetStreamIsLeader() {
  2897  			return
  2898  		}
  2899  	}
  2900  
  2901  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  2902  		if doErr {
  2903  			resp.Error = NewJSNotEnabledForAccountError()
  2904  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2905  		}
  2906  		return
  2907  	}
  2908  
  2909  	if !isEmptyRequest(msg) {
  2910  		resp.Error = NewJSNotEmptyRequestError()
  2911  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2912  		return
  2913  	}
  2914  	stream := streamNameFromSubject(subject)
  2915  
  2916  	// Clustered.
  2917  	if s.JetStreamIsClustered() {
  2918  		s.jsClusteredStreamDeleteRequest(ci, acc, stream, subject, reply, msg)
  2919  		return
  2920  	}
  2921  
  2922  	mset, err := acc.lookupStream(stream)
  2923  	if err != nil {
  2924  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  2925  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2926  		return
  2927  	}
  2928  
  2929  	if err := mset.delete(); err != nil {
  2930  		resp.Error = NewJSStreamDeleteError(err, Unless(err))
  2931  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2932  		return
  2933  	}
  2934  	resp.Success = true
  2935  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  2936  }
  2937  
  2938  // Request to delete a message.
  2939  // This expects a stream sequence number as the msg body.
  2940  func (s *Server) jsMsgDeleteRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  2941  	if c == nil || !s.JetStreamEnabled() {
  2942  		return
  2943  	}
  2944  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  2945  	if err != nil {
  2946  		s.Warnf(badAPIRequestT, msg)
  2947  		return
  2948  	}
  2949  
  2950  	stream := tokenAt(subject, 6)
  2951  
  2952  	var resp = JSApiMsgDeleteResponse{ApiResponse: ApiResponse{Type: JSApiMsgDeleteResponseType}}
  2953  
  2954  	// If we are in clustered mode we need to be the stream leader to proceed.
  2955  	if s.JetStreamIsClustered() {
  2956  		// Check to make sure the stream is assigned.
  2957  		js, cc := s.getJetStreamCluster()
  2958  		if js == nil || cc == nil {
  2959  			return
  2960  		}
  2961  		if js.isLeaderless() {
  2962  			resp.Error = NewJSClusterNotAvailError()
  2963  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2964  			return
  2965  		}
  2966  
  2967  		js.mu.RLock()
  2968  		isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, stream)
  2969  		js.mu.RUnlock()
  2970  
  2971  		if isLeader && sa == nil {
  2972  			// We can't find the stream, so mimic what would be the errors below.
  2973  			if hasJS, doErr := acc.checkJetStream(); !hasJS {
  2974  				if doErr {
  2975  					resp.Error = NewJSNotEnabledForAccountError()
  2976  					s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2977  				}
  2978  				return
  2979  			}
  2980  			// No stream present.
  2981  			resp.Error = NewJSStreamNotFoundError()
  2982  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2983  			return
  2984  		} else if sa == nil {
  2985  			return
  2986  		}
  2987  
  2988  		// Check to see if we are a member of the group and if the group has no leader.
  2989  		if js.isGroupLeaderless(sa.Group) {
  2990  			resp.Error = NewJSClusterNotAvailError()
  2991  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  2992  			return
  2993  		}
  2994  
  2995  		// We have the stream assigned and a leader, so only the stream leader should answer.
  2996  		if !acc.JetStreamIsStreamLeader(stream) {
  2997  			return
  2998  		}
  2999  	}
  3000  
  3001  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  3002  		if doErr {
  3003  			resp.Error = NewJSNotEnabledForAccountError()
  3004  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3005  		}
  3006  		return
  3007  	}
  3008  	if isEmptyRequest(msg) {
  3009  		resp.Error = NewJSBadRequestError()
  3010  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3011  		return
  3012  	}
  3013  	var req JSApiMsgDeleteRequest
  3014  	if err := json.Unmarshal(msg, &req); err != nil {
  3015  		resp.Error = NewJSInvalidJSONError()
  3016  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3017  		return
  3018  	}
  3019  
  3020  	mset, err := acc.lookupStream(stream)
  3021  	if err != nil {
  3022  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  3023  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3024  		return
  3025  	}
  3026  	if mset.cfg.Sealed {
  3027  		resp.Error = NewJSStreamSealedError()
  3028  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3029  		return
  3030  	}
  3031  	if mset.cfg.DenyDelete {
  3032  		resp.Error = NewJSStreamMsgDeleteFailedError(errors.New("message delete not permitted"))
  3033  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3034  		return
  3035  	}
  3036  
  3037  	if s.JetStreamIsClustered() {
  3038  		s.jsClusteredMsgDeleteRequest(ci, acc, mset, stream, subject, reply, &req, rmsg)
  3039  		return
  3040  	}
  3041  
  3042  	var removed bool
  3043  	if req.NoErase {
  3044  		removed, err = mset.removeMsg(req.Seq)
  3045  	} else {
  3046  		removed, err = mset.eraseMsg(req.Seq)
  3047  	}
  3048  	if err != nil {
  3049  		resp.Error = NewJSStreamMsgDeleteFailedError(err, Unless(err))
  3050  	} else if !removed {
  3051  		resp.Error = NewJSSequenceNotFoundError(req.Seq)
  3052  	} else {
  3053  		resp.Success = true
  3054  	}
  3055  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  3056  }
  3057  
  3058  // Request to get a raw stream message.
  3059  func (s *Server) jsMsgGetRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  3060  	if c == nil || !s.JetStreamEnabled() {
  3061  		return
  3062  	}
  3063  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  3064  	if err != nil {
  3065  		s.Warnf(badAPIRequestT, msg)
  3066  		return
  3067  	}
  3068  
  3069  	stream := tokenAt(subject, 6)
  3070  
  3071  	var resp = JSApiMsgGetResponse{ApiResponse: ApiResponse{Type: JSApiMsgGetResponseType}}
  3072  
  3073  	// If we are in clustered mode we need to be the stream leader to proceed.
  3074  	if s.JetStreamIsClustered() {
  3075  		// Check to make sure the stream is assigned.
  3076  		js, cc := s.getJetStreamCluster()
  3077  		if js == nil || cc == nil {
  3078  			return
  3079  		}
  3080  		if js.isLeaderless() {
  3081  			resp.Error = NewJSClusterNotAvailError()
  3082  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3083  			return
  3084  		}
  3085  
  3086  		js.mu.RLock()
  3087  		isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, stream)
  3088  		js.mu.RUnlock()
  3089  
  3090  		if isLeader && sa == nil {
  3091  			// We can't find the stream, so mimic what would be the errors below.
  3092  			if hasJS, doErr := acc.checkJetStream(); !hasJS {
  3093  				if doErr {
  3094  					resp.Error = NewJSNotEnabledForAccountError()
  3095  					s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3096  				}
  3097  				return
  3098  			}
  3099  			// No stream present.
  3100  			resp.Error = NewJSStreamNotFoundError()
  3101  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3102  			return
  3103  		} else if sa == nil {
  3104  			return
  3105  		}
  3106  
  3107  		// Check to see if we are a member of the group and if the group has no leader.
  3108  		if js.isGroupLeaderless(sa.Group) {
  3109  			resp.Error = NewJSClusterNotAvailError()
  3110  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3111  			return
  3112  		}
  3113  
  3114  		// We have the stream assigned and a leader, so only the stream leader should answer.
  3115  		if !acc.JetStreamIsStreamLeader(stream) {
  3116  			return
  3117  		}
  3118  	}
  3119  
  3120  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  3121  		if doErr {
  3122  			resp.Error = NewJSNotEnabledForAccountError()
  3123  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3124  		}
  3125  		return
  3126  	}
  3127  	if isEmptyRequest(msg) {
  3128  		resp.Error = NewJSBadRequestError()
  3129  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3130  		return
  3131  	}
  3132  	var req JSApiMsgGetRequest
  3133  	if err := json.Unmarshal(msg, &req); err != nil {
  3134  		resp.Error = NewJSInvalidJSONError()
  3135  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3136  		return
  3137  	}
  3138  
  3139  	// This version does not support batch.
  3140  	if req.Batch > 0 || req.MaxBytes > 0 {
  3141  		resp.Error = NewJSBadRequestError()
  3142  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3143  		return
  3144  	}
  3145  
  3146  	// Validate non-conflicting options. Seq, LastFor, and AsOfTime are mutually exclusive.
  3147  	// NextFor can be paired with Seq or AsOfTime indicating a filter subject.
  3148  	if (req.Seq > 0 && req.LastFor != _EMPTY_) ||
  3149  		(req.Seq == 0 && req.LastFor == _EMPTY_ && req.NextFor == _EMPTY_ && req.StartTime == nil) ||
  3150  		(req.Seq > 0 && req.StartTime != nil) ||
  3151  		(req.StartTime != nil && req.LastFor != _EMPTY_) ||
  3152  		(req.LastFor != _EMPTY_ && req.NextFor != _EMPTY_) {
  3153  		resp.Error = NewJSBadRequestError()
  3154  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3155  		return
  3156  	}
  3157  
  3158  	mset, err := acc.lookupStream(stream)
  3159  	if err != nil {
  3160  		resp.Error = NewJSStreamNotFoundError()
  3161  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3162  		return
  3163  	}
  3164  
  3165  	var svp StoreMsg
  3166  	var sm *StoreMsg
  3167  
  3168  	// If AsOfTime is set, perform this first to get the sequence.
  3169  	var seq uint64
  3170  	if req.StartTime != nil {
  3171  		seq = mset.store.GetSeqFromTime(*req.StartTime)
  3172  	} else {
  3173  		seq = req.Seq
  3174  	}
  3175  
  3176  	if seq > 0 && req.NextFor == _EMPTY_ {
  3177  		sm, err = mset.store.LoadMsg(seq, &svp)
  3178  	} else if req.NextFor != _EMPTY_ {
  3179  		sm, _, err = mset.store.LoadNextMsg(req.NextFor, subjectHasWildcard(req.NextFor), seq, &svp)
  3180  	} else {
  3181  		sm, err = mset.store.LoadLastMsg(req.LastFor, &svp)
  3182  	}
  3183  	if err != nil {
  3184  		resp.Error = NewJSNoMessageFoundError()
  3185  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3186  		return
  3187  	}
  3188  	resp.Message = &StoredMsg{
  3189  		Subject:  sm.subj,
  3190  		Sequence: sm.seq,
  3191  		Header:   sm.hdr,
  3192  		Data:     sm.msg,
  3193  		Time:     time.Unix(0, sm.ts).UTC(),
  3194  	}
  3195  
  3196  	// Don't send response through API layer for this call.
  3197  	s.sendInternalAccountMsg(nil, reply, s.jsonResponse(resp))
  3198  }
  3199  
  3200  // Request to purge a stream.
  3201  func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  3202  	if c == nil || !s.JetStreamEnabled() {
  3203  		return
  3204  	}
  3205  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  3206  	if err != nil {
  3207  		s.Warnf(badAPIRequestT, msg)
  3208  		return
  3209  	}
  3210  
  3211  	stream := streamNameFromSubject(subject)
  3212  
  3213  	var resp = JSApiStreamPurgeResponse{ApiResponse: ApiResponse{Type: JSApiStreamPurgeResponseType}}
  3214  
  3215  	// If we are in clustered mode we need to be the stream leader to proceed.
  3216  	if s.JetStreamIsClustered() {
  3217  		// Check to make sure the stream is assigned.
  3218  		js, cc := s.getJetStreamCluster()
  3219  		if js == nil || cc == nil {
  3220  			return
  3221  		}
  3222  
  3223  		js.mu.RLock()
  3224  		isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, stream)
  3225  		js.mu.RUnlock()
  3226  
  3227  		if isLeader && sa == nil {
  3228  			// We can't find the stream, so mimic what would be the errors below.
  3229  			if hasJS, doErr := acc.checkJetStream(); !hasJS {
  3230  				if doErr {
  3231  					resp.Error = NewJSNotEnabledForAccountError()
  3232  					s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3233  				}
  3234  				return
  3235  			}
  3236  			// No stream present.
  3237  			resp.Error = NewJSStreamNotFoundError()
  3238  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3239  			return
  3240  		} else if sa == nil {
  3241  			if js.isLeaderless() {
  3242  				resp.Error = NewJSClusterNotAvailError()
  3243  				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3244  			}
  3245  			return
  3246  		}
  3247  
  3248  		// Check to see if we are a member of the group and if the group has no leader.
  3249  		if js.isGroupLeaderless(sa.Group) {
  3250  			resp.Error = NewJSClusterNotAvailError()
  3251  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3252  			return
  3253  		}
  3254  
  3255  		// We have the stream assigned and a leader, so only the stream leader should answer.
  3256  		if !acc.JetStreamIsStreamLeader(stream) {
  3257  			if js.isLeaderless() {
  3258  				resp.Error = NewJSClusterNotAvailError()
  3259  				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3260  			}
  3261  			return
  3262  		}
  3263  	}
  3264  
  3265  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  3266  		if doErr {
  3267  			resp.Error = NewJSNotEnabledForAccountError()
  3268  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3269  		}
  3270  		return
  3271  	}
  3272  
  3273  	var purgeRequest *JSApiStreamPurgeRequest
  3274  	if !isEmptyRequest(msg) {
  3275  		var req JSApiStreamPurgeRequest
  3276  		if err := json.Unmarshal(msg, &req); err != nil {
  3277  			resp.Error = NewJSInvalidJSONError()
  3278  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3279  			return
  3280  		}
  3281  		if req.Sequence > 0 && req.Keep > 0 {
  3282  			resp.Error = NewJSBadRequestError()
  3283  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3284  			return
  3285  		}
  3286  		purgeRequest = &req
  3287  	}
  3288  
  3289  	mset, err := acc.lookupStream(stream)
  3290  	if err != nil {
  3291  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  3292  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3293  		return
  3294  	}
  3295  	if mset.cfg.Sealed {
  3296  		resp.Error = NewJSStreamSealedError()
  3297  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3298  		return
  3299  	}
  3300  	if mset.cfg.DenyPurge {
  3301  		resp.Error = NewJSStreamPurgeFailedError(errors.New("stream purge not permitted"))
  3302  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3303  		return
  3304  	}
  3305  
  3306  	if s.JetStreamIsClustered() {
  3307  		s.jsClusteredStreamPurgeRequest(ci, acc, mset, stream, subject, reply, rmsg, purgeRequest)
  3308  		return
  3309  	}
  3310  
  3311  	purged, err := mset.purge(purgeRequest)
  3312  	if err != nil {
  3313  		resp.Error = NewJSStreamGeneralError(err, Unless(err))
  3314  	} else {
  3315  		resp.Purged = purged
  3316  		resp.Success = true
  3317  	}
  3318  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  3319  }
  3320  
  3321  func (acc *Account) jsNonClusteredStreamLimitsCheck(cfg *StreamConfig) *ApiError {
  3322  	selectedLimits, tier, jsa, apiErr := acc.selectLimits(cfg)
  3323  	if apiErr != nil {
  3324  		return apiErr
  3325  	}
  3326  	jsa.mu.RLock()
  3327  	defer jsa.mu.RUnlock()
  3328  	if selectedLimits.MaxStreams > 0 && jsa.countStreams(tier, cfg) >= selectedLimits.MaxStreams {
  3329  		return NewJSMaximumStreamsLimitError()
  3330  	}
  3331  	reserved := jsa.tieredReservation(tier, cfg)
  3332  	if err := jsa.js.checkAllLimits(selectedLimits, cfg, reserved, 0); err != nil {
  3333  		return NewJSStreamLimitsError(err, Unless(err))
  3334  	}
  3335  	return nil
  3336  }
  3337  
  3338  // Request to restore a stream.
  3339  func (s *Server) jsStreamRestoreRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  3340  	if c == nil || !s.JetStreamIsLeader() {
  3341  		return
  3342  	}
  3343  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  3344  	if err != nil {
  3345  		s.Warnf(badAPIRequestT, msg)
  3346  		return
  3347  	}
  3348  
  3349  	var resp = JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}}
  3350  	if !acc.JetStreamEnabled() {
  3351  		resp.Error = NewJSNotEnabledForAccountError()
  3352  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3353  		return
  3354  	}
  3355  	if isEmptyRequest(msg) {
  3356  		resp.Error = NewJSBadRequestError()
  3357  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3358  		return
  3359  	}
  3360  
  3361  	var req JSApiStreamRestoreRequest
  3362  	if err := json.Unmarshal(msg, &req); err != nil {
  3363  		resp.Error = NewJSInvalidJSONError()
  3364  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3365  		return
  3366  	}
  3367  
  3368  	stream := streamNameFromSubject(subject)
  3369  
  3370  	if stream != req.Config.Name && req.Config.Name == _EMPTY_ {
  3371  		req.Config.Name = stream
  3372  	}
  3373  
  3374  	// check stream config at the start of the restore process, not at the end
  3375  	cfg, apiErr := s.checkStreamCfg(&req.Config, acc)
  3376  	if apiErr != nil {
  3377  		resp.Error = apiErr
  3378  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3379  		return
  3380  	}
  3381  
  3382  	if s.JetStreamIsClustered() {
  3383  		s.jsClusteredStreamRestoreRequest(ci, acc, &req, subject, reply, rmsg)
  3384  		return
  3385  	}
  3386  
  3387  	if err := acc.jsNonClusteredStreamLimitsCheck(&cfg); err != nil {
  3388  		resp.Error = err
  3389  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3390  		return
  3391  	}
  3392  
  3393  	if _, err := acc.lookupStream(stream); err == nil {
  3394  		resp.Error = NewJSStreamNameExistRestoreFailedError()
  3395  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3396  		return
  3397  	}
  3398  
  3399  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  3400  		if doErr {
  3401  			resp.Error = NewJSNotEnabledForAccountError()
  3402  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3403  		}
  3404  		return
  3405  	}
  3406  
  3407  	s.processStreamRestore(ci, acc, &req.Config, subject, reply, string(msg))
  3408  }
  3409  
  3410  func (s *Server) processStreamRestore(ci *ClientInfo, acc *Account, cfg *StreamConfig, subject, reply, msg string) <-chan error {
  3411  	js := s.getJetStream()
  3412  
  3413  	var resp = JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}}
  3414  
  3415  	snapDir := filepath.Join(js.config.StoreDir, snapStagingDir)
  3416  	if _, err := os.Stat(snapDir); os.IsNotExist(err) {
  3417  		if err := os.MkdirAll(snapDir, defaultDirPerms); err != nil {
  3418  			resp.Error = &ApiError{Code: 503, Description: "JetStream unable to create temp storage for restore"}
  3419  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3420  			return nil
  3421  		}
  3422  	}
  3423  
  3424  	tfile, err := os.CreateTemp(snapDir, "js-restore-")
  3425  	if err != nil {
  3426  		resp.Error = NewJSTempStorageFailedError()
  3427  		s.sendAPIErrResponse(ci, acc, subject, reply, msg, s.jsonResponse(&resp))
  3428  		return nil
  3429  	}
  3430  
  3431  	streamName := cfg.Name
  3432  	s.Noticef("Starting restore for stream '%s > %s'", acc.Name, streamName)
  3433  
  3434  	start := time.Now().UTC()
  3435  	domain := s.getOpts().JetStreamDomain
  3436  	s.publishAdvisory(acc, JSAdvisoryStreamRestoreCreatePre+"."+streamName, &JSRestoreCreateAdvisory{
  3437  		TypedEvent: TypedEvent{
  3438  			Type: JSRestoreCreateAdvisoryType,
  3439  			ID:   nuid.Next(),
  3440  			Time: start,
  3441  		},
  3442  		Stream: streamName,
  3443  		Client: ci,
  3444  		Domain: domain,
  3445  	})
  3446  
  3447  	// Create our internal subscription to accept the snapshot.
  3448  	restoreSubj := fmt.Sprintf(jsRestoreDeliverT, streamName, nuid.Next())
  3449  
  3450  	type result struct {
  3451  		err   error
  3452  		reply string
  3453  	}
  3454  
  3455  	// For signaling to upper layers.
  3456  	resultCh := make(chan result, 1)
  3457  	activeQ := newIPQueue[int](s, fmt.Sprintf("[ACC:%s] stream '%s' restore", acc.Name, streamName)) // of int
  3458  
  3459  	var total int
  3460  
  3461  	// FIXME(dlc) - Probably take out of network path eventually due to disk I/O?
  3462  	processChunk := func(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) {
  3463  		// We require reply subjects to communicate back failures, flow etc. If they do not have one log and cancel.
  3464  		if reply == _EMPTY_ {
  3465  			sub.client.processUnsub(sub.sid)
  3466  			resultCh <- result{
  3467  				fmt.Errorf("restore for stream '%s > %s' requires reply subject for each chunk", acc.Name, streamName),
  3468  				reply,
  3469  			}
  3470  			return
  3471  		}
  3472  		// Account client messages have \r\n on end. This is an error.
  3473  		if len(msg) < LEN_CR_LF {
  3474  			sub.client.processUnsub(sub.sid)
  3475  			resultCh <- result{
  3476  				fmt.Errorf("restore for stream '%s > %s' received short chunk", acc.Name, streamName),
  3477  				reply,
  3478  			}
  3479  			return
  3480  		}
  3481  		// Adjust.
  3482  		msg = msg[:len(msg)-LEN_CR_LF]
  3483  
  3484  		// This means we are complete with our transfer from the client.
  3485  		if len(msg) == 0 {
  3486  			s.Debugf("Finished staging restore for stream '%s > %s'", acc.Name, streamName)
  3487  			resultCh <- result{err, reply}
  3488  			return
  3489  		}
  3490  
  3491  		// We track total and check on server limits.
  3492  		// TODO(dlc) - We could check apriori and cancel initial request if we know it won't fit.
  3493  		total += len(msg)
  3494  		if js.wouldExceedLimits(FileStorage, total) {
  3495  			s.resourcesExceededError()
  3496  			resultCh <- result{NewJSInsufficientResourcesError(), reply}
  3497  			return
  3498  		}
  3499  
  3500  		// Append chunk to temp file. Mark as issue if we encounter an error.
  3501  		if n, err := tfile.Write(msg); n != len(msg) || err != nil {
  3502  			resultCh <- result{err, reply}
  3503  			if reply != _EMPTY_ {
  3504  				s.sendInternalAccountMsg(acc, reply, "-ERR 'storage failure during restore'")
  3505  			}
  3506  			return
  3507  		}
  3508  
  3509  		activeQ.push(len(msg))
  3510  
  3511  		s.sendInternalAccountMsg(acc, reply, nil)
  3512  	}
  3513  
  3514  	sub, err := acc.subscribeInternal(restoreSubj, processChunk)
  3515  	if err != nil {
  3516  		tfile.Close()
  3517  		os.Remove(tfile.Name())
  3518  		resp.Error = NewJSRestoreSubscribeFailedError(err, restoreSubj)
  3519  		s.sendAPIErrResponse(ci, acc, subject, reply, msg, s.jsonResponse(&resp))
  3520  		return nil
  3521  	}
  3522  
  3523  	// Mark the subject so the end user knows where to send the snapshot chunks.
  3524  	resp.DeliverSubject = restoreSubj
  3525  	s.sendAPIResponse(ci, acc, subject, reply, msg, s.jsonResponse(resp))
  3526  
  3527  	doneCh := make(chan error, 1)
  3528  
  3529  	// Monitor the progress from another Go routine.
  3530  	s.startGoRoutine(func() {
  3531  		defer s.grWG.Done()
  3532  		defer func() {
  3533  			tfile.Close()
  3534  			os.Remove(tfile.Name())
  3535  			sub.client.processUnsub(sub.sid)
  3536  			activeQ.unregister()
  3537  		}()
  3538  
  3539  		const activityInterval = 5 * time.Second
  3540  		notActive := time.NewTimer(activityInterval)
  3541  		defer notActive.Stop()
  3542  
  3543  		total := 0
  3544  		for {
  3545  			select {
  3546  			case result := <-resultCh:
  3547  				err := result.err
  3548  				var mset *stream
  3549  
  3550  				// If we staged properly go ahead and do restore now.
  3551  				if err == nil {
  3552  					s.Debugf("Finalizing restore for stream '%s > %s'", acc.Name, streamName)
  3553  					tfile.Seek(0, 0)
  3554  					mset, err = acc.RestoreStream(cfg, tfile)
  3555  				} else {
  3556  					errStr := err.Error()
  3557  					tmp := []rune(errStr)
  3558  					tmp[0] = unicode.ToUpper(tmp[0])
  3559  					s.Warnf(errStr)
  3560  				}
  3561  
  3562  				end := time.Now().UTC()
  3563  
  3564  				// TODO(rip) - Should this have the error code in it??
  3565  				s.publishAdvisory(acc, JSAdvisoryStreamRestoreCompletePre+"."+streamName, &JSRestoreCompleteAdvisory{
  3566  					TypedEvent: TypedEvent{
  3567  						Type: JSRestoreCompleteAdvisoryType,
  3568  						ID:   nuid.Next(),
  3569  						Time: end,
  3570  					},
  3571  					Stream: streamName,
  3572  					Start:  start,
  3573  					End:    end,
  3574  					Bytes:  int64(total),
  3575  					Client: ci,
  3576  					Domain: domain,
  3577  				})
  3578  
  3579  				var resp = JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}}
  3580  
  3581  				if err != nil {
  3582  					resp.Error = NewJSStreamRestoreError(err, Unless(err))
  3583  					s.Warnf("Restore failed for %s for stream '%s > %s' in %v",
  3584  						friendlyBytes(int64(total)), streamName, acc.Name, end.Sub(start))
  3585  				} else {
  3586  					resp.StreamInfo = &StreamInfo{
  3587  						Created:   mset.createdTime(),
  3588  						State:     mset.state(),
  3589  						Config:    mset.config(),
  3590  						TimeStamp: time.Now().UTC(),
  3591  					}
  3592  					s.Noticef("Completed restore of %s for stream '%s > %s' in %v",
  3593  						friendlyBytes(int64(total)), streamName, acc.Name, end.Sub(start).Round(time.Millisecond))
  3594  				}
  3595  
  3596  				// On the last EOF, send back the stream info or error status.
  3597  				s.sendInternalAccountMsg(acc, result.reply, s.jsonResponse(&resp))
  3598  				// Signal to the upper layers.
  3599  				doneCh <- err
  3600  				return
  3601  			case <-activeQ.ch:
  3602  				if n, ok := activeQ.popOne(); ok {
  3603  					total += n
  3604  					notActive.Reset(activityInterval)
  3605  				}
  3606  			case <-notActive.C:
  3607  				err := fmt.Errorf("restore for stream '%s > %s' is stalled", acc, streamName)
  3608  				doneCh <- err
  3609  				return
  3610  			}
  3611  		}
  3612  	})
  3613  
  3614  	return doneCh
  3615  }
  3616  
  3617  // Process a snapshot request.
  3618  func (s *Server) jsStreamSnapshotRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  3619  	if c == nil || !s.JetStreamEnabled() {
  3620  		return
  3621  	}
  3622  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  3623  	if err != nil {
  3624  		s.Warnf(badAPIRequestT, msg)
  3625  		return
  3626  	}
  3627  
  3628  	smsg := string(msg)
  3629  	stream := streamNameFromSubject(subject)
  3630  
  3631  	// If we are in clustered mode we need to be the stream leader to proceed.
  3632  	if s.JetStreamIsClustered() && !acc.JetStreamIsStreamLeader(stream) {
  3633  		return
  3634  	}
  3635  
  3636  	var resp = JSApiStreamSnapshotResponse{ApiResponse: ApiResponse{Type: JSApiStreamSnapshotResponseType}}
  3637  	if !acc.JetStreamEnabled() {
  3638  		resp.Error = NewJSNotEnabledForAccountError()
  3639  		s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
  3640  		return
  3641  	}
  3642  	if isEmptyRequest(msg) {
  3643  		resp.Error = NewJSBadRequestError()
  3644  		s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
  3645  		return
  3646  	}
  3647  
  3648  	mset, err := acc.lookupStream(stream)
  3649  	if err != nil {
  3650  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  3651  		s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
  3652  		return
  3653  	}
  3654  
  3655  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  3656  		if doErr {
  3657  			resp.Error = NewJSNotEnabledForAccountError()
  3658  			s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
  3659  		}
  3660  		return
  3661  	}
  3662  
  3663  	var req JSApiStreamSnapshotRequest
  3664  	if err := json.Unmarshal(msg, &req); err != nil {
  3665  		resp.Error = NewJSInvalidJSONError()
  3666  		s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
  3667  		return
  3668  	}
  3669  	if !IsValidSubject(req.DeliverSubject) {
  3670  		resp.Error = NewJSSnapshotDeliverSubjectInvalidError()
  3671  		s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
  3672  		return
  3673  	}
  3674  
  3675  	// We will do the snapshot in a go routine as well since check msgs may
  3676  	// stall this go routine.
  3677  	go func() {
  3678  		if req.CheckMsgs {
  3679  			s.Noticef("Starting health check and snapshot for stream '%s > %s'", mset.jsa.account.Name, mset.name())
  3680  		} else {
  3681  			s.Noticef("Starting snapshot for stream '%s > %s'", mset.jsa.account.Name, mset.name())
  3682  		}
  3683  
  3684  		start := time.Now().UTC()
  3685  
  3686  		sr, err := mset.snapshot(0, req.CheckMsgs, !req.NoConsumers)
  3687  		if err != nil {
  3688  			s.Warnf("Snapshot of stream '%s > %s' failed: %v", mset.jsa.account.Name, mset.name(), err)
  3689  			resp.Error = NewJSStreamSnapshotError(err, Unless(err))
  3690  			s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp))
  3691  			return
  3692  		}
  3693  
  3694  		config := mset.config()
  3695  		resp.State = &sr.State
  3696  		resp.Config = &config
  3697  
  3698  		s.sendAPIResponse(ci, acc, subject, reply, smsg, s.jsonResponse(resp))
  3699  
  3700  		s.publishAdvisory(acc, JSAdvisoryStreamSnapshotCreatePre+"."+mset.name(), &JSSnapshotCreateAdvisory{
  3701  			TypedEvent: TypedEvent{
  3702  				Type: JSSnapshotCreatedAdvisoryType,
  3703  				ID:   nuid.Next(),
  3704  				Time: time.Now().UTC(),
  3705  			},
  3706  			Stream: mset.name(),
  3707  			State:  sr.State,
  3708  			Client: ci,
  3709  			Domain: s.getOpts().JetStreamDomain,
  3710  		})
  3711  
  3712  		// Now do the real streaming.
  3713  		s.streamSnapshot(acc, mset, sr, &req)
  3714  
  3715  		end := time.Now().UTC()
  3716  
  3717  		s.publishAdvisory(acc, JSAdvisoryStreamSnapshotCompletePre+"."+mset.name(), &JSSnapshotCompleteAdvisory{
  3718  			TypedEvent: TypedEvent{
  3719  				Type: JSSnapshotCompleteAdvisoryType,
  3720  				ID:   nuid.Next(),
  3721  				Time: end,
  3722  			},
  3723  			Stream: mset.name(),
  3724  			Start:  start,
  3725  			End:    end,
  3726  			Client: ci,
  3727  			Domain: s.getOpts().JetStreamDomain,
  3728  		})
  3729  
  3730  		s.Noticef("Completed snapshot of %s for stream '%s > %s' in %v",
  3731  			friendlyBytes(int64(sr.State.Bytes)),
  3732  			mset.jsa.account.Name,
  3733  			mset.name(),
  3734  			end.Sub(start))
  3735  	}()
  3736  }
  3737  
  3738  // Default chunk size for now.
  3739  const defaultSnapshotChunkSize = 128 * 1024
  3740  const defaultSnapshotWindowSize = 8 * 1024 * 1024 // 8MB
  3741  
  3742  // streamSnapshot will stream out our snapshot to the reply subject.
  3743  func (s *Server) streamSnapshot(acc *Account, mset *stream, sr *SnapshotResult, req *JSApiStreamSnapshotRequest) {
  3744  	chunkSize := req.ChunkSize
  3745  	if chunkSize == 0 {
  3746  		chunkSize = defaultSnapshotChunkSize
  3747  	}
  3748  	// Setup for the chunk stream.
  3749  	reply := req.DeliverSubject
  3750  	r := sr.Reader
  3751  	defer r.Close()
  3752  
  3753  	// Check interest for the snapshot deliver subject.
  3754  	inch := make(chan bool, 1)
  3755  	acc.sl.RegisterNotification(req.DeliverSubject, inch)
  3756  	defer acc.sl.ClearNotification(req.DeliverSubject, inch)
  3757  	hasInterest := <-inch
  3758  	if !hasInterest {
  3759  		// Allow 2 seconds or so for interest to show up.
  3760  		select {
  3761  		case <-inch:
  3762  		case <-time.After(2 * time.Second):
  3763  		}
  3764  	}
  3765  
  3766  	// Create our ack flow handler.
  3767  	// This is very simple for now.
  3768  	ackSize := defaultSnapshotWindowSize / chunkSize
  3769  	if ackSize < 8 {
  3770  		ackSize = 8
  3771  	} else if ackSize > 8*1024 {
  3772  		ackSize = 8 * 1024
  3773  	}
  3774  	acks := make(chan struct{}, ackSize)
  3775  	acks <- struct{}{}
  3776  
  3777  	// Track bytes outstanding.
  3778  	var out int32
  3779  
  3780  	// We will place sequence number and size of chunk sent in the reply.
  3781  	ackSubj := fmt.Sprintf(jsSnapshotAckT, mset.name(), nuid.Next())
  3782  	ackSub, _ := mset.subscribeInternal(ackSubj+".>", func(_ *subscription, _ *client, _ *Account, subject, _ string, _ []byte) {
  3783  		cs, _ := strconv.Atoi(tokenAt(subject, 6))
  3784  		// This is very crude and simple, but ok for now.
  3785  		// This only matters when sending multiple chunks.
  3786  		if atomic.AddInt32(&out, int32(-cs)) < defaultSnapshotWindowSize {
  3787  			select {
  3788  			case acks <- struct{}{}:
  3789  			default:
  3790  			}
  3791  		}
  3792  	})
  3793  	defer mset.unsubscribe(ackSub)
  3794  
  3795  	// TODO(dlc) - Add in NATS-Chunked-Sequence header
  3796  	var hdr []byte
  3797  	for index := 1; ; index++ {
  3798  		chunk := make([]byte, chunkSize)
  3799  		n, err := r.Read(chunk)
  3800  		chunk = chunk[:n]
  3801  		if err != nil {
  3802  			if n > 0 {
  3803  				mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, chunk, nil, 0))
  3804  			}
  3805  			break
  3806  		}
  3807  
  3808  		// Wait on acks for flow control if past our window size.
  3809  		// Wait up to 10ms for now if no acks received.
  3810  		if atomic.LoadInt32(&out) > defaultSnapshotWindowSize {
  3811  			select {
  3812  			case <-acks:
  3813  				// ok to proceed.
  3814  			case <-inch:
  3815  				// Lost interest
  3816  				hdr = []byte("NATS/1.0 408 No Interest\r\n\r\n")
  3817  				goto done
  3818  			case <-time.After(2 * time.Second):
  3819  				hdr = []byte("NATS/1.0 408 No Flow Response\r\n\r\n")
  3820  				goto done
  3821  			}
  3822  		}
  3823  		ackReply := fmt.Sprintf("%s.%d.%d", ackSubj, len(chunk), index)
  3824  		if hdr == nil {
  3825  			hdr = []byte("NATS/1.0 204\r\n\r\n")
  3826  		}
  3827  		mset.outq.send(newJSPubMsg(reply, _EMPTY_, ackReply, nil, chunk, nil, 0))
  3828  		atomic.AddInt32(&out, int32(len(chunk)))
  3829  	}
  3830  done:
  3831  	// Send last EOF
  3832  	// TODO(dlc) - place hash in header
  3833  	mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
  3834  }
  3835  
  3836  // For determining consumer request type.
  3837  type ccReqType uint8
  3838  
  3839  const (
  3840  	ccNew = iota
  3841  	ccLegacyEphemeral
  3842  	ccLegacyDurable
  3843  )
  3844  
  3845  // Request to create a consumer where stream and optional consumer name are part of the subject, and optional
  3846  // filtered subjects can be at the tail end.
  3847  // Assumes stream and consumer names are single tokens.
  3848  func (s *Server) jsConsumerCreateRequest(sub *subscription, c *client, a *Account, subject, reply string, rmsg []byte) {
  3849  	if c == nil || !s.JetStreamEnabled() {
  3850  		return
  3851  	}
  3852  
  3853  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  3854  	if err != nil {
  3855  		s.Warnf(badAPIRequestT, msg)
  3856  		return
  3857  	}
  3858  
  3859  	var resp = JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}}
  3860  
  3861  	var req CreateConsumerRequest
  3862  	if err := json.Unmarshal(msg, &req); err != nil {
  3863  		resp.Error = NewJSInvalidJSONError()
  3864  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3865  		return
  3866  	}
  3867  
  3868  	var js *jetStream
  3869  	isClustered := s.JetStreamIsClustered()
  3870  
  3871  	// Determine if we should proceed here when we are in clustered mode.
  3872  	if isClustered {
  3873  		if req.Config.Direct {
  3874  			// Check to see if we have this stream and are the stream leader.
  3875  			if !acc.JetStreamIsStreamLeader(streamNameFromSubject(subject)) {
  3876  				return
  3877  			}
  3878  		} else {
  3879  			var cc *jetStreamCluster
  3880  			js, cc = s.getJetStreamCluster()
  3881  			if js == nil || cc == nil {
  3882  				return
  3883  			}
  3884  			if js.isLeaderless() {
  3885  				resp.Error = NewJSClusterNotAvailError()
  3886  				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3887  				return
  3888  			}
  3889  			// Make sure we are meta leader.
  3890  			if !s.JetStreamIsLeader() {
  3891  				return
  3892  			}
  3893  		}
  3894  	}
  3895  
  3896  	var streamName, consumerName, filteredSubject string
  3897  	var rt ccReqType
  3898  
  3899  	if n := numTokens(subject); n < 5 {
  3900  		s.Warnf(badAPIRequestT, msg)
  3901  		return
  3902  	} else if n == 5 {
  3903  		// Legacy ephemeral.
  3904  		rt = ccLegacyEphemeral
  3905  		streamName = streamNameFromSubject(subject)
  3906  	} else {
  3907  		// New style and durable legacy.
  3908  		if tokenAt(subject, 4) == "DURABLE" {
  3909  			rt = ccLegacyDurable
  3910  			if n != 7 {
  3911  				resp.Error = NewJSConsumerDurableNameNotInSubjectError()
  3912  				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3913  				return
  3914  			}
  3915  			streamName = tokenAt(subject, 6)
  3916  			consumerName = tokenAt(subject, 7)
  3917  		} else {
  3918  			streamName = streamNameFromSubject(subject)
  3919  			consumerName = consumerNameFromSubject(subject)
  3920  			// New has optional filtered subject as part of main subject..
  3921  			if n > 6 {
  3922  				tokens := strings.Split(subject, tsep)
  3923  				filteredSubject = strings.Join(tokens[6:], tsep)
  3924  			}
  3925  		}
  3926  	}
  3927  
  3928  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  3929  		if doErr {
  3930  			resp.Error = NewJSNotEnabledForAccountError()
  3931  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3932  		}
  3933  		return
  3934  	}
  3935  
  3936  	if streamName != req.Stream {
  3937  		resp.Error = NewJSStreamMismatchError()
  3938  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3939  		return
  3940  	}
  3941  
  3942  	if consumerName != _EMPTY_ {
  3943  		// Check for path like separators in the name.
  3944  		if strings.ContainsAny(consumerName, `\/`) {
  3945  			resp.Error = NewJSConsumerNameContainsPathSeparatorsError()
  3946  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3947  			return
  3948  		}
  3949  	}
  3950  
  3951  	// Should we expect a durable name
  3952  	if rt == ccLegacyDurable {
  3953  		if numTokens(subject) < 7 {
  3954  			resp.Error = NewJSConsumerDurableNameNotInSubjectError()
  3955  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3956  			return
  3957  		}
  3958  		// Now check on requirements for durable request.
  3959  		if req.Config.Durable == _EMPTY_ {
  3960  			resp.Error = NewJSConsumerDurableNameNotSetError()
  3961  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3962  			return
  3963  		}
  3964  		if consumerName != req.Config.Durable {
  3965  			resp.Error = NewJSConsumerDurableNameNotMatchSubjectError()
  3966  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3967  			return
  3968  		}
  3969  	}
  3970  	// If new style and durable set make sure they match.
  3971  	if rt == ccNew {
  3972  		if req.Config.Durable != _EMPTY_ {
  3973  			if consumerName != req.Config.Durable {
  3974  				resp.Error = NewJSConsumerDurableNameNotMatchSubjectError()
  3975  				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3976  				return
  3977  			}
  3978  		}
  3979  		// New style ephemeral so we need to honor the name.
  3980  		req.Config.Name = consumerName
  3981  	}
  3982  	// Check for legacy ephemeral mis-configuration.
  3983  	if rt == ccLegacyEphemeral && req.Config.Durable != _EMPTY_ {
  3984  		resp.Error = NewJSConsumerEphemeralWithDurableNameError()
  3985  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3986  		return
  3987  	}
  3988  
  3989  	// in case of multiple filters provided, error if new API is used.
  3990  	if filteredSubject != _EMPTY_ && len(req.Config.FilterSubjects) != 0 {
  3991  		resp.Error = NewJSConsumerMultipleFiltersNotAllowedError()
  3992  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  3993  		return
  3994  	}
  3995  
  3996  	// Check for a filter subject.
  3997  	if filteredSubject != _EMPTY_ && req.Config.FilterSubject != filteredSubject {
  3998  		resp.Error = NewJSConsumerCreateFilterSubjectMismatchError()
  3999  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4000  		return
  4001  	}
  4002  
  4003  	if isClustered && !req.Config.Direct {
  4004  		// If we are inline with client, we still may need to do a callout for consumer info
  4005  		// during this call, so place in Go routine to not block client.
  4006  		// Router and Gateway API calls already in separate context.
  4007  		if c.kind != ROUTER && c.kind != GATEWAY {
  4008  			go s.jsClusteredConsumerRequest(ci, acc, subject, reply, rmsg, req.Stream, &req.Config, req.Action)
  4009  		} else {
  4010  			s.jsClusteredConsumerRequest(ci, acc, subject, reply, rmsg, req.Stream, &req.Config, req.Action)
  4011  		}
  4012  		return
  4013  	}
  4014  
  4015  	// If we are here we are single server mode.
  4016  	if req.Config.Replicas > 1 {
  4017  		resp.Error = NewJSStreamReplicasNotSupportedError()
  4018  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4019  		return
  4020  	}
  4021  
  4022  	stream, err := acc.lookupStream(req.Stream)
  4023  	if err != nil {
  4024  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  4025  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4026  		return
  4027  	}
  4028  
  4029  	// If the consumer already exists then don't allow updating the PauseUntil, just set
  4030  	// it back to whatever the current configured value is.
  4031  	if o := stream.lookupConsumer(consumerName); o != nil {
  4032  		req.Config.PauseUntil = o.cfg.PauseUntil
  4033  	}
  4034  
  4035  	o, err := stream.addConsumerWithAction(&req.Config, req.Action)
  4036  
  4037  	if err != nil {
  4038  		if IsNatsErr(err, JSConsumerStoreFailedErrF) {
  4039  			cname := req.Config.Durable // Will be empty if ephemeral.
  4040  			s.Warnf("Consumer create failed for '%s > %s > %s': %v", acc, req.Stream, cname, err)
  4041  			err = errConsumerStoreFailed
  4042  		}
  4043  		resp.Error = NewJSConsumerCreateError(err, Unless(err))
  4044  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4045  		return
  4046  	}
  4047  	resp.ConsumerInfo = o.initialInfo()
  4048  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  4049  
  4050  	if o.cfg.PauseUntil != nil && !o.cfg.PauseUntil.IsZero() && time.Now().Before(*o.cfg.PauseUntil) {
  4051  		o.sendPauseAdvisoryLocked(&o.cfg)
  4052  	}
  4053  }
  4054  
  4055  // Request for the list of all consumer names.
  4056  func (s *Server) jsConsumerNamesRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  4057  	if c == nil || !s.JetStreamEnabled() {
  4058  		return
  4059  	}
  4060  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  4061  	if err != nil {
  4062  		s.Warnf(badAPIRequestT, msg)
  4063  		return
  4064  	}
  4065  
  4066  	var resp = JSApiConsumerNamesResponse{
  4067  		ApiResponse: ApiResponse{Type: JSApiConsumerNamesResponseType},
  4068  		Consumers:   []string{},
  4069  	}
  4070  
  4071  	// Determine if we should proceed here when we are in clustered mode.
  4072  	if s.JetStreamIsClustered() {
  4073  		js, cc := s.getJetStreamCluster()
  4074  		if js == nil || cc == nil {
  4075  			return
  4076  		}
  4077  		if js.isLeaderless() {
  4078  			resp.Error = NewJSClusterNotAvailError()
  4079  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4080  			return
  4081  		}
  4082  		// Make sure we are meta leader.
  4083  		if !s.JetStreamIsLeader() {
  4084  			return
  4085  		}
  4086  	}
  4087  
  4088  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  4089  		if doErr {
  4090  			resp.Error = NewJSNotEnabledForAccountError()
  4091  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4092  		}
  4093  		return
  4094  	}
  4095  
  4096  	var offset int
  4097  	if !isEmptyRequest(msg) {
  4098  		var req JSApiConsumersRequest
  4099  		if err := json.Unmarshal(msg, &req); err != nil {
  4100  			resp.Error = NewJSInvalidJSONError()
  4101  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4102  			return
  4103  		}
  4104  		offset = req.Offset
  4105  	}
  4106  
  4107  	streamName := streamNameFromSubject(subject)
  4108  	var numConsumers int
  4109  
  4110  	if s.JetStreamIsClustered() {
  4111  		js, cc := s.getJetStreamCluster()
  4112  		if js == nil || cc == nil {
  4113  			// TODO(dlc) - Debug or Warn?
  4114  			return
  4115  		}
  4116  		js.mu.RLock()
  4117  		sas := cc.streams[acc.Name]
  4118  		if sas == nil {
  4119  			js.mu.RUnlock()
  4120  			resp.Error = NewJSStreamNotFoundError()
  4121  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4122  			return
  4123  		}
  4124  		sa := sas[streamName]
  4125  		if sa == nil || sa.err != nil {
  4126  			js.mu.RUnlock()
  4127  			resp.Error = NewJSStreamNotFoundError()
  4128  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4129  			return
  4130  		}
  4131  		for consumer := range sa.consumers {
  4132  			resp.Consumers = append(resp.Consumers, consumer)
  4133  		}
  4134  		if len(resp.Consumers) > 1 {
  4135  			sort.Slice(resp.Consumers, func(i, j int) bool { return strings.Compare(resp.Consumers[i], resp.Consumers[j]) < 0 })
  4136  		}
  4137  		numConsumers = len(resp.Consumers)
  4138  		if offset > numConsumers {
  4139  			offset = numConsumers
  4140  		}
  4141  		resp.Consumers = resp.Consumers[offset:]
  4142  		if len(resp.Consumers) > JSApiNamesLimit {
  4143  			resp.Consumers = resp.Consumers[:JSApiNamesLimit]
  4144  		}
  4145  		js.mu.RUnlock()
  4146  
  4147  	} else {
  4148  		mset, err := acc.lookupStream(streamName)
  4149  		if err != nil {
  4150  			resp.Error = NewJSStreamNotFoundError(Unless(err))
  4151  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4152  			return
  4153  		}
  4154  
  4155  		obs := mset.getPublicConsumers()
  4156  		sort.Slice(obs, func(i, j int) bool {
  4157  			return strings.Compare(obs[i].name, obs[j].name) < 0
  4158  		})
  4159  
  4160  		numConsumers = len(obs)
  4161  		if offset > numConsumers {
  4162  			offset = numConsumers
  4163  		}
  4164  
  4165  		for _, o := range obs[offset:] {
  4166  			resp.Consumers = append(resp.Consumers, o.String())
  4167  			if len(resp.Consumers) >= JSApiNamesLimit {
  4168  				break
  4169  			}
  4170  		}
  4171  	}
  4172  	resp.Total = numConsumers
  4173  	resp.Limit = JSApiNamesLimit
  4174  	resp.Offset = offset
  4175  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  4176  }
  4177  
  4178  // Request for the list of all detailed consumer information.
  4179  func (s *Server) jsConsumerListRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  4180  	if c == nil || !s.JetStreamEnabled() {
  4181  		return
  4182  	}
  4183  
  4184  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  4185  	if err != nil {
  4186  		s.Warnf(badAPIRequestT, msg)
  4187  		return
  4188  	}
  4189  
  4190  	var resp = JSApiConsumerListResponse{
  4191  		ApiResponse: ApiResponse{Type: JSApiConsumerListResponseType},
  4192  		Consumers:   []*ConsumerInfo{},
  4193  	}
  4194  
  4195  	// Determine if we should proceed here when we are in clustered mode.
  4196  	if s.JetStreamIsClustered() {
  4197  		js, cc := s.getJetStreamCluster()
  4198  		if js == nil || cc == nil {
  4199  			return
  4200  		}
  4201  		if js.isLeaderless() {
  4202  			resp.Error = NewJSClusterNotAvailError()
  4203  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4204  			return
  4205  		}
  4206  		// Make sure we are meta leader.
  4207  		if !s.JetStreamIsLeader() {
  4208  			return
  4209  		}
  4210  	}
  4211  
  4212  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  4213  		if doErr {
  4214  			resp.Error = NewJSNotEnabledForAccountError()
  4215  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4216  		}
  4217  		return
  4218  	}
  4219  
  4220  	var offset int
  4221  	if !isEmptyRequest(msg) {
  4222  		var req JSApiConsumersRequest
  4223  		if err := json.Unmarshal(msg, &req); err != nil {
  4224  			resp.Error = NewJSInvalidJSONError()
  4225  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4226  			return
  4227  		}
  4228  		offset = req.Offset
  4229  	}
  4230  
  4231  	streamName := streamNameFromSubject(subject)
  4232  
  4233  	// Clustered mode will invoke a scatter and gather.
  4234  	if s.JetStreamIsClustered() {
  4235  		// Need to copy these off before sending.. don't move this inside startGoRoutine!!!
  4236  		msg = copyBytes(msg)
  4237  		s.startGoRoutine(func() {
  4238  			s.jsClusteredConsumerListRequest(acc, ci, offset, streamName, subject, reply, msg)
  4239  		})
  4240  		return
  4241  	}
  4242  
  4243  	mset, err := acc.lookupStream(streamName)
  4244  	if err != nil {
  4245  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  4246  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4247  		return
  4248  	}
  4249  
  4250  	obs := mset.getPublicConsumers()
  4251  	sort.Slice(obs, func(i, j int) bool {
  4252  		return strings.Compare(obs[i].name, obs[j].name) < 0
  4253  	})
  4254  
  4255  	ocnt := len(obs)
  4256  	if offset > ocnt {
  4257  		offset = ocnt
  4258  	}
  4259  
  4260  	for _, o := range obs[offset:] {
  4261  		if cinfo := o.info(); cinfo != nil {
  4262  			resp.Consumers = append(resp.Consumers, cinfo)
  4263  		}
  4264  		if len(resp.Consumers) >= JSApiListLimit {
  4265  			break
  4266  		}
  4267  	}
  4268  	resp.Total = ocnt
  4269  	resp.Limit = JSApiListLimit
  4270  	resp.Offset = offset
  4271  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  4272  }
  4273  
  4274  // Request for information about an consumer.
  4275  func (s *Server) jsConsumerInfoRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  4276  	if c == nil || !s.JetStreamEnabled() {
  4277  		return
  4278  	}
  4279  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  4280  	if err != nil {
  4281  		s.Warnf(badAPIRequestT, msg)
  4282  		return
  4283  	}
  4284  
  4285  	streamName := streamNameFromSubject(subject)
  4286  	consumerName := consumerNameFromSubject(subject)
  4287  
  4288  	var resp = JSApiConsumerInfoResponse{ApiResponse: ApiResponse{Type: JSApiConsumerInfoResponseType}}
  4289  
  4290  	if !isEmptyRequest(msg) {
  4291  		resp.Error = NewJSNotEmptyRequestError()
  4292  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4293  		return
  4294  	}
  4295  
  4296  	// If we are in clustered mode we need to be the consumer leader to proceed.
  4297  	if s.JetStreamIsClustered() {
  4298  		// Check to make sure the consumer is assigned.
  4299  		js, cc := s.getJetStreamCluster()
  4300  		if js == nil || cc == nil {
  4301  			return
  4302  		}
  4303  
  4304  		js.mu.RLock()
  4305  		isLeader, sa, ca := cc.isLeader(), js.streamAssignment(acc.Name, streamName), js.consumerAssignment(acc.Name, streamName, consumerName)
  4306  		ourID := cc.meta.ID()
  4307  		var rg *raftGroup
  4308  		var offline, isMember bool
  4309  		if ca != nil {
  4310  			if rg = ca.Group; rg != nil {
  4311  				offline = s.allPeersOffline(rg)
  4312  				isMember = rg.isMember(ourID)
  4313  			}
  4314  		}
  4315  		// Capture consumer leader here.
  4316  		isConsumerLeader := cc.isConsumerLeader(acc.Name, streamName, consumerName)
  4317  		// Also capture if we think there is no meta leader.
  4318  		var isLeaderLess bool
  4319  		if !isLeader {
  4320  			isLeaderLess = cc.meta.GroupLeader() == _EMPTY_ && time.Since(cc.meta.Created()) > lostQuorumIntervalDefault
  4321  		}
  4322  		js.mu.RUnlock()
  4323  
  4324  		if isLeader && ca == nil {
  4325  			// We can't find the consumer, so mimic what would be the errors below.
  4326  			if hasJS, doErr := acc.checkJetStream(); !hasJS {
  4327  				if doErr {
  4328  					resp.Error = NewJSNotEnabledForAccountError()
  4329  					s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4330  				}
  4331  				return
  4332  			}
  4333  			if sa == nil {
  4334  				resp.Error = NewJSStreamNotFoundError()
  4335  				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4336  				return
  4337  			}
  4338  			// If we are here the consumer is not present.
  4339  			resp.Error = NewJSConsumerNotFoundError()
  4340  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4341  			return
  4342  		} else if ca == nil {
  4343  			if isLeaderLess {
  4344  				resp.Error = NewJSClusterNotAvailError()
  4345  				// Delaying an error response gives the leader a chance to respond before us
  4346  				s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil)
  4347  			}
  4348  			return
  4349  		} else if isLeader && offline {
  4350  			resp.Error = NewJSConsumerOfflineError()
  4351  			s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil)
  4352  			return
  4353  		}
  4354  
  4355  		// Check to see if we are a member of the group and if the group has no leader.
  4356  		if isMember && js.isGroupLeaderless(ca.Group) {
  4357  			resp.Error = NewJSClusterNotAvailError()
  4358  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4359  			return
  4360  		}
  4361  
  4362  		// We have the consumer assigned and a leader, so only the consumer leader should answer.
  4363  		if !isConsumerLeader {
  4364  			if isLeaderLess {
  4365  				resp.Error = NewJSClusterNotAvailError()
  4366  				// Delaying an error response gives the leader a chance to respond before us
  4367  				s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), ca.Group)
  4368  				return
  4369  			}
  4370  
  4371  			var node RaftNode
  4372  			var leaderNotPartOfGroup bool
  4373  
  4374  			// We have a consumer assignment.
  4375  			if isMember {
  4376  				js.mu.RLock()
  4377  				if rg.node != nil {
  4378  					node = rg.node
  4379  					if gl := node.GroupLeader(); gl != _EMPTY_ && !rg.isMember(gl) {
  4380  						leaderNotPartOfGroup = true
  4381  					}
  4382  				}
  4383  				js.mu.RUnlock()
  4384  			}
  4385  
  4386  			// Check if we should ignore all together.
  4387  			if node == nil {
  4388  				// We have been assigned but have not created a node yet. If we are a member return
  4389  				// our config and defaults for state and no cluster info.
  4390  				if isMember {
  4391  					// Since we access consumerAssignment, need js lock.
  4392  					js.mu.RLock()
  4393  					resp.ConsumerInfo = &ConsumerInfo{
  4394  						Stream:    ca.Stream,
  4395  						Name:      ca.Name,
  4396  						Created:   ca.Created,
  4397  						Config:    ca.Config,
  4398  						TimeStamp: time.Now().UTC(),
  4399  					}
  4400  					b := s.jsonResponse(resp)
  4401  					js.mu.RUnlock()
  4402  					s.sendAPIResponse(ci, acc, subject, reply, string(msg), b)
  4403  				}
  4404  				return
  4405  			}
  4406  			// If we are a member and we have a group leader or we had a previous leader consider bailing out.
  4407  			if node.GroupLeader() != _EMPTY_ || node.HadPreviousLeader() {
  4408  				if leaderNotPartOfGroup {
  4409  					resp.Error = NewJSConsumerOfflineError()
  4410  					s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil)
  4411  				}
  4412  				return
  4413  			}
  4414  			// If we are here we are a member and this is just a new consumer that does not have a leader yet.
  4415  			// Will fall through and return what we have. All consumers can respond but this should be very rare
  4416  			// but makes more sense to clients when they try to create, get a consumer exists, and then do consumer info.
  4417  		}
  4418  	}
  4419  
  4420  	if !acc.JetStreamEnabled() {
  4421  		resp.Error = NewJSNotEnabledForAccountError()
  4422  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4423  		return
  4424  	}
  4425  
  4426  	mset, err := acc.lookupStream(streamName)
  4427  	if err != nil {
  4428  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  4429  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4430  		return
  4431  	}
  4432  
  4433  	obs := mset.lookupConsumer(consumerName)
  4434  	if obs == nil {
  4435  		resp.Error = NewJSConsumerNotFoundError()
  4436  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4437  		return
  4438  	}
  4439  
  4440  	if resp.ConsumerInfo = obs.info(); resp.ConsumerInfo == nil {
  4441  		// This consumer returned nil which means it's closed. Respond with not found.
  4442  		resp.Error = NewJSConsumerNotFoundError()
  4443  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4444  		return
  4445  	}
  4446  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  4447  }
  4448  
  4449  // Request to delete an Consumer.
  4450  func (s *Server) jsConsumerDeleteRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  4451  	if c == nil || !s.JetStreamEnabled() {
  4452  		return
  4453  	}
  4454  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  4455  	if err != nil {
  4456  		s.Warnf(badAPIRequestT, msg)
  4457  		return
  4458  	}
  4459  
  4460  	var resp = JSApiConsumerDeleteResponse{ApiResponse: ApiResponse{Type: JSApiConsumerDeleteResponseType}}
  4461  
  4462  	// Determine if we should proceed here when we are in clustered mode.
  4463  	if s.JetStreamIsClustered() {
  4464  		js, cc := s.getJetStreamCluster()
  4465  		if js == nil || cc == nil {
  4466  			return
  4467  		}
  4468  		if js.isLeaderless() {
  4469  			resp.Error = NewJSClusterNotAvailError()
  4470  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4471  			return
  4472  		}
  4473  		// Make sure we are meta leader.
  4474  		if !s.JetStreamIsLeader() {
  4475  			return
  4476  		}
  4477  	}
  4478  
  4479  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  4480  		if doErr {
  4481  			resp.Error = NewJSNotEnabledForAccountError()
  4482  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4483  		}
  4484  		return
  4485  	}
  4486  	if !isEmptyRequest(msg) {
  4487  		resp.Error = NewJSNotEmptyRequestError()
  4488  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4489  		return
  4490  	}
  4491  	stream := streamNameFromSubject(subject)
  4492  	consumer := consumerNameFromSubject(subject)
  4493  
  4494  	if s.JetStreamIsClustered() {
  4495  		s.jsClusteredConsumerDeleteRequest(ci, acc, stream, consumer, subject, reply, rmsg)
  4496  		return
  4497  	}
  4498  
  4499  	mset, err := acc.lookupStream(stream)
  4500  	if err != nil {
  4501  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  4502  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4503  		return
  4504  	}
  4505  
  4506  	obs := mset.lookupConsumer(consumer)
  4507  	if obs == nil {
  4508  		resp.Error = NewJSConsumerNotFoundError()
  4509  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4510  		return
  4511  	}
  4512  	if err := obs.delete(); err != nil {
  4513  		resp.Error = NewJSStreamGeneralError(err, Unless(err))
  4514  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4515  		return
  4516  	}
  4517  	resp.Success = true
  4518  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  4519  }
  4520  
  4521  // Request to pause or unpause a Consumer.
  4522  func (s *Server) jsConsumerPauseRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
  4523  	if c == nil || !s.JetStreamEnabled() {
  4524  		return
  4525  	}
  4526  	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
  4527  	if err != nil {
  4528  		s.Warnf(badAPIRequestT, msg)
  4529  		return
  4530  	}
  4531  
  4532  	var req JSApiConsumerPauseRequest
  4533  	var resp = JSApiConsumerPauseResponse{ApiResponse: ApiResponse{Type: JSApiConsumerPauseResponseType}}
  4534  
  4535  	if !isEmptyRequest(msg) {
  4536  		if err := json.Unmarshal(msg, &req); err != nil {
  4537  			resp.Error = NewJSInvalidJSONError()
  4538  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4539  			return
  4540  		}
  4541  	}
  4542  
  4543  	// Determine if we should proceed here when we are in clustered mode.
  4544  	isClustered := s.JetStreamIsClustered()
  4545  	js, cc := s.getJetStreamCluster()
  4546  	if isClustered {
  4547  		if js == nil || cc == nil {
  4548  			return
  4549  		}
  4550  		if js.isLeaderless() {
  4551  			resp.Error = NewJSClusterNotAvailError()
  4552  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4553  			return
  4554  		}
  4555  		// Make sure we are meta leader.
  4556  		if !s.JetStreamIsLeader() {
  4557  			return
  4558  		}
  4559  	}
  4560  
  4561  	if hasJS, doErr := acc.checkJetStream(); !hasJS {
  4562  		if doErr {
  4563  			resp.Error = NewJSNotEnabledForAccountError()
  4564  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4565  		}
  4566  		return
  4567  	}
  4568  
  4569  	stream := streamNameFromSubject(subject)
  4570  	consumer := consumerNameFromSubject(subject)
  4571  
  4572  	if isClustered {
  4573  		sa := js.streamAssignment(acc.Name, stream)
  4574  		if sa == nil {
  4575  			resp.Error = NewJSStreamNotFoundError(Unless(err))
  4576  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4577  			return
  4578  		}
  4579  
  4580  		ca, ok := sa.consumers[consumer]
  4581  		if !ok || ca == nil {
  4582  			resp.Error = NewJSConsumerNotFoundError()
  4583  			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4584  			return
  4585  		}
  4586  
  4587  		nca := *ca
  4588  		pauseUTC := req.PauseUntil.UTC()
  4589  		if !pauseUTC.IsZero() {
  4590  			nca.Config.PauseUntil = &pauseUTC
  4591  		}
  4592  		eca := encodeAddConsumerAssignment(&nca)
  4593  		cc.meta.Propose(eca)
  4594  
  4595  		resp.PauseUntil = pauseUTC
  4596  		if resp.Paused = time.Now().Before(pauseUTC); resp.Paused {
  4597  			resp.PauseRemaining = time.Until(pauseUTC)
  4598  		}
  4599  		s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  4600  		return
  4601  	}
  4602  
  4603  	mset, err := acc.lookupStream(stream)
  4604  	if err != nil {
  4605  		resp.Error = NewJSStreamNotFoundError(Unless(err))
  4606  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4607  		return
  4608  	}
  4609  
  4610  	obs := mset.lookupConsumer(consumer)
  4611  	if obs == nil {
  4612  		resp.Error = NewJSConsumerNotFoundError()
  4613  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4614  		return
  4615  	}
  4616  
  4617  	ncfg := obs.cfg
  4618  	pauseUTC := req.PauseUntil.UTC()
  4619  	if !pauseUTC.IsZero() {
  4620  		ncfg.PauseUntil = &pauseUTC
  4621  	} else {
  4622  		ncfg.PauseUntil = nil
  4623  	}
  4624  
  4625  	if err := obs.updateConfig(&ncfg); err != nil {
  4626  		// The only type of error that should be returned here is from o.store,
  4627  		// so use a store failed error type.
  4628  		resp.Error = NewJSConsumerStoreFailedError(err)
  4629  		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
  4630  		return
  4631  	}
  4632  
  4633  	resp.PauseUntil = pauseUTC
  4634  	if resp.Paused = time.Now().Before(pauseUTC); resp.Paused {
  4635  		resp.PauseRemaining = time.Until(pauseUTC)
  4636  	}
  4637  	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
  4638  }
  4639  
  4640  // sendJetStreamAPIAuditAdvisor will send the audit event for a given event.
  4641  func (s *Server) sendJetStreamAPIAuditAdvisory(ci *ClientInfo, acc *Account, subject, request, response string) {
  4642  	s.publishAdvisory(acc, JSAuditAdvisory, JSAPIAudit{
  4643  		TypedEvent: TypedEvent{
  4644  			Type: JSAPIAuditType,
  4645  			ID:   nuid.Next(),
  4646  			Time: time.Now().UTC(),
  4647  		},
  4648  		Server:   s.Name(),
  4649  		Client:   ci,
  4650  		Subject:  subject,
  4651  		Request:  request,
  4652  		Response: response,
  4653  		Domain:   s.getOpts().JetStreamDomain,
  4654  	})
  4655  }