func ExampleMutex() { m, err := redsync.NewMutexWithGenericPool("FlyingSquirrels", pools) if err != nil { panic(err) } err = m.Lock() if err != nil { panic(err) } defer m.Unlock() // Output: }
func TestMutex(t *testing.T) { done := make(chan bool) chErr := make(chan error) for i := 0; i < 4; i++ { go func() { m, err := redsync.NewMutexWithGenericPool("RedsyncMutex", pools) if err != nil { chErr <- err return } f := 0 for j := 0; j < 32; j++ { err := m.Lock() if err == redsync.ErrFailed { f++ if f > 2 { chErr <- err return } continue } if err != nil { chErr <- err return } time.Sleep(1 * time.Millisecond) m.Unlock() time.Sleep(time.Duration(rand.Int31n(128)) * time.Millisecond) } done <- true }() } for i := 0; i < 4; i++ { select { case <-done: case err := <-chErr: t.Fatal(err) } } }
// redMutexForTask vendors a configured redlock w/ randomness builtin for the expiration // of the lock func (r *RateLimiter) redMutexForTask(factor float64, delay int64) *redsync.Mutex { // Grab the pool redisPool := r.pool nodes := []redsync.Pool{redisPool} // Generate the mutex w/ token redSyncToken := r.redlockToken() redMutex, err := redsync.NewMutexWithGenericPool(redSyncToken, nodes) if err != nil { meshLog.Fatalf("Error creating RedMutex in limiter: %+v", err) return nil } // Configure the mutex to have add sleep time randomness to its waiting. It was // found in testing that w/ out this, the system locks in step w/ itself when not using // a local pmutex. This is a danger for dist systems redMutex.Tries = 10000 sleepTime := (rand.Float64() * factor * float64(delay)) + float64(delay) redMutex.Delay = time.Duration(sleepTime) * time.Millisecond redMutex.Expiry = 15 * time.Second return redMutex }