github.com/gocaveman/caveman@v0.0.0-20191211162744-0ddf99dbdf6e/menus/map-menu-store.go (about) 1 package menus 2 3 import ( 4 "sort" 5 "sync" 6 ) 7 8 func NewMapMenuStore() *MapMenuStore { 9 return &MapMenuStore{ 10 menuItems: make(map[string]*MenuItem), 11 } 12 } 13 14 // MapMenuStore implements Store using an in-memory map. 15 // It is safe for confurrent use. 16 type MapMenuStore struct { 17 menuItems map[string]*MenuItem 18 mu sync.RWMutex 19 } 20 21 func (s *MapMenuStore) ReadMenuItem(id string) (*MenuItem, error) { 22 s.mu.RLock() 23 defer s.mu.RUnlock() 24 mi, ok := s.menuItems[id] 25 if !ok { 26 return nil, ErrNotFound 27 } 28 miCopy := *mi 29 return &miCopy, nil 30 } 31 32 func (s *MapMenuStore) CreateMenuItem(mi *MenuItem) error { 33 s.mu.Lock() 34 defer s.mu.Unlock() 35 _, ok := s.menuItems[mi.MenuID] 36 if ok { 37 return ErrAlreadyExists 38 } 39 miCopy := *mi 40 s.menuItems[miCopy.MenuID] = &miCopy 41 return nil 42 } 43 44 func (s *MapMenuStore) UpdateMenuItem(mi *MenuItem) error { 45 s.mu.Lock() 46 defer s.mu.Unlock() 47 _, ok := s.menuItems[mi.MenuID] 48 if !ok { 49 return ErrNotFound 50 } 51 miCopy := *mi 52 s.menuItems[miCopy.MenuID] = &miCopy 53 return nil 54 } 55 56 func (s *MapMenuStore) DeleteMenuItem(id string) error { 57 s.mu.Lock() 58 defer s.mu.Unlock() 59 delete(s.menuItems, id) 60 return nil 61 } 62 63 func (s *MapMenuStore) FindChildren(id string) ([]string, error) { 64 // FIXME: We really should index this properly, menus are 65 // read-intensive and this call will be very frequent. 66 // Even if we had to rebuild the entire index on each change, it 67 // would probabyl still be worth it. 68 s.mu.RLock() 69 defer s.mu.RUnlock() 70 var retMenuItems MenuItemList 71 for _, mi := range s.menuItems { 72 if mi.ParentMenuID == id { 73 retMenuItems = append(retMenuItems, *mi) 74 } 75 } 76 sort.Sort(retMenuItems) 77 ret := make([]string, 0, len(retMenuItems)) 78 for _, mi := range retMenuItems { 79 ret = append(ret, mi.MenuID) 80 } 81 return ret, nil 82 }