// ReadMultiple gets the values from redis in a single call by pipelining func (s *Store) ReadMultiple(i interface{}) error { v := reflect.ValueOf(i) if v.Kind() == reflect.Ptr { v = v.Elem() } if v.Kind() != reflect.Slice { return errors.New("store: value must be a a slice") } c := s.pool.Get() defer c.Close() var key string var err error prefix := s.typeName(v) + ":" // Using transactions to execute HGETALL in a pipeline. // Mark the start of a transaction block. // Subsequent commands will be queued for atomic execution. c.Send("MULTI") for y := 0; y < v.Len(); y++ { if key = v.Index(y).Addr().MethodByName("Key").Call(nil)[0].String(); len(key) == 0 { return store.ErrEmptyKey } // Send writes the command to the connection's output buffer. if err = c.Send("HGETALL", prefix+key); err != nil { return err } } // Flush flushes the connection's output buffer to the server if err = c.Flush(); err != nil { return err } // Execute all previously queued commands // in a transaction and restores the connection // state to normal reply, err := c.Do("EXEC") if err != nil { return err } replyValue := reflect.ValueOf(reply) var values []interface{} // Reply is a two dimentional array of interfaces. Iterate over the first // dimension and scan each slice into destination interface type for y := 0; y < replyValue.Len(); y++ { itemPtrV := reflect.New(v.Type().Elem()) if values, err = driver.Values(replyValue.Index(y).Interface(), nil); err != nil { return err } driver.ScanStruct(values, itemPtrV.Interface()) v.Index(y).Set(itemPtrV.Elem()) } return nil }
func TestWrite(t *testing.T) { s := &TestR{ ID: uuid.New(), Field: "value", FieldInt: 10, FieldFloat: 1.234, FieldBool: true, FieldUint: 1, } db := testStore(t) if err := db.Write(s); err != nil { t.Fatal("err", err) } if len(s.Key()) == 0 { t.Fatalf("key is emtpy %#v", s) } cfg, err := NewConfig(testRedisURL) if err != nil { t.Fatal(err) } pool := NewPool(cfg) c := pool.Get() defer c.Close() reply, err := driver.Values(c.Do("HGETALL", testNs+":TestR:"+s.Key())) if err != nil { t.Fatal("err", err) } got := &TestR{} if err := driver.ScanStruct(reply, got); err != nil { t.Fatal("err", err) } if !reflect.DeepEqual(s, got) { t.Fatal("expected:", s, " got:", got) } }
// Read reads the item from redis store and copies the values to item // It Returns store.ErrKeyNotFound when no values are found for the key provided // and store.ErrKeyMissing when key is not provided. Unmarshalling id done using // driver provided redis.ScanStruct func (s *Store) Read(i store.Item) error { c := s.pool.Get() defer c.Close() value := reflect.ValueOf(i).Elem() if len(i.Key()) == 0 { return store.ErrEmptyKey } ri := &Item{ key: i.Key(), prefix: value.Type().Name(), } reply, err := driver.Values(c.Do("HGETALL", ri.Key())) if err != nil { return err } if len(reply) == 0 { return store.ErrKeyNotFound } if err := driver.ScanStruct(reply, i); err != nil { return err } return nil }