73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
|
package dao
|
|||
|
|
|||
|
import (
|
|||
|
"context"
|
|||
|
"fmt"
|
|||
|
"go-common/library/cache/memcache"
|
|||
|
"go-common/library/log"
|
|||
|
"go-common/library/stat/prom"
|
|||
|
)
|
|||
|
|
|||
|
func (d *Dao) Lock(c context.Context, key string, val string) (err error) {
|
|||
|
if val == "" {
|
|||
|
return
|
|||
|
}
|
|||
|
conn := d.mc.Get(c)
|
|||
|
defer conn.Close()
|
|||
|
obj := &struct {
|
|||
|
Value string
|
|||
|
}{
|
|||
|
Value: val,
|
|||
|
}
|
|||
|
item := &memcache.Item{Key: key, Object: obj, Expiration: d.cacheTTL.LockTTL, Flags: memcache.FlagJSON}
|
|||
|
if err = conn.Add(item); err != nil {
|
|||
|
prom.BusinessErrCount.Incr("mc:Lock")
|
|||
|
log.Errorv(c, log.KV("Lock", fmt.Sprintf("%+v", err)), log.KV("key", key))
|
|||
|
return
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// no thread-safe, but it's works.
|
|||
|
// bad case of unlocking:
|
|||
|
// 1, process-a gets lock
|
|||
|
// 2, lock expires
|
|||
|
// 3, process-b gets lock
|
|||
|
// 4, process-a releases lock
|
|||
|
func (d *Dao) Unlock(c context.Context, key string, val string) (err error) {
|
|||
|
conn := d.mc.Get(c)
|
|||
|
defer conn.Close()
|
|||
|
reply, err := conn.Get(key)
|
|||
|
if err != nil {
|
|||
|
if err == memcache.ErrNotFound {
|
|||
|
err = nil
|
|||
|
return
|
|||
|
}
|
|||
|
prom.BusinessErrCount.Incr("mc:Unlock")
|
|||
|
log.Errorv(c, log.KV("Unlock", fmt.Sprintf("%+v", err)), log.KV("key", key))
|
|||
|
return
|
|||
|
}
|
|||
|
res := &struct {
|
|||
|
Value string
|
|||
|
}{}
|
|||
|
err = conn.Scan(reply, &res)
|
|||
|
if err != nil {
|
|||
|
prom.BusinessErrCount.Incr("mc:Unlock")
|
|||
|
log.Errorv(c, log.KV("Unlock", fmt.Sprintf("%+v", err)), log.KV("key", key))
|
|||
|
return
|
|||
|
}
|
|||
|
if res.Value != val {
|
|||
|
return nil
|
|||
|
}
|
|||
|
if err = conn.Delete(key); err != nil {
|
|||
|
if err == memcache.ErrNotFound {
|
|||
|
err = nil
|
|||
|
return
|
|||
|
}
|
|||
|
prom.BusinessErrCount.Incr("mc:Unlock")
|
|||
|
log.Errorv(c, log.KV("Unlock", fmt.Sprintf("%+v", err)), log.KV("key", key))
|
|||
|
return
|
|||
|
}
|
|||
|
return
|
|||
|
}
|