github.com/goravel/framework@v1.13.9/cache/lock.go (about) 1 package cache 2 3 import ( 4 "time" 5 6 contractscache "github.com/goravel/framework/contracts/cache" 7 ) 8 9 type Lock struct { 10 store contractscache.Driver 11 key string 12 time *time.Duration 13 get bool 14 } 15 16 func NewLock(instance contractscache.Driver, key string, t ...time.Duration) *Lock { 17 if len(t) == 0 { 18 return &Lock{ 19 store: instance, 20 key: key, 21 } 22 } 23 24 return &Lock{ 25 store: instance, 26 key: key, 27 time: &t[0], 28 } 29 } 30 31 func (r *Lock) Block(t time.Duration, callback ...func()) bool { 32 timer := time.NewTimer(t) 33 ticker := time.NewTicker(1 * time.Second) 34 defer ticker.Stop() 35 36 res := make(chan bool, 1) 37 go func() { 38 for { 39 select { 40 case <-timer.C: 41 if r.Get(callback...) { 42 res <- true 43 return 44 } 45 46 res <- false 47 return 48 case <-ticker.C: 49 if r.Get(callback...) { 50 res <- true 51 return 52 } 53 } 54 } 55 }() 56 57 return <-res 58 } 59 60 func (r *Lock) Get(callback ...func()) bool { 61 var res bool 62 if r.time == nil { 63 res = r.store.Add(r.key, 1, NoExpiration) 64 } else { 65 res = r.store.Add(r.key, 1, *r.time) 66 } 67 68 if !res { 69 return false 70 } 71 72 r.get = true 73 74 if len(callback) == 0 { 75 return true 76 } 77 78 callback[0]() 79 80 return r.Release() 81 } 82 83 func (r *Lock) Release() bool { 84 if r.get { 85 return r.ForceRelease() 86 } 87 88 return false 89 } 90 91 func (r *Lock) ForceRelease() bool { 92 return r.store.Forget(r.key) 93 }