client.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package memcache
  2. import (
  3. "context"
  4. )
  5. // Memcache memcache client
  6. type Memcache struct {
  7. pool *Pool
  8. }
  9. // Reply is the result of Get
  10. type Reply struct {
  11. err error
  12. item *Item
  13. conn Conn
  14. closed bool
  15. }
  16. // Replies is the result of GetMulti
  17. type Replies struct {
  18. err error
  19. items map[string]*Item
  20. usedItems map[string]struct{}
  21. conn Conn
  22. closed bool
  23. }
  24. // New get a memcache client
  25. func New(c *Config) *Memcache {
  26. return &Memcache{pool: NewPool(c)}
  27. }
  28. // Close close connection pool
  29. func (mc *Memcache) Close() error {
  30. return mc.pool.Close()
  31. }
  32. // Conn direct get a connection
  33. func (mc *Memcache) Conn(c context.Context) Conn {
  34. return mc.pool.Get(c)
  35. }
  36. // Set writes the given item, unconditionally.
  37. func (mc *Memcache) Set(c context.Context, item *Item) (err error) {
  38. conn := mc.pool.Get(c)
  39. err = conn.Set(item)
  40. conn.Close()
  41. return
  42. }
  43. // Add writes the given item, if no value already exists for its key.
  44. // ErrNotStored is returned if that condition is not met.
  45. func (mc *Memcache) Add(c context.Context, item *Item) (err error) {
  46. conn := mc.pool.Get(c)
  47. err = conn.Add(item)
  48. conn.Close()
  49. return
  50. }
  51. // Replace writes the given item, but only if the server *does* already hold data for this key.
  52. func (mc *Memcache) Replace(c context.Context, item *Item) (err error) {
  53. conn := mc.pool.Get(c)
  54. err = conn.Replace(item)
  55. conn.Close()
  56. return
  57. }
  58. // CompareAndSwap writes the given item that was previously returned by Get
  59. func (mc *Memcache) CompareAndSwap(c context.Context, item *Item) (err error) {
  60. conn := mc.pool.Get(c)
  61. err = conn.CompareAndSwap(item)
  62. conn.Close()
  63. return
  64. }
  65. // Get sends a command to the server for gets data.
  66. func (mc *Memcache) Get(c context.Context, key string) *Reply {
  67. conn := mc.pool.Get(c)
  68. item, err := conn.Get(key)
  69. if err != nil {
  70. conn.Close()
  71. }
  72. return &Reply{err: err, item: item, conn: conn}
  73. }
  74. // Item get raw Item
  75. func (r *Reply) Item() *Item {
  76. return r.item
  77. }
  78. // Scan converts value, read from the memcache
  79. func (r *Reply) Scan(v interface{}) (err error) {
  80. if r.err != nil {
  81. return r.err
  82. }
  83. err = r.conn.Scan(r.item, v)
  84. if !r.closed {
  85. r.conn.Close()
  86. r.closed = true
  87. }
  88. return
  89. }
  90. // GetMulti is a batch version of Get
  91. func (mc *Memcache) GetMulti(c context.Context, keys []string) (*Replies, error) {
  92. conn := mc.pool.Get(c)
  93. items, err := conn.GetMulti(keys)
  94. rs := &Replies{err: err, items: items, conn: conn, usedItems: make(map[string]struct{}, len(keys))}
  95. if err != nil {
  96. conn.Close()
  97. rs.closed = true
  98. }
  99. return rs, err
  100. }
  101. // Close close rows.
  102. func (rs *Replies) Close() (err error) {
  103. if !rs.closed {
  104. err = rs.conn.Close()
  105. rs.closed = true
  106. }
  107. return
  108. }
  109. // Item get Item from rows
  110. func (rs *Replies) Item(key string) *Item {
  111. return rs.items[key]
  112. }
  113. // Scan converts value, read from key in rows
  114. func (rs *Replies) Scan(key string, v interface{}) (err error) {
  115. if rs.err != nil {
  116. return rs.err
  117. }
  118. item, ok := rs.items[key]
  119. if !ok {
  120. return ErrNotFound
  121. }
  122. rs.usedItems[key] = struct{}{}
  123. err = rs.conn.Scan(item, v)
  124. shouldClose := len(rs.items) == len(rs.usedItems)
  125. if shouldClose {
  126. rs.Close()
  127. }
  128. return
  129. }
  130. // Keys keys of result
  131. func (rs *Replies) Keys() (keys []string) {
  132. keys = make([]string, 0, len(rs.items))
  133. for key := range rs.items {
  134. keys = append(keys, key)
  135. }
  136. return
  137. }
  138. // Touch updates the expiry for the given key.
  139. func (mc *Memcache) Touch(c context.Context, key string, timeout int32) (err error) {
  140. conn := mc.pool.Get(c)
  141. err = conn.Touch(key, timeout)
  142. conn.Close()
  143. return
  144. }
  145. // Delete deletes the item with the provided key.
  146. func (mc *Memcache) Delete(c context.Context, key string) (err error) {
  147. conn := mc.pool.Get(c)
  148. err = conn.Delete(key)
  149. conn.Close()
  150. return
  151. }
  152. // Increment atomically increments key by delta.
  153. func (mc *Memcache) Increment(c context.Context, key string, delta uint64) (newValue uint64, err error) {
  154. conn := mc.pool.Get(c)
  155. newValue, err = conn.Increment(key, delta)
  156. conn.Close()
  157. return
  158. }
  159. // Decrement atomically decrements key by delta.
  160. func (mc *Memcache) Decrement(c context.Context, key string, delta uint64) (newValue uint64, err error) {
  161. conn := mc.pool.Get(c)
  162. newValue, err = conn.Decrement(key, delta)
  163. conn.Close()
  164. return
  165. }