package main import ( "errors" "sync" "time" ) type ObjectID int64 var ErrObjectNotFound = errors.New("object not found") type ObjectStore interface { AwaitObjects(ids []ObjectID, c chan ObjectResult, timeout *time.Duration) MakeObject(data []byte) (ObjectID, error) } type ObjectResult struct { Object *Object Error error } type Object struct { ID ObjectID Data []byte } func GetObject(s ObjectStore, id ObjectID) ([]byte, error) { c := make(chan ObjectResult) defer close(c) ids := []ObjectID{id} go func() { s.AwaitObjects(ids, c, nil) }() obj := <-c if !ok { return nil, errors.New("Couldn't get object") } if obj.Error != nil { return nil, obj.Error } return obj.Object.Data, nil } type MemObjectStore struct { sync.RWMutex db map[ObjectID][]byte } func (mem *MemObjectStore) AwaitObjects(ids []ObjectID, c chan Object, timeout *time.Duration) { if timeout != nil { panic("timeout not yet implemented") } mem.RLock() defer mem.RUnlock() for _, id := range ids { v, ok := mem.db[id] if !ok { c <- ObjectResult{Error: ErrObjectNotFound} } else { c <- ObjectResult{&Object{ID: id, Data: v}} } } close(c) } func (mem *MemObjectStore) MakeObject(data []byte) (ObjectID, error) { mem.Lock() defer mem.Unlock() id := mem.makeID() mem.db[id] = data return id, nil } func NewMemObjectStore() *MemObjectStore { return &MemObjectStore{ db: make(map[ObjectID][]byte), } }