forked from rbaliyan/config
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoptions.go
More file actions
175 lines (155 loc) · 4.19 KB
/
options.go
File metadata and controls
175 lines (155 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package config
import (
"log/slog"
"time"
"github.com/rbaliyan/config/codec"
)
// watchBackoffConfig configures the exponential backoff for watch reconnection.
type watchBackoffConfig struct {
initialBackoff time.Duration
maxBackoff time.Duration
backoffFactor float64
}
// managerOptions holds configuration for the Manager (unexported).
type managerOptions struct {
store Store
codec codec.Codec
logger *slog.Logger
watchBackoff watchBackoffConfig
maxKeysPerNS int // 0 = unlimited
}
// Option configures the Manager.
type Option func(*managerOptions)
// newManagerOptions creates options with defaults.
func newManagerOptions() *managerOptions {
return &managerOptions{
codec: codec.Default(),
logger: slog.Default(),
watchBackoff: watchBackoffConfig{
initialBackoff: 100 * time.Millisecond,
maxBackoff: 30 * time.Second,
backoffFactor: 2.0,
},
}
}
// WithStore sets the configuration store backend.
// This is required - the manager will fail to connect without a store.
func WithStore(store Store) Option {
return func(o *managerOptions) {
if store != nil {
o.store = store
}
}
}
// WithCodec sets the default codec for encoding/decoding values.
// Default is JSON if not specified.
func WithCodec(c codec.Codec) Option {
return func(o *managerOptions) {
if c != nil {
o.codec = c
}
}
}
// WithLogger sets a custom logger.
func WithLogger(logger *slog.Logger) Option {
return func(o *managerOptions) {
if logger != nil {
o.logger = logger
}
}
}
// WithMaxKeysPerNamespace sets the maximum number of keys allowed per namespace.
// Set operations that would exceed this limit return ErrNamespaceFull.
// Only enforced on creates (not updates to existing keys). 0 means unlimited (default).
func WithMaxKeysPerNamespace(n int) Option {
return func(o *managerOptions) {
if n >= 0 {
o.maxKeysPerNS = n
}
}
}
// WithWatchInitialBackoff sets the initial wait time between watch reconnection attempts.
// Default: 100ms.
func WithWatchInitialBackoff(d time.Duration) Option {
return func(o *managerOptions) {
if d > 0 {
o.watchBackoff.initialBackoff = d
}
}
}
// WithWatchMaxBackoff sets the maximum wait time between watch reconnection attempts.
// Default: 30s.
func WithWatchMaxBackoff(d time.Duration) Option {
return func(o *managerOptions) {
if d > 0 {
o.watchBackoff.maxBackoff = d
}
}
}
// WithWatchBackoffFactor sets the multiplier applied to backoff after each watch failure.
// Default: 2.0.
func WithWatchBackoffFactor(f float64) Option {
return func(o *managerOptions) {
if f > 0 {
o.watchBackoff.backoffFactor = f
}
}
}
// SetOption configures Set operations.
type SetOption func(*setOptions)
type setOptions struct {
codec codec.Codec
typ Type
writeMode WriteMode
}
func newSetOptions() *setOptions {
return &setOptions{}
}
// WithSetCodec sets the codec for encoding the value.
func WithSetCodec(c codec.Codec) SetOption {
return func(o *setOptions) {
if c != nil {
o.codec = c
}
}
}
// WithType explicitly sets the value type.
func WithType(t Type) SetOption {
return func(o *setOptions) {
o.typ = t
}
}
// WithIfNotExists configures Set to only create the key if it doesn't exist.
// Returns ErrKeyExists if the key already exists.
//
// This is useful for implementing "create-only" semantics where you want to
// ensure you don't accidentally overwrite an existing value.
//
// Example:
//
// err := cfg.Set(ctx, "lock/owner", "instance-1", config.WithIfNotExists())
// if config.IsKeyExists(err) {
// // Key was already taken by another instance
// }
func WithIfNotExists() SetOption {
return func(o *setOptions) {
o.writeMode = WriteModeCreate
}
}
// WithIfExists configures Set to only update the key if it already exists.
// Returns ErrNotFound if the key doesn't exist.
//
// This is useful for implementing "update-only" semantics where you want to
// ensure the key was previously created.
//
// Example:
//
// err := cfg.Set(ctx, "app/timeout", 60, config.WithIfExists())
// if config.IsNotFound(err) {
// // Key doesn't exist, need to create it first
// }
func WithIfExists() SetOption {
return func(o *setOptions) {
o.writeMode = WriteModeUpdate
}
}