Skip to content

Commit 4c68fc5

Browse files
omer9564claude
andauthored
Add optional JetStream domain config to the natsstore plugin (PER-13735) (#5)
* feat(natsstore): add optional JetStream domain config (PER-13735) Adds a `domain` plugin option; when set, the JetStream context is created with nats.Domain so API calls are scoped to $JS.<domain>.API. Empty preserves the default domain-less prefix, so existing deployments are unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(natsstore): close NATS connection and defer connected state until JetStream init succeeds Addresses review comments: - #5 (comment) (@copilot-pull-request-reviewer) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent ff5b68e commit 4c68fc5

4 files changed

Lines changed: 22 additions & 5 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ services:
8989
| `tls_key` | string | `""` | Path to TLS private key |
9090
| `tls_ca_cert` | string | `""` | Path to TLS CA certificate |
9191
| `tls_insecure` | bool | `false` | Skip TLS certificate verification |
92+
| `domain` | string | `""` | JetStream domain; scopes API calls to `$JS.<domain>.API`. Needed when NATS is reached across a leafnode boundary (optional) |
9293

9394
## Built-in Functions
9495

pkg/natsstore/config.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ type Config struct {
4242
TLSCACert string `json:"tls_ca_cert,omitempty"`
4343
TLSInsecure bool `json:"tls_insecure,omitempty"`
4444

45+
// Domain is an optional JetStream domain. When set, JetStream API calls are
46+
// scoped to $JS.<domain>.API instead of the default $JS.API. Required when
47+
// the target cluster is reached across a leafnode boundary; harmless for
48+
// direct connections since the server serves its own domain prefix locally.
49+
// Empty preserves the default (domain-less) prefix.
50+
Domain string `json:"domain,omitempty"`
51+
4552
// Cache settings
4653
TTL Duration `json:"ttl"`
4754
RefreshInterval Duration `json:"refresh_interval"`

pkg/natsstore/config_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ func TestConfig_JSONMarshaling(t *testing.T) {
229229
ReconnectWait: Duration(1 * time.Second),
230230
MaxBucketsWatchers: 20,
231231
RootTenant: "test-bucket",
232+
Domain: "cloud",
232233
}
233234

234235
// Marshal to JSON
@@ -248,4 +249,5 @@ func TestConfig_JSONMarshaling(t *testing.T) {
248249
assert.Equal(t, config.MaxBucketsWatchers, unmarshaled.MaxBucketsWatchers)
249250
assert.Equal(t, config.Bucket, unmarshaled.Bucket)
250251
assert.Equal(t, config.RootTenant, unmarshaled.RootTenant)
252+
assert.Equal(t, config.Domain, unmarshaled.Domain)
251253
}

pkg/natsstore/nats_client.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,22 @@ func (nc *NATSClient) connect() error {
101101
return fmt.Errorf("failed to connect to NATS server: %w", err)
102102
}
103103

104-
nc.conn = conn
105-
nc.setConnected(true)
106-
107-
// Create JetStream context
108-
js, err := conn.JetStream()
104+
// Create JetStream context, scoped to the configured domain when set
105+
var jsOpts []nats.JSOpt
106+
if nc.config.Domain != "" {
107+
jsOpts = append(jsOpts, nats.Domain(nc.config.Domain))
108+
}
109+
js, err := conn.JetStream(jsOpts...)
109110
if err != nil {
111+
// Close the connection so a JetStream init failure doesn't leak it;
112+
// only mark the client connected once setup fully succeeds.
113+
conn.Close()
110114
return fmt.Errorf("failed to create JetStream context: %w", err)
111115
}
116+
117+
nc.conn = conn
112118
nc.js = js
119+
nc.setConnected(true)
113120

114121
nc.logger.Info("Connected to NATS at %s", nc.config.ServerURL)
115122
return nil

0 commit comments

Comments
 (0)