gifs/api
2014-10-17
Parent:96aac3ae74e6
gifs/api/memstore.go
Upload is no longer async, memstorage is parallel-safe. Upload no longer needs to be run async (it can be run inside a goroutine), so it now returns stuff instead of taking a channel as an argument. This will make it easier to implement, as all the async stuff is an abstraction above, and therefore doesn't need to be worried about for each reimplementation. The memstorage type is no longer exported and can now be safely used by multiple goroutines, thanks to the sync package.
| paddy@0 | 1 package api |
| paddy@0 | 2 |
| paddy@0 | 3 import ( |
| paddy@0 | 4 "time" |
| paddy@0 | 5 |
| paddy@3 | 6 "code.secondbit.org/uuid.hg" |
| paddy@0 | 7 ) |
| paddy@0 | 8 |
| paddy@0 | 9 type Memstore struct { |
| paddy@0 | 10 collections map[string]Collection |
| paddy@0 | 11 domains map[string]Domain |
| paddy@0 | 12 items map[string]Item |
| paddy@0 | 13 } |
| paddy@0 | 14 |
| paddy@0 | 15 func NewMemstore() Memstore { |
| paddy@0 | 16 return Memstore{ |
| paddy@0 | 17 collections: map[string]Collection{}, |
| paddy@0 | 18 domains: map[string]Domain{}, |
| paddy@0 | 19 items: map[string]Item{}, |
| paddy@0 | 20 } |
| paddy@0 | 21 } |
| paddy@0 | 22 |
| paddy@0 | 23 func (m Memstore) CreateCollection(c Collection) error { |
| paddy@0 | 24 m.collections[c.ID.String()] = c |
| paddy@0 | 25 return nil |
| paddy@0 | 26 } |
| paddy@0 | 27 |
| paddy@3 | 28 func (m Memstore) UpdateCollection(id uuid.ID, change CollectionChange) error { |
| paddy@3 | 29 c, ok := m.collections[id.String()] |
| paddy@3 | 30 if !ok { |
| paddy@3 | 31 return ErrCollectionNotFound |
| paddy@0 | 32 } |
| paddy@3 | 33 c.ApplyChange(change) |
| paddy@3 | 34 m.collections[id.String()] = c |
| paddy@0 | 35 return nil |
| paddy@0 | 36 } |
| paddy@0 | 37 |
| paddy@0 | 38 func (m Memstore) GetCollectionByDomain(domain string) (Collection, error) { |
| paddy@0 | 39 d, ok := m.domains[domain] |
| paddy@0 | 40 if !ok { |
| paddy@3 | 41 return Collection{}, ErrCollectionNotFound |
| paddy@0 | 42 } |
| paddy@0 | 43 return m.GetCollectionByID(d.CollectionID) |
| paddy@0 | 44 } |
| paddy@0 | 45 |
| paddy@0 | 46 func (m Memstore) GetCollectionByID(id uuid.ID) (Collection, error) { |
| paddy@0 | 47 if c, ok := m.collections[id.String()]; ok { |
| paddy@0 | 48 return c, nil |
| paddy@0 | 49 } |
| paddy@3 | 50 return Collection{}, ErrCollectionNotFound |
| paddy@0 | 51 } |
| paddy@0 | 52 |
| paddy@0 | 53 func (m Memstore) GetCollectionsByUser(id uuid.ID) ([]Collection, error) { |
| paddy@0 | 54 collections := []Collection{} |
| paddy@0 | 55 for _, c := range m.collections { |
| paddy@0 | 56 if c.Owner.Equal(id) { |
| paddy@0 | 57 collections = append(collections, c) |
| paddy@0 | 58 } |
| paddy@0 | 59 } |
| paddy@0 | 60 return collections, nil |
| paddy@0 | 61 } |
| paddy@0 | 62 |
| paddy@0 | 63 func (m Memstore) AddDomainToCollection(id uuid.ID, domain string) error { |
| paddy@0 | 64 if _, ok := m.domains[domain]; ok { |
| paddy@3 | 65 return ErrDomainAlreadyExists |
| paddy@0 | 66 } |
| paddy@0 | 67 m.domains[domain] = Domain{ |
| paddy@0 | 68 Domain: domain, |
| paddy@0 | 69 CollectionID: id, |
| paddy@0 | 70 Created: time.Now(), |
| paddy@0 | 71 } |
| paddy@0 | 72 return nil |
| paddy@0 | 73 } |
| paddy@0 | 74 |
| paddy@0 | 75 func (m Memstore) RemoveDomainFromCollection(id uuid.ID, domain string) error { |
| paddy@0 | 76 if _, ok := m.domains[domain]; !ok { |
| paddy@3 | 77 return ErrDomainNotFound |
| paddy@0 | 78 } |
| paddy@0 | 79 delete(m.domains, domain) |
| paddy@0 | 80 return nil |
| paddy@0 | 81 } |
| paddy@0 | 82 |
| paddy@0 | 83 func (m Memstore) GetDomainsByCollection(id uuid.ID) ([]Domain, error) { |
| paddy@0 | 84 domains := []Domain{} |
| paddy@0 | 85 for _, d := range m.domains { |
| paddy@0 | 86 if d.CollectionID.Equal(id) { |
| paddy@0 | 87 domains = append(domains, d) |
| paddy@0 | 88 } |
| paddy@0 | 89 } |
| paddy@0 | 90 return domains, nil |
| paddy@0 | 91 } |
| paddy@0 | 92 |
| paddy@0 | 93 func (m Memstore) DeleteCollection(c Collection) error { |
| paddy@0 | 94 if _, ok := m.collections[c.ID.String()]; !ok { |
| paddy@3 | 95 return ErrCollectionNotFound |
| paddy@0 | 96 } |
| paddy@0 | 97 delete(m.collections, c.ID.String()) |
| paddy@0 | 98 return nil |
| paddy@0 | 99 } |
| paddy@0 | 100 |
| paddy@0 | 101 func (m Memstore) GetItemsByCollectionDomain(domain string, num, offset int) ([]Item, error) { |
| paddy@0 | 102 collection, err := m.GetCollectionByDomain(domain) |
| paddy@0 | 103 if err != nil { |
| paddy@0 | 104 return []Item{}, err |
| paddy@0 | 105 } |
| paddy@0 | 106 return m.GetItemsByCollectionID(collection.ID, num, offset) |
| paddy@0 | 107 } |
| paddy@0 | 108 |
| paddy@0 | 109 func (m Memstore) GetItemsByCollectionID(id uuid.ID, num, offset int) ([]Item, error) { |
| paddy@0 | 110 if _, ok := m.collections[id.String()]; !ok { |
| paddy@3 | 111 return []Item{}, ErrCollectionNotFound |
| paddy@0 | 112 } |
| paddy@0 | 113 items := []Item{} |
| paddy@0 | 114 for _, item := range m.items { |
| paddy@0 | 115 if item.CollectionID.Equal(id) { |
| paddy@0 | 116 items = append(items, item) |
| paddy@0 | 117 } |
| paddy@0 | 118 } |
| paddy@0 | 119 if len(items) < offset { |
| paddy@0 | 120 return []Item{}, nil |
| paddy@0 | 121 } |
| paddy@0 | 122 end := offset + num |
| paddy@0 | 123 if len(items) < end { |
| paddy@0 | 124 end = len(items) |
| paddy@0 | 125 } |
| paddy@0 | 126 return items[offset:end], nil |
| paddy@0 | 127 } |
| paddy@0 | 128 |
| paddy@0 | 129 func (m Memstore) AddItemToCollection(id uuid.ID, item Item) error { |
| paddy@0 | 130 if _, ok := m.collections[id.String()]; !ok { |
| paddy@3 | 131 return ErrCollectionNotFound |
| paddy@0 | 132 } |
| paddy@0 | 133 if _, ok := m.items[id.String()+"/"+item.Name]; ok { |
| paddy@3 | 134 return ErrItemAlreadyExists |
| paddy@0 | 135 } |
| paddy@0 | 136 item.CollectionID = id |
| paddy@0 | 137 m.items[id.String()+"/"+item.Name] = item |
| paddy@0 | 138 return nil |
| paddy@0 | 139 } |
| paddy@0 | 140 |
| paddy@0 | 141 func (m Memstore) GetItemByName(collectionID uuid.ID, name string) (Item, error) { |
| paddy@0 | 142 if _, ok := m.collections[collectionID.String()]; !ok { |
| paddy@3 | 143 return Item{}, ErrCollectionNotFound |
| paddy@0 | 144 } |
| paddy@0 | 145 if item, ok := m.items[collectionID.String()+"/"+name]; ok { |
| paddy@0 | 146 return item, nil |
| paddy@0 | 147 } |
| paddy@3 | 148 return Item{}, ErrItemNotFound |
| paddy@0 | 149 } |
| paddy@0 | 150 |
| paddy@0 | 151 func (m Memstore) DeleteItem(item Item) error { |
| paddy@0 | 152 if _, ok := m.items[item.CollectionID.String()+"/"+item.Name]; !ok { |
| paddy@3 | 153 return ErrItemNotFound |
| paddy@0 | 154 } |
| paddy@0 | 155 delete(m.items, item.CollectionID.String()+"/"+item.Name) |
| paddy@0 | 156 return nil |
| paddy@0 | 157 } |