profile
viewpoint

nats-io/nats.js 907

Node.js client for NATS, the cloud native messaging system.

nats-io/nats.rb 848

Ruby client for NATS, the cloud native messaging system.

nats-io/nats.java 310

Java client for NATS

nats-io/nats-top 197

A top-like tool for monitoring NATS servers.

nats-io/graft 106

A RAFT Election implementation in Go.

nats-io/stan.java 91

NATS Streaming Java Client

nats-io/nginx-nats 85

NGINX client module for NATS, the cloud native messaging system.

nats-io/elixir-nats 69

Elixir NATS client

nats-io/nats.py2 61

A Tornado based Python 2 client for NATS

nats-io/nats-general 35

General NATS Information

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (mset *Stream) subscribeInternal(subject string, cb msgHandler) (*subscript 	mset.sid++  	// Now create the subscription-	return c.processSub([]byte(subject), nil, []byte(strconv.Itoa(mset.sid)), cb, false)+	return c.processSub(c.createSub([]byte(subject), nil, []byte(strconv.Itoa(mset.sid)), cb), false)

Explained earlier.

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func getExpectedLastSeq(hdr []byte) uint64 { }  // processInboundJetStreamMsg handles processing messages bound for a stream.-func (mset *Stream) processInboundJetStreamMsg(_ *subscription, pc *client, subject, reply string, msg []byte) {+func (mset *Stream) processInboundJetStreamMsg(sub *subscription, pc *client, subject, reply string, msg []byte) {

Left over from some earlier code, will remove.

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (a *Account) AddStreamWithStore(config *StreamConfig, fsConfig *FileStoreCo  	// Setup the internal client. 	c := s.createInternalJetStreamClient()-	mset := &Stream{jsa: jsa, config: cfg, client: c, consumers: make(map[string]*Consumer)}+	mset := &Stream{jsa: jsa, config: cfg, client: c, consumers: make(map[string]*Consumer), nosubj: noSubjectsOK}

What about the issue with persisting the config? I will experiment to see if a non exported config option works, but I believe that it would not be persisted..

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (a *Account) AddStream(config *StreamConfig) (*Stream, error) {  // AddStreamWithStore adds a stream for the given account with custome store config options. func (a *Account) AddStreamWithStore(config *StreamConfig, fsConfig *FileStoreConfig) (*Stream, error) {+	if strings.HasPrefix(config.Name, mqttStreamNamePrefix) {

As I mentioned in the past, I wanted to make this a configuration but if it is not exported, it won't be persisted (json does not marshall non exported fields, right?). If so, on recovery I won't be able to rely on the config and have to check the name anyway. Of course, in some other places, like here, I could use the internal's config option instead of checking name.

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (s *Server) createClient(conn net.Conn, ws *websocket) *client { 	now := time.Now()  	c := &client{srv: s, nc: conn, opts: defaultOpts, mpay: maxPay, msubs: maxSubs, start: now, last: now, ws: ws}+	if mqtt != nil {+		c.mqtt = mqtt+		// Set some of the options here since MQTT clients don't+		// send a regular CONNECT (but have their own).+		c.opts.Lang = "mqtt"

No because some code check that Lang not empty means it is a "client" connection, as opposed to route, etc...

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (c *tlsMixConn) Read(b []byte) (int, error) { 	return c.Conn.Read(b) } -func (s *Server) createClient(conn net.Conn, ws *websocket) *client {+func (s *Server) createClient(conn net.Conn, ws *websocket, mqtt *mqtt) *client {

There would be a LOT of code to copy/paste and have to fix issues in 3 different places (we have been fixing issues in that code very recently).

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (s *Server) Start() { 		s.startWebsocketServer() 	} +	// MQTT+	if opts.MQTT.Port != 0 {

No, again, like we do for routes, etc.. this is how the server knows if it should start MQTT, it is by checking if the port is set.

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func setBaselineOptions(opts *Options) { 			opts.Websocket.Host = DEFAULT_HOST 		} 	}+	if opts.MQTT.Port != 0 {

You already mentioned the same for Websocket and my answer will be the same: setting the port is how users will enable MQTT, so I can't set a default port... We could have a "enabled" flag in mqtt{} instead, but that is a departure of what we have been doing (which is fine). For instance, this is how routes, leafnodes, etc.. are enabled, by setting the port, not having an "enabled" option.

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 type WebsocketOpts struct { 	HandshakeTimeout time.Duration } +// MQTTOpts are options for MQTT+type MQTTOpts struct {+	// The server will accept MQTT client connections on this hostname/IP.+	Host string+	// The server will accept MQTT client connections on this port.+	Port int++	// If no user name is provided when a client connects, will default to the+	// matching user from the global list of users in `Options.Users`.+	NoAuthUser string++	// Authentication section. If anything is configured in this section,+	// it will override the authorization configuration of regular clients.+	Username string+	Password string+	Token    string++	// Timeout for the authentication process.+	AuthTimeout float64

No, simply to be consistent with all the auth timeout that we have in all other configs where we have auth block.

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (mset *Stream) deliveryFormsCycle(deliverySubject string) bool { 	return false } -// This is same as check for delivery cycle.+// Check that the subject is a subset of the stream's configured subjects,+// or returns true if the stream has been created with no subject. func (mset *Stream) validSubject(partitionSubject string) bool {-	return mset.deliveryFormsCycle(partitionSubject)

Not sure what you mean, but yes, deliveryFormsCycle is still used in this branch. The thing is that I want validSubject() to return true if the stream is created with "no subject allowed", but if I were to put the check in deliveryFormsCycle I would have to return "true" (that it forms cycle) which does not make sense to me. This is why I originally I duplicated the code from deliveryFormsCycle but made it about validating the subject.

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (c *client) parseSub(argo []byte, noForward bool) error { 	arg := make([]byte, len(argo)) 	copy(arg, argo) 	args := splitArg(arg)-	var (-		subject []byte-		queue   []byte-		sid     []byte-	)+	sub := &subscription{client: c} 	switch len(args) { 	case 2:-		subject = args[0]-		queue = nil-		sid = args[1]+		sub.subject = args[0]+		sub.queue = nil+		sub.sid = args[1] 	case 3:-		subject = args[0]-		queue = args[1]-		sid = args[2]+		sub.subject = args[0]+		sub.queue = args[1]+		sub.sid = args[2] 	default: 		return fmt.Errorf("processSub Parse Error: '%s'", arg) 	} 	// If there was an error, it has been sent to the client. We don't return an 	// error here to not close the connection as a parsing error.-	c.processSub(subject, queue, sid, nil, noForward)+	c.processSub(sub, noForward) 	return nil } -func (c *client) processSub(subject, queue, bsid []byte, cb msgHandler, noForward bool) (*subscription, error) {-	// Create the subscription-	sub := &subscription{client: c, subject: subject, queue: queue, sid: bsid, icb: cb}+func (c *client) createSub(subject, queue, sid []byte, cb msgHandler) *subscription {+	return &subscription{client: c, subject: subject, queue: queue, sid: sid, icb: cb}+}++func (c *client) processSub(sub *subscription, noForward bool) (*subscription, error) {

There is qos, but not only that, the subscription has a mqtt field that holds the JS consumer it is attached to. I want this to be set before I call processSub() because I want to make sure that this is set prior to add the sub to sublist. You can't set things to the sub after processSub() returns, it is simply not safe. Remember that I had to fix races where you would set sub.icb after calling processSub(). For the retained message, I don't think in the spec they say that they must be sent before any incoming messages, although my experience with some mqtt brokers is that they are sent first.

kozlovic

comment created time in 2 hours

push eventnats-io/nats-server

Derek Collison

commit sha 7e27042e6e6da714328bfbccc1774966012d8771

Fix for #1736 When a system account was configured and not the default when we did a reload we would lose the JetStream service exports. Signed-off-by: Derek Collison <derek@nats.io>

view details

Derek Collison

commit sha 4e6d600ecc0d1c29fbc984bd31b88628358c8608

Also make sure account works after reload Signed-off-by: Derek Collison <derek@nats.io>

view details

Derek Collison

commit sha 3ec2b6d00f52d9cc4614eee57d9c76f650bfe399

Version bump Signed-off-by: Derek Collison <derek@nats.io>

view details

Derek Collison

commit sha bfb726e8e979e0b44497b34e54a6209174d1c14b

Make sure to clear JS resources on reload Signed-off-by: Derek Collison <derek@nats.io>

view details

Derek Collison

commit sha af81a2013d7b2c1d8a91a0e96473954df60aebbd

Log errors Signed-off-by: Derek Collison <derek@nats.io>

view details

Derek Collison

commit sha 2e26d9195eb155d01a5e5c4542448595c7e22c42

Merge pull request #1756 from nats-io/jsreload Fix for #1736

view details

push time in 2 hours

delete branch nats-io/nats-server

delete branch : jsreload

delete time in 2 hours

PR merged nats-io/nats-server

Reviewers
Fix for #1736

When a system account was configured and not the default when we did a reload we would lose the JetStream service exports.

Signed-off-by: Derek Collison derek@nats.io

Resolves #1736

/cc @nats-io/core

+197 -8

13 comments

5 changed files

derekcollison

pr closed time in 2 hours

issue closednats-io/nats-server

SIGHUP reload loses JetStream availability

Defect

Make sure that these boxes are checked before submitting your issue -- thank you!

  • [x] Included nats-server -DV output
  • [x] Included a [Minimal, Complete, and Verifiable example] (https://stackoverflow.com/help/mcve)

Versions of nats-server and affected client libraries used:

  • nats-server v2.2.0-beta.33 (git commit 4d51a41d) with one patch, that from #1734 (to unbreak FreeBSD)
  • client nats CLI tool from the Jetstream repo, v0.0.19-56-g4d382ff with build modified only to replace nats-server module with ../nats-server to pull in the FreeBSD fix
  • client nats CLI tool, on Linux, version v0.0.19-27-g8d386d1 built with clean repo

<details><summary><tt>/usr/local/sbin/nats-server -c /etc/nats/nats.conf -DV</tt></summary>

[56863] 2020/11/22 20:51:28.835595 [INF] Starting nats-server version 2.2.0-beta.33
[56863] 2020/11/22 20:51:28.835736 [DBG] Go build version go1.15.5
[56863] 2020/11/22 20:51:28.835744 [INF] Git commit [4d51a41d]
[56863] 2020/11/22 20:51:28.835823 [WRN] Plaintext passwords detected, use nkeys or bcrypt
[56863] 2020/11/22 20:51:28.835833 [INF] Using configuration file: /etc/nats/nats.conf
[56863] 2020/11/22 20:51:28.836179 [INF] Starting JetStream
[56863] 2020/11/22 20:51:28.836747 [WRN]     _ ___ _____ ___ _____ ___ ___   _   __  __
[56863] 2020/11/22 20:51:28.836763 [WRN]  _ | | __|_   _/ __|_   _| _ \ __| /_\ |  \/  |
[56863] 2020/11/22 20:51:28.836770 [WRN] | || | _|  | | \__ \ | | |   / _| / _ \| |\/| |
[56863] 2020/11/22 20:51:28.836776 [WRN]  \__/|___| |_| |___/ |_| |_|_\___/_/ \_\_|  |_|
[56863] 2020/11/22 20:51:28.836782 [WRN] 
[56863] 2020/11/22 20:51:28.836787 [WRN]                _         _
[56863] 2020/11/22 20:51:28.836793 [WRN]               | |__  ___| |_ __ _
[56863] 2020/11/22 20:51:28.836798 [WRN]               | '_ \/ -_)  _/ _` |
[56863] 2020/11/22 20:51:28.836803 [WRN]               |_.__/\___|\__\__,_|
[56863] 2020/11/22 20:51:28.836809 [WRN] 
[56863] 2020/11/22 20:51:28.836814 [WRN]          JetStream is a Beta feature
[56863] 2020/11/22 20:51:28.836819 [WRN]     https://github.com/nats-io/jetstream
[56863] 2020/11/22 20:51:28.836825 [INF] 
[56863] 2020/11/22 20:51:28.836830 [INF] ----------- JETSTREAM -----------
[56863] 2020/11/22 20:51:28.836848 [INF]   Max Memory:      32.00 MB
[56863] 2020/11/22 20:51:28.836860 [INF]   Max Storage:     16.00 GB
[56863] 2020/11/22 20:51:28.836870 [INF]   Store Directory: "/srv/nats/js1/store"
[56863] 2020/11/22 20:51:28.836877 [DBG]   Exports:
[56863] 2020/11/22 20:51:28.836884 [DBG]      $JS.API.INFO
[56863] 2020/11/22 20:51:28.836894 [DBG]      $JS.API.STREAM.TEMPLATE.CREATE.*
[56863] 2020/11/22 20:51:28.836903 [DBG]      $JS.API.STREAM.TEMPLATE.NAMES
[56863] 2020/11/22 20:51:28.836912 [DBG]      $JS.API.STREAM.TEMPLATE.INFO.*
[56863] 2020/11/22 20:51:28.836921 [DBG]      $JS.API.STREAM.TEMPLATE.DELETE.*
[56863] 2020/11/22 20:51:28.836930 [DBG]      $JS.API.STREAM.CREATE.*
[56863] 2020/11/22 20:51:28.836939 [DBG]      $JS.API.STREAM.UPDATE.*
[56863] 2020/11/22 20:51:28.836948 [DBG]      $JS.API.STREAM.NAMES
[56863] 2020/11/22 20:51:28.836959 [DBG]      $JS.API.STREAM.LIST
[56863] 2020/11/22 20:51:28.836969 [DBG]      $JS.API.STREAM.INFO.*
[56863] 2020/11/22 20:51:28.836979 [DBG]      $JS.API.STREAM.LOOKUP
[56863] 2020/11/22 20:51:28.836989 [DBG]      $JS.API.STREAM.DELETE.*
[56863] 2020/11/22 20:51:28.836999 [DBG]      $JS.API.STREAM.PURGE.*
[56863] 2020/11/22 20:51:28.837012 [DBG]      $JS.API.STREAM.SNAPSHOT.*
[56863] 2020/11/22 20:51:28.837022 [DBG]      $JS.API.STREAM.RESTORE.*
[56863] 2020/11/22 20:51:28.837032 [DBG]      $JS.API.STREAM.MSG.DELETE.*
[56863] 2020/11/22 20:51:28.837043 [DBG]      $JS.API.STREAM.MSG.GET.*
[56863] 2020/11/22 20:51:28.837053 [DBG]      $JS.API.CONSUMER.CREATE.*
[56863] 2020/11/22 20:51:28.837064 [DBG]      $JS.API.CONSUMER.DURABLE.CREATE.*.*
[56863] 2020/11/22 20:51:28.837077 [DBG]      $JS.API.CONSUMER.NAMES.*
[56863] 2020/11/22 20:51:28.837089 [DBG]      $JS.API.CONSUMER.LIST.*
[56863] 2020/11/22 20:51:28.837099 [DBG]      $JS.API.CONSUMER.INFO.*.*
[56863] 2020/11/22 20:51:28.837110 [DBG]      $JS.API.CONSUMER.DELETE.*.*
[56863] 2020/11/22 20:51:28.837121 [INF] ----------------------------------------
[56863] 2020/11/22 20:51:28.837377 [DBG] Enabled JetStream for account "Foobar"
[56863] 2020/11/22 20:51:28.837394 [DBG]   Max Memory:      -1 B
[56863] 2020/11/22 20:51:28.837404 [DBG]   Max Storage:     -1 B
[56863] 2020/11/22 20:51:28.837450 [INF]   Recovering JetStream state for account "Foobar"
[56863] 2020/11/22 20:51:28.837683 [INF] JetStream state for account "Foobar" recovered
[56863] 2020/11/22 20:51:28.837906 [DBG] Enabled JetStream for account "Anonymous"
[56863] 2020/11/22 20:51:28.837921 [DBG]   Max Memory:      -1 B
[56863] 2020/11/22 20:51:28.837931 [DBG]   Max Storage:     -1 B
[56863] 2020/11/22 20:51:28.837967 [INF]   Recovering JetStream state for account "Anonymous"
[56863] 2020/11/22 20:51:28.839761 [INF]   Restored 7 messages for Stream "SVEN-GIT-MAINLOG"
[56863] 2020/11/22 20:51:28.839946 [INF]   Recovering 1 Consumers for Stream - "SVEN-GIT-MAINLOG"
[56863] 2020/11/22 20:51:28.841803 [INF]   Restored 1 messages for Stream "SVEN-GIT-PUSHES"
[56863] 2020/11/22 20:51:28.843210 [INF]   Restored 1 messages for Stream "SVEN-GIT-REFS"
[56863] 2020/11/22 20:51:28.843418 [INF] JetStream state for account "Anonymous" recovered
[56863] 2020/11/22 20:51:28.843577 [INF] Starting http monitor on 0.0.0.0:8222
[56863] 2020/11/22 20:51:28.843654 [INF] Listening for client connections on 0.0.0.0:4222
[56863] 2020/11/22 20:51:28.843665 [INF] TLS required for client connections
[56863] 2020/11/22 20:51:28.843673 [INF] Server id is NBFQQQMBBS4JA4DXYSKM6UJMX4CEQKNN7YUVQJRYLL6YIY7Y6MCWDU4L
[56863] 2020/11/22 20:51:28.843680 [INF] Server name is NBFQQQMBBS4JA4DXYSKM6UJMX4CEQKNN7YUVQJRYLL6YIY7Y6MCWDU4L
[56863] 2020/11/22 20:51:28.843686 [INF] Server is ready

</details>

<details><summary><tt>nats.conf</tt>, partially redacted</summary>

port: 4222
monitor_port: 8222
client_advertise: nats.lan
jetstream {
  store_dir: "/srv/nats/js1/store"
  max_memory_store: 32MiB
  max_file_store: 16GiB
}
tls {
    ca_file:   /etc/ssl/cert.pem
    cert_file: /etc/nats/tls.crt
    key_file:  /etc/nats/tls.key
}
accounts: {
  Anonymous: {
    jetstream: enabled
    users: [
      {user: anonymous, password: "none"}
    ]
  }
  System: {
    users: [
      {user: control, password: "$crypted-pw-censored"}
    ]
  }
  Foobar: {
    jetstream: enabled
    users: [
      {user: foo1, password: "$crypted-pw-censored"}
    ]
  }
}
system_account: System
no_auth_user: anonymous

</details>

OS/Container environment:

FreeBSD 11.4, but I think this causes a symptom I saw in an Alpine Linux 3.12.1 container too.

Steps or code to reproduce the issue:

  1. Start NATS server. See it load JS data store, have client able to query JS streams
  2. Send server a SIGHUP
  3. See the nats: error: could not create Stream: nats: no responders available for request error message
  4. Restart server, have nats client able to query streams
  5. Send server a SIGHUP, see that this is repeatable: once one or more SIGHUPs has been received by the NATS server, it stops responding to jetstream client requests

Expected result:

Server should work right after a reload.

Actual result:

Reload breaks Jetstream.

In the logs here, I hit enter for a blank line between the client request, the reload, and the second client request.

<details><summary>nats -DV output across the reload</summary>

[58811] 2020/11/22 21:02:27.007071 [DBG] 192.168.120.1:57228 - cid:9 - Client connection created
[58811] 2020/11/22 21:02:27.007594 [DBG] 192.168.120.1:57228 - cid:9 - Starting TLS client connection handshake
[58811] 2020/11/22 21:02:27.054567 [DBG] 192.168.120.1:57228 - cid:9 - TLS handshake complete
[58811] 2020/11/22 21:02:27.054595 [DBG] 192.168.120.1:57228 - cid:9 - TLS version 1.3, cipher suite TLS_AES_128_GCM_SHA256
[58811] 2020/11/22 21:02:27.054733 [TRC] 192.168.120.1:57228 - cid:9 - <<- [CONNECT {"verbose":false,"pedantic":false,"tls_required":false,"name":"NATS CLI Version v0.0.19-27-g8d386
d1","lang":"go","version":"1.11.0","protocol":1,"echo":true,"headers":true,"no_responders":true}]
[58811] 2020/11/22 21:02:27.054985 [TRC] 192.168.120.1:57228 - cid:9 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - <<- [PING]
[58811] 2020/11/22 21:02:27.055004 [TRC] 192.168.120.1:57228 - cid:9 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - ->> [PONG]
[58811] 2020/11/22 21:02:27.056574 [TRC] 192.168.120.1:57228 - cid:9 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - <<- [SUB _INBOX.e2g0RbGKlGGqOaTYEqwBir.*  1]
[58811] 2020/11/22 21:02:27.056629 [TRC] 192.168.120.1:57228 - cid:9 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - <<- [PUB $JS.API.INFO _INBOX.e2g0RbGKlGGqOaTYEqwBir.ZrEW2a
tg 0]
[58811] 2020/11/22 21:02:27.056647 [TRC] 192.168.120.1:57228 - cid:9 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - <<- MSG_PAYLOAD: [""]
[58811] 2020/11/22 21:02:27.057170 [TRC] 192.168.120.1:57228 - cid:9 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - ->> [MSG _INBOX.e2g0RbGKlGGqOaTYEqwBir.ZrEW2atg 1 223]
[58811] 2020/11/22 21:02:27.061477 [DBG] 192.168.120.1:57228 - cid:9 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - Client connection closed: Client Closed
[58811] 2020/11/22 21:02:27.061524 [TRC] 192.168.120.1:57228 - cid:9 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - <-> [DELSUB 1]

[58811] 2020/11/22 21:02:40.664207 [DBG] Trapped "hangup" signal
[58811] 2020/11/22 21:02:40.877400 [INF] Reloaded: authorization users
[58811] 2020/11/22 21:02:40.877431 [INF] Reloaded: accounts
[58811] 2020/11/22 21:02:40.877442 [INF] Reloaded: tls = enabled
[58811] 2020/11/22 21:02:40.877545 [TRC] ACCOUNT - <-> [DELSUB 1]
[58811] 2020/11/22 21:02:40.877572 [DBG] ACCOUNT - Account connection closed: Internal Client
[58811] 2020/11/22 21:02:40.877611 [TRC] ACCOUNT - <-> [DELSUB 23]
[58811] 2020/11/22 21:02:40.877634 [TRC] ACCOUNT - <-> [DELSUB 2]
[58811] 2020/11/22 21:02:40.877653 [TRC] ACCOUNT - <-> [DELSUB 8]
[58811] 2020/11/22 21:02:40.877672 [TRC] ACCOUNT - <-> [DELSUB 13]
[58811] 2020/11/22 21:02:40.877691 [TRC] ACCOUNT - <-> [DELSUB 14]
[58811] 2020/11/22 21:02:40.877709 [TRC] ACCOUNT - <-> [DELSUB 22]
[58811] 2020/11/22 21:02:40.877728 [TRC] ACCOUNT - <-> [DELSUB 21]
[58811] 2020/11/22 21:02:40.877746 [TRC] ACCOUNT - <-> [DELSUB 3]
[58811] 2020/11/22 21:02:40.877764 [TRC] ACCOUNT - <-> [DELSUB 5]
[58811] 2020/11/22 21:02:40.877783 [TRC] ACCOUNT - <-> [DELSUB 9]
[58811] 2020/11/22 21:02:40.877803 [TRC] ACCOUNT - <-> [DELSUB 11]
[58811] 2020/11/22 21:02:40.877822 [TRC] ACCOUNT - <-> [DELSUB 20]
[58811] 2020/11/22 21:02:40.877840 [TRC] ACCOUNT - <-> [DELSUB 6]
[58811] 2020/11/22 21:02:40.877857 [TRC] ACCOUNT - <-> [DELSUB 12]
[58811] 2020/11/22 21:02:40.877878 [TRC] ACCOUNT - <-> [DELSUB 16]
[58811] 2020/11/22 21:02:40.877896 [TRC] ACCOUNT - <-> [DELSUB 18]
[58811] 2020/11/22 21:02:40.877914 [TRC] ACCOUNT - <-> [DELSUB 19]
[58811] 2020/11/22 21:02:40.877932 [TRC] ACCOUNT - <-> [DELSUB 17]
[58811] 2020/11/22 21:02:40.877951 [TRC] ACCOUNT - <-> [DELSUB 1]
[58811] 2020/11/22 21:02:40.877968 [TRC] ACCOUNT - <-> [DELSUB 4]
[58811] 2020/11/22 21:02:40.877988 [TRC] ACCOUNT - <-> [DELSUB 7]
[58811] 2020/11/22 21:02:40.878006 [TRC] ACCOUNT - <-> [DELSUB 10]
[58811] 2020/11/22 21:02:40.878024 [TRC] ACCOUNT - <-> [DELSUB 15]
[58811] 2020/11/22 21:02:40.878040 [DBG] ACCOUNT - Account connection closed: Internal Client
[58811] 2020/11/22 21:02:40.878056 [DBG] ACCOUNT - Account connection closed: Internal Client
[58811] 2020/11/22 21:02:40.878079 [TRC] ACCOUNT - <-> [DELSUB 15]
[58811] 2020/11/22 21:02:40.878099 [TRC] ACCOUNT - <-> [DELSUB 18]
[58811] 2020/11/22 21:02:40.878117 [TRC] ACCOUNT - <-> [DELSUB 23]
[58811] 2020/11/22 21:02:40.878135 [TRC] ACCOUNT - <-> [DELSUB 11]
[58811] 2020/11/22 21:02:40.878154 [TRC] ACCOUNT - <-> [DELSUB 20]
[58811] 2020/11/22 21:02:40.878172 [TRC] ACCOUNT - <-> [DELSUB 22]
[58811] 2020/11/22 21:02:40.878190 [TRC] ACCOUNT - <-> [DELSUB 2]
[58811] 2020/11/22 21:02:40.878208 [TRC] ACCOUNT - <-> [DELSUB 3]
[58811] 2020/11/22 21:02:40.878228 [TRC] ACCOUNT - <-> [DELSUB 8]
[58811] 2020/11/22 21:02:40.878247 [TRC] ACCOUNT - <-> [DELSUB 10]
[58811] 2020/11/22 21:02:40.878266 [TRC] ACCOUNT - <-> [DELSUB 12]
[58811] 2020/11/22 21:02:40.878284 [TRC] ACCOUNT - <-> [DELSUB 14]
[58811] 2020/11/22 21:02:40.878302 [TRC] ACCOUNT - <-> [DELSUB 16]
[58811] 2020/11/22 21:02:40.878320 [TRC] ACCOUNT - <-> [DELSUB 17]
[58811] 2020/11/22 21:02:40.878339 [TRC] ACCOUNT - <-> [DELSUB 1]
[58811] 2020/11/22 21:02:40.878357 [TRC] ACCOUNT - <-> [DELSUB 5]
[58811] 2020/11/22 21:02:40.878376 [TRC] ACCOUNT - <-> [DELSUB 7]
[58811] 2020/11/22 21:02:40.878394 [TRC] ACCOUNT - <-> [DELSUB 9]
[58811] 2020/11/22 21:02:40.878411 [TRC] ACCOUNT - <-> [DELSUB 19]
[58811] 2020/11/22 21:02:40.878429 [TRC] ACCOUNT - <-> [DELSUB 4]
[58811] 2020/11/22 21:02:40.878447 [TRC] ACCOUNT - <-> [DELSUB 6]
[58811] 2020/11/22 21:02:40.878466 [TRC] ACCOUNT - <-> [DELSUB 13]
[58811] 2020/11/22 21:02:40.878484 [TRC] ACCOUNT - <-> [DELSUB 21]
[58811] 2020/11/22 21:02:40.878500 [DBG] ACCOUNT - Account connection closed: Internal Client
[58811] 2020/11/22 21:02:40.878536 [INF] Reloaded server configuration

[58811] 2020/11/22 21:02:46.959419 [DBG] 192.168.120.1:57230 - cid:11 - Client connection created
[58811] 2020/11/22 21:02:46.959556 [DBG] 192.168.120.1:57230 - cid:11 - Starting TLS client connection handshake
[58811] 2020/11/22 21:02:47.019747 [DBG] 192.168.120.1:57230 - cid:11 - TLS handshake complete
[58811] 2020/11/22 21:02:47.019775 [DBG] 192.168.120.1:57230 - cid:11 - TLS version 1.3, cipher suite TLS_AES_128_GCM_SHA256
[58811] 2020/11/22 21:02:47.019910 [TRC] 192.168.120.1:57230 - cid:11 - <<- [CONNECT {"verbose":false,"pedantic":false,"tls_required":false,"name":"NATS CLI Version v0.0.19-27-g8d38
6d1","lang":"go","version":"1.11.0","protocol":1,"echo":true,"headers":true,"no_responders":true}]
[58811] 2020/11/22 21:02:47.020014 [TRC] 192.168.120.1:57230 - cid:11 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - <<- [PING]
[58811] 2020/11/22 21:02:47.020033 [TRC] 192.168.120.1:57230 - cid:11 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - ->> [PONG]
[58811] 2020/11/22 21:02:47.021745 [TRC] 192.168.120.1:57230 - cid:11 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - <<- [SUB _INBOX.7sX7qtrb7vQnbJxaXwD9F2.*  1]
[58811] 2020/11/22 21:02:47.021792 [TRC] 192.168.120.1:57230 - cid:11 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - <<- [PUB $JS.API.INFO _INBOX.7sX7qtrb7vQnbJxaXwD9F2.GcNCP
j2g 0]
[58811] 2020/11/22 21:02:47.021814 [TRC] 192.168.120.1:57230 - cid:11 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - <<- MSG_PAYLOAD: [""]
[58811] 2020/11/22 21:02:47.024865 [DBG] 192.168.120.1:57230 - cid:11 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - Client connection closed: Client Closed
[58811] 2020/11/22 21:02:47.024905 [TRC] 192.168.120.1:57230 - cid:11 - "v1.11.0:go:NATS CLI Version v0.0.19-27-g8d386d1" - <-> [DELSUB 1]

^C[58811] 2020/11/22 21:02:49.844273 [DBG] Trapped "interrupt" signal
[58811] 2020/11/22 21:02:49.844379 [TRC] JETSTREAM - <-> [DELSUB 2]
[58811] 2020/11/22 21:02:49.844408 [TRC] JETSTREAM - <-> [DELSUB 3]
[58811] 2020/11/22 21:02:49.844512 [DBG] JETSTREAM - JetStream connection closed: Client Closed
[58811] 2020/11/22 21:02:49.846995 [DBG] JETSTREAM - JetStream connection closed: Client Closed
[58811] 2020/11/22 21:02:49.847203 [DBG] JETSTREAM - JetStream connection closed: Client Closed
[58811] 2020/11/22 21:02:49.847342 [DBG] JETSTREAM - JetStream connection closed: Client Closed
[58811] 2020/11/22 21:02:49.847474 [INF] Initiating Shutdown...
[58811] 2020/11/22 21:02:49.847590 [DBG] Client accept loop exiting..
[58811] 2020/11/22 21:02:49.847609 [INF] Server Exiting..

</details>

closed time in 2 hours

philpennock

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (c *client) parseSub(argo []byte, noForward bool) error { 	arg := make([]byte, len(argo)) 	copy(arg, argo) 	args := splitArg(arg)-	var (-		subject []byte-		queue   []byte-		sid     []byte-	)+	sub := &subscription{client: c} 	switch len(args) { 	case 2:-		subject = args[0]-		queue = nil-		sid = args[1]+		sub.subject = args[0]+		sub.queue = nil+		sub.sid = args[1] 	case 3:-		subject = args[0]-		queue = args[1]-		sid = args[2]+		sub.subject = args[0]+		sub.queue = args[1]+		sub.sid = args[2] 	default: 		return fmt.Errorf("processSub Parse Error: '%s'", arg) 	} 	// If there was an error, it has been sent to the client. We don't return an 	// error here to not close the connection as a parsing error.-	c.processSub(subject, queue, sid, nil, noForward)+	c.processSub(sub, noForward) 	return nil } -func (c *client) processSub(subject, queue, bsid []byte, cb msgHandler, noForward bool) (*subscription, error) {-	// Create the subscription-	sub := &subscription{client: c, subject: subject, queue: queue, sid: bsid, icb: cb}+func (c *client) createSub(subject, queue, sid []byte, cb msgHandler) *subscription {+	return &subscription{client: c, subject: subject, queue: queue, sid: sid, icb: cb}+}++func (c *client) processSub(sub *subscription, noForward bool) (*subscription, error) {

What additional params do you need to pass? Can you not ass in retained message post this without causing issues?

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (c *client) parseSub(argo []byte, noForward bool) error { 	arg := make([]byte, len(argo)) 	copy(arg, argo) 	args := splitArg(arg)-	var (-		subject []byte-		queue   []byte-		sid     []byte-	)+	sub := &subscription{client: c} 	switch len(args) { 	case 2:-		subject = args[0]-		queue = nil-		sid = args[1]+		sub.subject = args[0]+		sub.queue = nil+		sub.sid = args[1] 	case 3:-		subject = args[0]-		queue = args[1]-		sid = args[2]+		sub.subject = args[0]+		sub.queue = args[1]+		sub.sid = args[2] 	default: 		return fmt.Errorf("processSub Parse Error: '%s'", arg) 	} 	// If there was an error, it has been sent to the client. We don't return an 	// error here to not close the connection as a parsing error.-	c.processSub(subject, queue, sid, nil, noForward)+	c.processSub(sub, noForward) 	return nil } -func (c *client) processSub(subject, queue, bsid []byte, cb msgHandler, noForward bool) (*subscription, error) {-	// Create the subscription-	sub := &subscription{client: c, subject: subject, queue: queue, sid: bsid, icb: cb}+func (c *client) createSub(subject, queue, sid []byte, cb msgHandler) *subscription {+	return &subscription{client: c, subject: subject, queue: queue, sid: sid, icb: cb}+}++func (c *client) processSub(sub *subscription, noForward bool) (*subscription, error) {

This has 2 advantages: reduce the number of parameters that we would have to had to processSub(). Granted we could create a suboption struct that we pass, but this is really equivalent to passing a sub object, even better if happen to not exist so we don't create the suboption object AND the subscription. The second is that I need the subscription object to "add" to it retained message prior to be added to the sublist and possibly starting to receive incoming messages.

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (c *client) parseSub(argo []byte, noForward bool) error { 	arg := make([]byte, len(argo)) 	copy(arg, argo) 	args := splitArg(arg)-	var (-		subject []byte-		queue   []byte-		sid     []byte-	)+	sub := &subscription{client: c} 	switch len(args) { 	case 2:-		subject = args[0]-		queue = nil-		sid = args[1]+		sub.subject = args[0]+		sub.queue = nil+		sub.sid = args[1] 	case 3:-		subject = args[0]-		queue = args[1]-		sid = args[2]+		sub.subject = args[0]+		sub.queue = args[1]+		sub.sid = args[2] 	default: 		return fmt.Errorf("processSub Parse Error: '%s'", arg) 	} 	// If there was an error, it has been sent to the client. We don't return an 	// error here to not close the connection as a parsing error.-	c.processSub(subject, queue, sid, nil, noForward)+	c.processSub(sub, noForward) 	return nil } -func (c *client) processSub(subject, queue, bsid []byte, cb msgHandler, noForward bool) (*subscription, error) {-	// Create the subscription-	sub := &subscription{client: c, subject: subject, queue: queue, sid: bsid, icb: cb}+func (c *client) createSub(subject, queue, sid []byte, cb msgHandler) *subscription {+	return &subscription{client: c, subject: subject, queue: queue, sid: sid, icb: cb}+}++func (c *client) processSub(sub *subscription, noForward bool) (*subscription, error) {

ok then why do you need to build the sub beforehand?

kozlovic

comment created time in 2 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (c *client) processPingTimer() { 	c.mu.Lock() 	c.ping.tmr = nil 	// Check if connection is still opened-	if c.isClosed() {+	if c.isClosed() || c.mqtt != nil {

c.kind is still CLIENT. As for websocket, mqtt clients are CLIENT connections. They just have extra field to maintain specific state. I can however create an isMqtt() that does the check though.

kozlovic

comment created time in 3 hours

Pull request review commentnats-io/nats-server

Fix for #1736

 func (s *Server) reloadAuthorization() {  	// We will double check all JetStream configs on a reload. 	if checkJetStream {+		s.getJetStream().clearResources()

ok will add.

derekcollison

comment created time in 3 hours

push eventnats-io/nats-server

Derek Collison

commit sha af81a2013d7b2c1d8a91a0e96473954df60aebbd

Log errors Signed-off-by: Derek Collison <derek@nats.io>

view details

push time in 3 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (c *client) parseSub(argo []byte, noForward bool) error { 	arg := make([]byte, len(argo)) 	copy(arg, argo) 	args := splitArg(arg)-	var (-		subject []byte-		queue   []byte-		sid     []byte-	)+	sub := &subscription{client: c} 	switch len(args) { 	case 2:-		subject = args[0]-		queue = nil-		sid = args[1]+		sub.subject = args[0]+		sub.queue = nil+		sub.sid = args[1] 	case 3:-		subject = args[0]-		queue = args[1]-		sid = args[2]+		sub.subject = args[0]+		sub.queue = args[1]+		sub.sid = args[2] 	default: 		return fmt.Errorf("processSub Parse Error: '%s'", arg) 	} 	// If there was an error, it has been sent to the client. We don't return an 	// error here to not close the connection as a parsing error.-	c.processSub(subject, queue, sid, nil, noForward)+	c.processSub(sub, noForward) 	return nil } -func (c *client) processSub(subject, queue, bsid []byte, cb msgHandler, noForward bool) (*subscription, error) {-	// Create the subscription-	sub := &subscription{client: c, subject: subject, queue: queue, sid: bsid, icb: cb}+func (c *client) createSub(subject, queue, sid []byte, cb msgHandler) *subscription {+	return &subscription{client: c, subject: subject, queue: queue, sid: sid, icb: cb}+}++func (c *client) processSub(sub *subscription, noForward bool) (*subscription, error) {

This is because a subscription on "foo" may already exist, so if I call processSub() with a new subscription object but for the same subject/sid, then the existing one is returned (and some of the sub's field are updated - under the client lock. For mqtt it means the qos and other).

kozlovic

comment created time in 3 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (s *Sublist) collectAllSubs(l *level, subs *[]*subscription) { 		s.collectAllSubs(l.fwc.next, subs) 	} }++func (s *Sublist) ReverseMatch(subject string) *SublistResult {

Description here be good.

kozlovic

comment created time in 3 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (a *Account) AddStream(config *StreamConfig) (*Stream, error) {  // AddStreamWithStore adds a stream for the given account with custome store config options. func (a *Account) AddStreamWithStore(config *StreamConfig, fsConfig *FileStoreConfig) (*Stream, error) {+	if strings.HasPrefix(config.Name, mqttStreamNamePrefix) {

Meaning a non-public internal bool in stream config. The consumers could inherit that and bypass some of the subject stuff off of that.

kozlovic

comment created time in 3 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (mset *Stream) subscribeInternal(subject string, cb msgHandler) (*subscript 	mset.sid++  	// Now create the subscription-	return c.processSub([]byte(subject), nil, []byte(strconv.Itoa(mset.sid)), cb, false)+	return c.processSub(c.createSub([]byte(subject), nil, []byte(strconv.Itoa(mset.sid)), cb), false)

Why did you change first arg to *subscription?

kozlovic

comment created time in 3 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func getExpectedLastSeq(hdr []byte) uint64 { }  // processInboundJetStreamMsg handles processing messages bound for a stream.-func (mset *Stream) processInboundJetStreamMsg(_ *subscription, pc *client, subject, reply string, msg []byte) {+func (mset *Stream) processInboundJetStreamMsg(sub *subscription, pc *client, subject, reply string, msg []byte) {

I see you set sub but I don't think you use it.

kozlovic

comment created time in 3 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (s *Server) createClient(conn net.Conn, ws *websocket) *client { 	now := time.Now()  	c := &client{srv: s, nc: conn, opts: defaultOpts, mpay: maxPay, msubs: maxSubs, start: now, last: now, ws: ws}+	if mqtt != nil {+		c.mqtt = mqtt+		// Set some of the options here since MQTT clients don't+		// send a regular CONNECT (but have their own).+		c.opts.Lang = "mqtt"

Wonder if we should leave blank?

kozlovic

comment created time in 3 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (a *Account) AddStream(config *StreamConfig) (*Stream, error) {  // AddStreamWithStore adds a stream for the given account with custome store config options. func (a *Account) AddStreamWithStore(config *StreamConfig, fsConfig *FileStoreConfig) (*Stream, error) {+	if strings.HasPrefix(config.Name, mqttStreamNamePrefix) {+		return nil, fmt.Errorf("prefix %q is reserved for MQTT, unable to create stream %q", mqttStreamNamePrefix, config.Name)

Would just say reserved, not say anything about MQTT per se.

kozlovic

comment created time in 3 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (a *Account) AddStreamWithStore(config *StreamConfig, fsConfig *FileStoreCo  	// Setup the internal client. 	c := s.createInternalJetStreamClient()-	mset := &Stream{jsa: jsa, config: cfg, client: c, consumers: make(map[string]*Consumer)}+	mset := &Stream{jsa: jsa, config: cfg, client: c, consumers: make(map[string]*Consumer), nosubj: noSubjectsOK}

Let's move to stream and consumer config as internal fields in config struct.

interestNotRequired

kozlovic

comment created time in 3 hours

Pull request review commentnats-io/nats-server

[ADDED] MQTT Support

 func (a *Account) AddStream(config *StreamConfig) (*Stream, error) {  // AddStreamWithStore adds a stream for the given account with custome store config options. func (a *Account) AddStreamWithStore(config *StreamConfig, fsConfig *FileStoreConfig) (*Stream, error) {+	if strings.HasPrefix(config.Name, mqttStreamNamePrefix) {+		return nil, fmt.Errorf("prefix %q is reserved for MQTT, unable to create stream %q", mqttStreamNamePrefix, config.Name)+	}+	return a.addStreamWithStore(config, fsConfig, false)+}++func (a *Account) addStreamWithStore(config *StreamConfig, fsConfig *FileStoreConfig, noSubjectsOK bool) (*Stream, error) { 	s, jsa, err := a.checkForJetStream() 	if err != nil { 		return nil, err 	}  	// Sensible defaults.-	cfg, err := checkStreamCfg(config)+	cfg, err := checkStreamCfg(config, noSubjectsOK)

Same here with internal option.

kozlovic

comment created time in 3 hours

more