snapshot of https://github.com/nats-io/nats-server.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
NATS Server Tests / Lint (push) Failing after 3s
NATS Server Tests / Build (Latest Go) (push) Has been skipped
NATS Server Tests / Build (Minimum Go) (push) Has been skipped
NATS Server Tests / Build (Minimum Go, windows-2022) (push) Has been skipped
NATS Server Tests / Build (Minimum Go, windows-2025) (push) Has been skipped
NATS Server Tests / Test Stores (push) Has been skipped
NATS Server Tests / Test JetStream (push) Has been skipped
NATS Server Tests / Test Raft (push) Has been skipped
NATS Server Tests / Test JetStream Consumers (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 1 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 2 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 3 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 4 (push) Has been skipped
NATS Server Tests / Test JetStream Supercluster (push) Has been skipped
NATS Server Tests / Test No-Race 1 (push) Has been skipped
NATS Server Tests / Test No-Race 2 (push) Has been skipped
NATS Server Tests / Test MQTT (push) Has been skipped
NATS Server Tests / Test Message Tracing (push) Has been skipped
NATS Server Tests / Test JWT (push) Has been skipped
NATS Server Tests / Test Remaining Server Tests (push) Has been skipped
NATS Server Tests / Test Other Packages (push) Has been skipped
Vulnerability Scan / govulncheck (push) Failing after 12m2s
Some checks failed
NATS Server Tests / Lint (push) Failing after 3s
NATS Server Tests / Build (Latest Go) (push) Has been skipped
NATS Server Tests / Build (Minimum Go) (push) Has been skipped
NATS Server Tests / Build (Minimum Go, windows-2022) (push) Has been skipped
NATS Server Tests / Build (Minimum Go, windows-2025) (push) Has been skipped
NATS Server Tests / Test Stores (push) Has been skipped
NATS Server Tests / Test JetStream (push) Has been skipped
NATS Server Tests / Test Raft (push) Has been skipped
NATS Server Tests / Test JetStream Consumers (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 1 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 2 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 3 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 4 (push) Has been skipped
NATS Server Tests / Test JetStream Supercluster (push) Has been skipped
NATS Server Tests / Test No-Race 1 (push) Has been skipped
NATS Server Tests / Test No-Race 2 (push) Has been skipped
NATS Server Tests / Test MQTT (push) Has been skipped
NATS Server Tests / Test Message Tracing (push) Has been skipped
NATS Server Tests / Test JWT (push) Has been skipped
NATS Server Tests / Test Remaining Server Tests (push) Has been skipped
NATS Server Tests / Test Other Packages (push) Has been skipped
Vulnerability Scan / govulncheck (push) Failing after 12m2s
This commit is contained in:
157
server/feature_flags.go
Normal file
157
server/feature_flags.go
Normal file
@@ -0,0 +1,157 @@
|
||||
// Copyright 2026 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
FeatureFlagJsAckFormatV2 = "js_ack_fc_v2"
|
||||
FeatureFlagJsAPIReplyFormatV2 = "js_api_reply_v2"
|
||||
FeatureFlagJsRaftDeleteRange = "js_raft_delete_range"
|
||||
FeatureFlagJsSnapshotSources = "js_snapshot_sources"
|
||||
)
|
||||
|
||||
var featureFlags = map[string]bool{
|
||||
// Use v2 format for `$JS.ACK.>` and `$JS.FC.>`.
|
||||
// - Introduced: 2.14.0, both v1 and v2 supported, only using v1.
|
||||
// - Enabled: TBD, both supported, v2 becomes the default.
|
||||
//
|
||||
// - v1: $JS.ACK.<stream name>.<consumer name>.<num delivered>.<stream sequence>.<consumer sequence>.<timestamp>.<num pending>
|
||||
// - v2: $JS.ACK.<domain>.<account hash>.<stream name>.<consumer name>.<num delivered>.<stream sequence>.<consumer sequence>.<timestamp>.<num pending>
|
||||
// See also: https://github.com/nats-io/nats-architecture-and-design/blob/main/adr/ADR-15.md#jsack
|
||||
FeatureFlagJsAckFormatV2: false,
|
||||
|
||||
// Use a scoped v2 format for replies to internally-issued JetStream API
|
||||
// requests. This permits a leafnode to authorize only the replies for a
|
||||
// specific remote stream/consumer instead of every $JSC.R reply in an
|
||||
// account.
|
||||
//
|
||||
// - v1: $JSC.R.<uid>
|
||||
// - v2: $JSC.R.<domain>.<account hash>.<stream name>.<consumer name>.<uid>
|
||||
//
|
||||
// The reply subject is opaque to the remote API server, so this is safe to
|
||||
// enable independently on the server issuing the request.
|
||||
FeatureFlagJsAPIReplyFormatV2: false,
|
||||
|
||||
// Propose delete range gaps as a single `deleteRangeOp` Raft append entry
|
||||
// instead of one entry per deleted sequence. Dramatically reduces Raft cost
|
||||
// on mirrors whose origin has a large number of interior deletes.
|
||||
// - Introduced: 2.14.0, apply-side always supports receiving `deleteRangeOp`.
|
||||
// - Enabled: 2.15.0, when upgrading all servers should be 2.14.0+
|
||||
// - To be removed in 2.16.0
|
||||
//
|
||||
// WARNING: Only enable once every peer in the cluster is on a version that
|
||||
// supports receiving `deleteRangeOp`. Older peers panic on apply of an
|
||||
// unknown stream entry operation.
|
||||
FeatureFlagJsRaftDeleteRange: true,
|
||||
|
||||
// Include the stream's sourcing state in the replicated stream snapshot.
|
||||
// Unlike other per-message derived state, it outlives the messages it was
|
||||
// collected from, so a replica that caught up after those messages were
|
||||
// removed can't derive it locally and would resume sourcing from an earlier
|
||||
// position once it becomes leader.
|
||||
// - Introduced: 2.15.0, both encoding versions are accepted, only emitting v1.
|
||||
// - Enabled: TBD, once all supported versions accept v2.
|
||||
//
|
||||
// WARNING: Only enable once every peer in the cluster is on a version that
|
||||
// accepts the v2 encoding. Older peers reject the snapshot outright.
|
||||
FeatureFlagJsSnapshotSources: false,
|
||||
}
|
||||
|
||||
// getFeatureFlag is used to retrieve either the default or overwritten value for a feature flag.
|
||||
// The user's value takes precedence over the system's default. However, if the flag doesn't exist, it's disabled.
|
||||
// The *Options returned by Server.getOpts() is treated as immutable, mutations go through setOpts,
|
||||
// so no lock is required on the map read here.
|
||||
func (o *Options) getFeatureFlag(k string) bool {
|
||||
defaultValue, ok := featureFlags[k]
|
||||
if !ok {
|
||||
return false // Not supported.
|
||||
}
|
||||
if userValue, ok := o.FeatureFlags[k]; ok {
|
||||
return userValue
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// getMergedFeatureFlags returns a merged map of feature flags, with the user's values taking precedence.
|
||||
func (o *Options) getMergedFeatureFlags() map[string]bool {
|
||||
merged := make(map[string]bool)
|
||||
for k, v := range featureFlags {
|
||||
merged[k] = v
|
||||
}
|
||||
for k, v := range o.FeatureFlags {
|
||||
if _, ok := featureFlags[k]; !ok {
|
||||
continue
|
||||
}
|
||||
merged[k] = v
|
||||
}
|
||||
return merged
|
||||
}
|
||||
|
||||
// printFeatureFlags logs the currently used feature flags on server startup.
|
||||
func (s *Server) printFeatureFlags(o *Options) {
|
||||
if len(o.FeatureFlags) == 0 {
|
||||
return
|
||||
}
|
||||
keys := slices.Sorted(maps.Keys(o.FeatureFlags))
|
||||
|
||||
var (
|
||||
configured strings.Builder
|
||||
unsupported strings.Builder
|
||||
)
|
||||
|
||||
for _, k := range keys {
|
||||
// Unsupported
|
||||
defaultValue, ok := featureFlags[k]
|
||||
if !ok {
|
||||
if unsupported.Len() > 0 {
|
||||
unsupported.WriteString(", ")
|
||||
}
|
||||
unsupported.WriteString(k)
|
||||
continue
|
||||
}
|
||||
|
||||
v := o.FeatureFlags[k]
|
||||
if configured.Len() > 0 {
|
||||
configured.WriteString(", ")
|
||||
}
|
||||
configured.WriteString(k)
|
||||
configured.WriteString(" (")
|
||||
if defaultValue {
|
||||
if v {
|
||||
configured.WriteString("enabled")
|
||||
} else {
|
||||
configured.WriteString("opt-out")
|
||||
}
|
||||
} else if v {
|
||||
configured.WriteString("opt-in")
|
||||
} else {
|
||||
configured.WriteString("disabled")
|
||||
}
|
||||
configured.WriteString(")")
|
||||
}
|
||||
if configured.Len() == 0 {
|
||||
configured.WriteString("none")
|
||||
}
|
||||
|
||||
s.Noticef(" Feature flags:")
|
||||
s.Noticef(" Configured: %s", configured.String())
|
||||
if unsupported.Len() > 0 {
|
||||
s.Noticef(" Unsupported: %s", unsupported.String())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user