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  }