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  }