You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
4.1 KiB
188 lines
4.1 KiB
6 years ago
|
package memcache
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
)
|
||
|
|
||
|
// Memcache memcache client
|
||
|
type Memcache struct {
|
||
|
pool *Pool
|
||
|
}
|
||
|
|
||
|
// Reply is the result of Get
|
||
|
type Reply struct {
|
||
|
err error
|
||
|
item *Item
|
||
|
conn Conn
|
||
|
closed bool
|
||
|
}
|
||
|
|
||
|
// Replies is the result of GetMulti
|
||
|
type Replies struct {
|
||
|
err error
|
||
|
items map[string]*Item
|
||
|
usedItems map[string]struct{}
|
||
|
conn Conn
|
||
|
closed bool
|
||
|
}
|
||
|
|
||
|
// New get a memcache client
|
||
|
func New(c *Config) *Memcache {
|
||
|
return &Memcache{pool: NewPool(c)}
|
||
|
}
|
||
|
|
||
|
// Close close connection pool
|
||
|
func (mc *Memcache) Close() error {
|
||
|
return mc.pool.Close()
|
||
|
}
|
||
|
|
||
|
// Conn direct get a connection
|
||
|
func (mc *Memcache) Conn(c context.Context) Conn {
|
||
|
return mc.pool.Get(c)
|
||
|
}
|
||
|
|
||
|
// Set writes the given item, unconditionally.
|
||
|
func (mc *Memcache) Set(c context.Context, item *Item) (err error) {
|
||
|
conn := mc.pool.Get(c)
|
||
|
err = conn.Set(item)
|
||
|
conn.Close()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Add writes the given item, if no value already exists for its key.
|
||
|
// ErrNotStored is returned if that condition is not met.
|
||
|
func (mc *Memcache) Add(c context.Context, item *Item) (err error) {
|
||
|
conn := mc.pool.Get(c)
|
||
|
err = conn.Add(item)
|
||
|
conn.Close()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Replace writes the given item, but only if the server *does* already hold data for this key.
|
||
|
func (mc *Memcache) Replace(c context.Context, item *Item) (err error) {
|
||
|
conn := mc.pool.Get(c)
|
||
|
err = conn.Replace(item)
|
||
|
conn.Close()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// CompareAndSwap writes the given item that was previously returned by Get
|
||
|
func (mc *Memcache) CompareAndSwap(c context.Context, item *Item) (err error) {
|
||
|
conn := mc.pool.Get(c)
|
||
|
err = conn.CompareAndSwap(item)
|
||
|
conn.Close()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Get sends a command to the server for gets data.
|
||
|
func (mc *Memcache) Get(c context.Context, key string) *Reply {
|
||
|
conn := mc.pool.Get(c)
|
||
|
item, err := conn.Get(key)
|
||
|
if err != nil {
|
||
|
conn.Close()
|
||
|
}
|
||
|
return &Reply{err: err, item: item, conn: conn}
|
||
|
}
|
||
|
|
||
|
// Item get raw Item
|
||
|
func (r *Reply) Item() *Item {
|
||
|
return r.item
|
||
|
}
|
||
|
|
||
|
// Scan converts value, read from the memcache
|
||
|
func (r *Reply) Scan(v interface{}) (err error) {
|
||
|
if r.err != nil {
|
||
|
return r.err
|
||
|
}
|
||
|
err = r.conn.Scan(r.item, v)
|
||
|
if !r.closed {
|
||
|
r.conn.Close()
|
||
|
r.closed = true
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// GetMulti is a batch version of Get
|
||
|
func (mc *Memcache) GetMulti(c context.Context, keys []string) (*Replies, error) {
|
||
|
conn := mc.pool.Get(c)
|
||
|
items, err := conn.GetMulti(keys)
|
||
|
rs := &Replies{err: err, items: items, conn: conn, usedItems: make(map[string]struct{}, len(keys))}
|
||
|
if (err != nil) || (len(items) == 0) {
|
||
|
rs.Close()
|
||
|
}
|
||
|
return rs, err
|
||
|
}
|
||
|
|
||
|
// Close close rows.
|
||
|
func (rs *Replies) Close() (err error) {
|
||
|
if !rs.closed {
|
||
|
err = rs.conn.Close()
|
||
|
rs.closed = true
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Item get Item from rows
|
||
|
func (rs *Replies) Item(key string) *Item {
|
||
|
return rs.items[key]
|
||
|
}
|
||
|
|
||
|
// Scan converts value, read from key in rows
|
||
|
func (rs *Replies) Scan(key string, v interface{}) (err error) {
|
||
|
if rs.err != nil {
|
||
|
return rs.err
|
||
|
}
|
||
|
item, ok := rs.items[key]
|
||
|
if !ok {
|
||
|
rs.Close()
|
||
|
return ErrNotFound
|
||
|
}
|
||
|
rs.usedItems[key] = struct{}{}
|
||
|
err = rs.conn.Scan(item, v)
|
||
|
if (err != nil) || (len(rs.items) == len(rs.usedItems)) {
|
||
|
rs.Close()
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Keys keys of result
|
||
|
func (rs *Replies) Keys() (keys []string) {
|
||
|
keys = make([]string, 0, len(rs.items))
|
||
|
for key := range rs.items {
|
||
|
keys = append(keys, key)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Touch updates the expiry for the given key.
|
||
|
func (mc *Memcache) Touch(c context.Context, key string, timeout int32) (err error) {
|
||
|
conn := mc.pool.Get(c)
|
||
|
err = conn.Touch(key, timeout)
|
||
|
conn.Close()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Delete deletes the item with the provided key.
|
||
|
func (mc *Memcache) Delete(c context.Context, key string) (err error) {
|
||
|
conn := mc.pool.Get(c)
|
||
|
err = conn.Delete(key)
|
||
|
conn.Close()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Increment atomically increments key by delta.
|
||
|
func (mc *Memcache) Increment(c context.Context, key string, delta uint64) (newValue uint64, err error) {
|
||
|
conn := mc.pool.Get(c)
|
||
|
newValue, err = conn.Increment(key, delta)
|
||
|
conn.Close()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Decrement atomically decrements key by delta.
|
||
|
func (mc *Memcache) Decrement(c context.Context, key string, delta uint64) (newValue uint64, err error) {
|
||
|
conn := mc.pool.Get(c)
|
||
|
newValue, err = conn.Decrement(key, delta)
|
||
|
conn.Close()
|
||
|
return
|
||
|
}
|