From 371be24ebf9a9806a4c8a6695bcb3151b439a9c5 Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Sat, 7 Nov 2026 17:27:02 -0500 Subject: [PATCH] feat(natsstore): connect to NATS with the configured credentials and TLS Auth and TLS options map one to one onto the nats CLI variables, and failures must not echo URL userinfo, so connection errors are redacted. Tests run against a real server in Docker so credential handling is exercised for real. Signed-off-by: Yordis Prieto --- go.mod | 6 +- go.sum | 8 +- internal/store/natsstore/connect.go | 210 ++++++++++++++++++ internal/store/natsstore/connect_test.go | 172 ++++++++++++++ internal/store/natsstore/natstest/natstest.go | 137 ++++++++++++ 5 files changed, 529 insertions(+), 4 deletions(-) create mode 100644 internal/store/natsstore/connect.go create mode 100644 internal/store/natsstore/connect_test.go create mode 100644 internal/store/natsstore/natstest/natstest.go diff --git a/go.mod b/go.mod index 5330c35b5f2..ccee8e4514b 100644 --- a/go.mod +++ b/go.mod @@ -16,10 +16,12 @@ require ( github.com/gorilla/websocket v1.5.3 github.com/jackc/pgx/v5 v5.9.2 github.com/joho/godotenv v1.5.1 - github.com/klauspost/compress v1.17.4 + github.com/klauspost/compress v1.20.0 github.com/libp2p/zeroconf/v2 v2.2.0 github.com/miekg/dns v1.1.43 github.com/minio/minio-go/v7 v7.0.66 + github.com/nats-io/nats.go v1.55.0 + github.com/nats-io/nkeys v0.4.17 github.com/pion/ice/v4 v4.3.0 github.com/pion/interceptor v0.1.45 github.com/pion/rtp v1.10.4 @@ -46,7 +48,7 @@ replace github.com/MoeForge/moego v0.1.0-alpha.1 => github.com/router-for-me/moe require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/dlclark/regexp2/v2 v2.5.1 // indirect - github.com/nats-io/nkeys v0.4.17 // indirect + github.com/nats-io/nuid v1.0.1 // indirect github.com/pion/datachannel v1.6.2 // indirect github.com/pion/dtls/v3 v3.1.5 // indirect github.com/pion/logging v0.2.4 // indirect diff --git a/go.sum b/go.sum index b5d9c6b697c..e57d0e9390d 100644 --- a/go.sum +++ b/go.sum @@ -110,8 +110,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kevinburke/ssh_config v1.6.0 h1:J1FBfmuVosPHf5GRdltRLhPJtJpTlMdKTBjRgTaQBFY= github.com/kevinburke/ssh_config v1.6.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA= +github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= @@ -155,8 +155,12 @@ github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELU github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= +github.com/nats-io/nats.go v1.55.0 h1:Ng8QKHdvdHIWoaiq0+d/aH1BWkxvcJxWJ0Y/9BPKx3M= +github.com/nats-io/nats.go v1.55.0/go.mod h1:y+DZoD1oBOYfZTU681eTUiUjI0vbqYGixNVFHcjHJ0k= github.com/nats-io/nkeys v0.4.17 h1:JAJrlDhOyQqOt0a1eg4cbIZ1Kc7+vmkCigAltpwQpVA= github.com/nats-io/nkeys v0.4.17/go.mod h1:llLgWoI0o4z/Q57q2R1kHfmocyhGV6VG/U18Glg1Afs= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/pelletier/go-toml/v2 v2.4.3-0.20260624044523-35f78d5908f1 h1:gIZQQ2+wbsdQGWLPDSdJFptR25tBCjSC0KbSIQZ1rgE= github.com/pelletier/go-toml/v2 v2.4.3-0.20260624044523-35f78d5908f1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pierrec/xxHash v0.1.5 h1:n/jBpwTHiER4xYvK3/CdPVnLDPchj8eTJFFLUb4QHBo= diff --git a/internal/store/natsstore/connect.go b/internal/store/natsstore/connect.go new file mode 100644 index 00000000000..0d8e1b7a9b2 --- /dev/null +++ b/internal/store/natsstore/connect.go @@ -0,0 +1,210 @@ +package natsstore + +import ( + "context" + "errors" + "fmt" + "strings" + "sync/atomic" + "time" + + "github.com/nats-io/nats.go" + "github.com/nats-io/nkeys" + log "github.com/sirupsen/logrus" +) + +const ( + // DefaultConnectTimeout bounds one connection attempt and the initial wait. + DefaultConnectTimeout = 30 * time.Second + // MaxReconnectDelay caps the exponential reconnect backoff. + MaxReconnectDelay = 30 * time.Second + + clientName = "cliproxyapi" +) + +// ErrNotConnected is returned when the initial connection is not established in time. +var ErrNotConnected = errors.New("not connected to NATS") + +// reconnectDelay doubles per attempt from one second and stops at MaxReconnectDelay. +func reconnectDelay(attempts int) time.Duration { + if attempts < 1 { + attempts = 1 + } + if attempts > 6 { + return MaxReconnectDelay + } + return min(MaxReconnectDelay, time.Duration(1<