// CheckAndSet put a value with a key into the Cache, // ONLY IF it has no newer values with, i.e. no update since, a given serial. // It takes key, value parameters as an interface{} type and performs marshal for them. // If succeed, it returns a serial number(an unix timestamp in millis) for the value. // If a value of newer serial already exists, CheckAndSet would fail with ErrSetFailed. func (c *Cache) CheckAndSet(key interface{}, val interface{}, oserial int64) (int64, error) { bkey, err := c.options.Marshal(key) if err != nil { return 0, err } client, disconnect, _, err := c.connector.Connect(bkey) if err != nil { return 0, err } defer func() { if disconnect != nil { disconnect() } }() bval, err := c.options.Marshal(val) if err != nil { return 0, err } nserial := getSerial() resp := util.LuaEval(client, luaForCheckAndSet, 1, bkey, bval, oserial, nserial, c.options.Expiration.Seconds()) if resp.Err != nil { return 0, resp.Err } if resp.IsType(redis.Nil) { return 0, ErrSetFailed } atomic.AddInt64(&c.loads, 1) return nserial, nil }
// Get returns a cached value using bound Connector. // It takes key, value parameters as an interface{} type and performs marshal/unmarshal for them. func (c *Cache) Get(key interface{}, val interface{}) (int64, error) { bkey, err := c.options.Marshal(key) if err != nil { return 0, err } client, disconnect, validSince, err := c.connector.Connect(bkey) if err != nil { return 0, err } defer func() { if disconnect != nil { disconnect() } }() resp := util.LuaEval(client, luaForGet, 1, bkey, validSince) if resp.Err != nil { return 0, resp.Err } if resp.IsType(redis.Nil) { atomic.AddInt64(&c.misses, 1) return 0, ErrNoKey } if resp.IsType(redis.Array) { if res, err := resp.Array(); err == nil && len(res) == 2 { if res[0].IsType(redis.BulkStr) && res[1].IsType(redis.Int) { bval, _ := res[0].Bytes() serial, _ := res[1].Int64() if err := c.options.Unmarshal(bval, val); err != nil { return 0, err } atomic.AddInt64(&c.hits, 1) return serial, nil } } } return 0, ErrRESPParse }