|
| 1 | +package tbkv |
| 2 | + |
| 3 | +type KVStore struct { |
| 4 | + data map[string]string |
| 5 | + save chan ItemRequest |
| 6 | + fetch chan Request |
| 7 | + delete chan Request |
| 8 | +} |
| 9 | + |
| 10 | +func (s *KVStore) Get(key string) (string, error) { |
| 11 | + request := Request{ |
| 12 | + Key: key, |
| 13 | + Result: make(chan Result, 1), |
| 14 | + } |
| 15 | + s.fetch <- request |
| 16 | + result := <-request.Result |
| 17 | + if !result.Ok { |
| 18 | + return "", ErrNotFound |
| 19 | + } |
| 20 | + return result.Value, nil |
| 21 | +} |
| 22 | + |
| 23 | +func (s *KVStore) Set(key, value string) { |
| 24 | + setItemRequest := ItemRequest{ |
| 25 | + Item: Item{ |
| 26 | + Key: key, |
| 27 | + Value: value, |
| 28 | + }, |
| 29 | + Ok: make(chan bool, 1), |
| 30 | + } |
| 31 | + s.save <- setItemRequest |
| 32 | + <-setItemRequest.Ok |
| 33 | +} |
| 34 | + |
| 35 | +func (s *KVStore) Delete(key string) { |
| 36 | + request := Request{ |
| 37 | + Key: key, |
| 38 | + Result: make(chan Result, 1), |
| 39 | + } |
| 40 | + s.delete <- request |
| 41 | + <-request.Result |
| 42 | +} |
| 43 | + |
| 44 | +// NewStore creates a new KVStore. |
| 45 | +// requestBufferSize is the size of the request buffer. |
| 46 | +// If requestBufferSize is 0, it will use a default of 20. |
| 47 | +func NewStore(requestBufferSize uint8) KVStore { |
| 48 | + var buffer uint8 |
| 49 | + if requestBufferSize == 0 { |
| 50 | + buffer = 20 |
| 51 | + } else { |
| 52 | + buffer = requestBufferSize |
| 53 | + } |
| 54 | + kvs := KVStore{} |
| 55 | + kvs.data = make(map[string]string) |
| 56 | + kvs.save = make(chan ItemRequest, buffer) |
| 57 | + kvs.fetch = make(chan Request, buffer) |
| 58 | + kvs.delete = make(chan Request, buffer) |
| 59 | + go kvs.loop() // starts listening for requests |
| 60 | + return kvs |
| 61 | +} |
| 62 | + |
| 63 | +// NewDefaultStore is a convenience function for creating a KVStore with sensible defaults. |
| 64 | +// It will create a KVStore with a request buffer size of 20. |
| 65 | +func NewDefaultStore() KVStore { |
| 66 | + return NewStore(0) |
| 67 | +} |
| 68 | + |
| 69 | +func (s *KVStore) loop() error { |
| 70 | + for { |
| 71 | + select { |
| 72 | + case setRequest := <-s.save: |
| 73 | + s.data[setRequest.Item.Key] = setRequest.Item.Value |
| 74 | + setRequest.Ok <- true // cannot fail |
| 75 | + case getRequest := <-s.fetch: |
| 76 | + val, ok := s.data[getRequest.Key] |
| 77 | + getRequest.Result <- Result{ |
| 78 | + Value: val, |
| 79 | + Ok: ok, |
| 80 | + } |
| 81 | + case delRequest := <-s.delete: |
| 82 | + delete(s.data, delRequest.Key) |
| 83 | + delRequest.Result <- Result{ |
| 84 | + Value: delRequest.Key, |
| 85 | + Ok: true, // cannot fail |
| 86 | + } |
| 87 | + } |
| 88 | + } |
| 89 | +} |
0 commit comments