-
Notifications
You must be signed in to change notification settings - Fork 1
/
options.go
291 lines (239 loc) · 5.95 KB
/
options.go
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
package store
import (
"context"
"reflect"
"time"
)
// GetOptions represent all possible options for Get requests.
type GetOptions struct {
Prefix bool
Filter FilterFunc
Handler HandlerFunc
Context context.Context
Unmarshal *unmarshal
}
// PutOptions represent all possible options for Put requests.
type PutOptions struct {
Context context.Context
TTL time.Duration
ErrChan chan<- error
Insert bool
}
// DelOptions represent all possible options for Del requests.
type DelOptions struct {
Prefix bool
Context context.Context
}
// WatchOptions represent all possible options for watchers.
type WatchOptions struct {
Prefix bool
Context context.Context
NotifyCreated NotifyCallback
ErrorHandler ErrorFunc
}
// WithPrefix is an option to perform a request with prefix.
func WithPrefix() interface {
GetOption
DelOption
WatchOption
} {
return &prefixOption{}
}
// WithContext is an options to set a context for a request.
func WithContext(ctx context.Context) interface {
GetOption
PutOption
DelOption
WatchOption
} {
return &contextOption{Context: ctx}
}
// WithFilter is an option to use an FilterFunc on each
// key-value pair during a Get request.
func WithFilter(f FilterFunc) interface {
GetOption
} {
return &filterOption{Filter: f}
}
// WithHandler is an option to use an HandlerFunc on each
// key-value pair during a Get request.
func WithHandler(h HandlerFunc) interface {
GetOption
} {
return &handlerOption{Handler: h}
}
// WithNotifyCreated is an option to use a NotifyCallback
// as soon as the Watch is established and ready to receive events
func WithNotifyCreated(c NotifyCallback) interface {
WatchOption
} {
return ¬ifyCreatedOption{Callback: c}
}
// WithErrorHandler is an option to use an ErrorFunc on each
// error not returned
func WithErrorHandler(h ErrorFunc) interface {
WatchOption
} {
return &errorHandlerOption{ErrorHandler: h}
}
// WithTTL is an option to add a time to live.
func WithTTL(ttl time.Duration) interface {
PutOption
} {
return &ttlOption{TTL: ttl}
}
// WithKeepAlive is an option to start a keep-alive for a key.
// The keep-alive will only start if errChan != nil
func WithKeepAlive(errChan chan<- error) interface {
PutOption
} {
return &keepAliveOption{ErrChan: errChan}
}
// WithUnmarshal unmarshals the byte array in the store
// into v. It panics if v is not a pointer .
//
// In combination with WithPrefix, v should be a pointer to
// a slice.
func WithUnmarshal(v interface{}) interface {
GetOption
} {
return &unmarshalOption{Unmarshal: v}
}
// WithInsert is an option to put a non existing key. If the key already
// exists, nothing is done and false is returned. If key does not exist
// key and value are added and true is returned.
func WithInsert() interface {
PutOption
} {
return &insertOption{}
}
// GetOption is the option interface for Get requests.
type GetOption interface {
SetGetOption(*GetOptions)
}
// PutOption is the option interface for Put requests.
type PutOption interface {
SetPutOption(*PutOptions)
}
// DelOption is the option interface for Del requests.
type DelOption interface {
SetDelOption(*DelOptions)
}
// WatchOption is the option interface for watchers.
type WatchOption interface {
SetWatchOption(*WatchOptions)
}
// prefix
type prefixOption struct{}
func (p *prefixOption) SetGetOption(opts *GetOptions) {
opts.Prefix = true
}
func (p *prefixOption) SetDelOption(opts *DelOptions) {
opts.Prefix = true
}
func (p *prefixOption) SetWatchOption(opts *WatchOptions) {
opts.Prefix = true
}
// context
type contextOption struct {
Context context.Context
}
func (c *contextOption) SetWatchOption(opts *WatchOptions) {
opts.Context = c.Context
}
func (c *contextOption) SetGetOption(opts *GetOptions) {
opts.Context = c.Context
}
func (c *contextOption) SetPutOption(opts *PutOptions) {
opts.Context = c.Context
}
func (c *contextOption) SetDelOption(opts *DelOptions) {
opts.Context = c.Context
}
// filter
type filterOption struct {
Filter FilterFunc
}
func (h *filterOption) SetGetOption(opts *GetOptions) {
opts.Filter = h.Filter
}
// handler
type handlerOption struct {
Handler HandlerFunc
}
func (h *handlerOption) SetGetOption(opts *GetOptions) {
opts.Handler = h.Handler
}
// notifyCreated
type notifyCreatedOption struct {
Callback NotifyCallback
}
func (n *notifyCreatedOption) SetWatchOption(opts *WatchOptions) {
opts.NotifyCreated = n.Callback
}
// errorHandler
type errorHandlerOption struct {
ErrorHandler ErrorFunc
}
func (e *errorHandlerOption) SetWatchOption(opts *WatchOptions) {
opts.ErrorHandler = e.ErrorHandler
}
// ttl
type ttlOption struct {
TTL time.Duration
}
func (t *ttlOption) SetPutOption(opts *PutOptions) {
opts.TTL = t.TTL
}
// keepAlive
type keepAliveOption struct {
ErrChan chan<- error
}
func (k *keepAliveOption) SetPutOption(opts *PutOptions) {
opts.ErrChan = k.ErrChan
}
// insert
type insertOption struct{}
func (i *insertOption) SetPutOption(opts *PutOptions) {
opts.Insert = true
}
// unmarshal
type unmarshalOption struct {
Unmarshal interface{}
}
func (u *unmarshalOption) SetGetOption(opts *GetOptions) {
opts.Unmarshal = new(unmarshal)
opts.Unmarshal.Input = u.Unmarshal
ptr := reflect.ValueOf(u.Unmarshal)
opts.Unmarshal.Ptr = ptr
if ptr.Kind() != reflect.Ptr {
panic("unmarshal value has to be pointer")
}
opts.Unmarshal.Type = ptr.Elem().Kind()
if opts.Unmarshal.Type == reflect.Slice {
opts.Unmarshal.Slice = ptr.Elem()
opts.Unmarshal.NewSlice = reflect.MakeSlice(opts.Unmarshal.Slice.Type(), 0, 0)
}
}
type unmarshal struct {
Input interface{}
Ptr reflect.Value
Type reflect.Kind
Slice reflect.Value
NewSlice reflect.Value
}
func (u *unmarshal) IsSlice() bool {
if u == nil {
return false
}
return u.Type == reflect.Slice
}
func (u *unmarshal) Element() interface{} {
if u == nil || !u.IsSlice() {
return nil
}
return reflect.New(u.Slice.Type().Elem()).Interface()
}
func (u *unmarshal) Append(v reflect.Value) {
u.NewSlice = reflect.Append(u.NewSlice, v)
}