feature

Paddy 2015-03-16

0:caad72abc05a Go to Latest

feature/server/store.go

First pass at an implementation. Implement the calculation to determine whether a string is included in the partition or not, using crc32 to coerce the string to an evenly distributed uint32, and a modulo to turn it into a percentage. Implement a store to keep track of available flags and the level of the partition for each flag. Implement an API to retrieve, create, and modify these available flags.

History
1 package server
3 import (
4 "fmt"
5 "sync"
7 "code.secondbit.org/feature.hg"
8 )
10 const (
11 errNotFound = "flag not found"
12 errAlreadyExists = "flag already exists"
13 )
15 type flagError struct {
16 pos int
17 code string
18 }
20 func (f *flagError) Error() string {
21 return fmt.Sprintf("[%d]: %s", f.pos, f.code)
22 }
24 type flagStore interface {
25 create(f feature.Flag) *flagError
26 update(flags []feature.Flag) []flagError
27 destroy(flag string) *flagError
28 list() ([]feature.Flag, *flagError)
29 }
31 type memstore struct {
32 flags map[string]feature.Flag
33 flock sync.RWMutex
34 }
36 func (m *memstore) create(f feature.Flag) *flagError {
37 m.flock.Lock()
38 defer m.flock.Unlock()
40 if _, ok := m.flags[f.ID]; ok {
41 return &flagError{pos: 0, code: errNotFound}
42 }
43 m.flags[f.ID] = f
44 return nil
45 }
47 func (m *memstore) update(flags []feature.Flag) []flagError {
48 m.flock.Lock()
49 defer m.flock.Unlock()
51 errs := []flagError{}
52 for pos, f := range flags {
53 if _, ok := m.flags[f.ID]; !ok {
54 errs = append(errs, flagError{pos: pos, code: errNotFound})
55 }
56 }
57 if len(errs) > 0 {
58 return errs
59 }
60 for _, flag := range flags {
61 m.flags[flag.ID] = flag
62 }
63 return nil
64 }
66 func (m *memstore) destroy(flag string) *flagError {
67 m.flock.Lock()
68 defer m.flock.Unlock()
70 if _, ok := m.flags[flag]; !ok {
71 return &flagError{pos: 0, code: errNotFound}
72 }
73 delete(m.flags, flag)
74 return nil
75 }
77 func (m *memstore) list() ([]feature.Flag, *flagError) {
78 m.flock.RLock()
79 defer m.flock.RUnlock()
81 flags := make([]feature.Flag, len(m.flags))
82 pos := 0
83 for _, flag := range m.flags {
84 flags[pos] = flag
85 pos = pos + 1
86 }
87 return flags, nil
88 }