Esempio n. 1
0
func TestLockContestDuo(t *testing.T) {
	assert := assert.New(t)
	// Instantiation
	c := cluster.NewRedisCluster(rConfig)
	assert.NotEmpty(c)
	defer c.Close()
	// Create 2 locks on the same key
	key := RandomKey()
	locks := []*lock.Lock{
		lock.CreateLock(c, key),
		lock.CreateLock(c, key),
	}
	// Unlease dogs of war
	result := make(chan int, 2)
	acquired := 0
	for _, l := range locks {
		func(l *lock.Lock) {
			go func() {
				success, err := l.Get(false)
				assert.Empty(err)
				if success {
					acquired++
				}
				result <- 1
			}()
		}(l)
	}
	// Wait for them to finish
	<-result
	<-result
	assert.Equal(acquired, 1)
}
Esempio n. 2
0
func TestLockAutoExpire(t *testing.T) {
	assert := assert.New(t)
	// Instantiation
	c := cluster.NewRedisCluster(rConfig)
	assert.NotEmpty(c)
	defer c.Close()
	// Create lock
	key := RandomKey()
	l1 := lock.CreateLock(c, key)
	duration := 3 * time.Second
	l1.Duration = duration
	l2 := lock.CreateLock(c, key)
	// Acquire lock
	success, err := l1.Get(false)
	assert.Empty(err)
	assert.True(success)
	// Acquire lock on the same key, should fail
	success, err = l2.Get(false)
	assert.Empty(err)
	assert.False(success)
	// Sleep past the expiration time
	time.Sleep(duration)
	// Acquire lock, should succeed this time
	success, err = l2.Get(false)
	assert.Empty(err)
	assert.True(success)
}
Esempio n. 3
0
func TestLockRelease(t *testing.T) {
	assert := assert.New(t)
	// Instantiation
	c := cluster.NewRedisCluster(rConfig)
	assert.NotEmpty(c)
	defer c.Close()
	// Create lock
	key := RandomKey()
	l1 := lock.CreateLock(c, key)
	l1.Duration = 16 * time.Second
	l2 := lock.CreateLock(c, key)
	// Acquire lock
	success, err := l1.Get(false)
	assert.Empty(err)
	assert.True(success)
	assert.True(l1.IsActive())
	// Acquire lock on the same key, should fail
	success, err = l2.Get(false)
	assert.Empty(err)
	assert.False(success)
	assert.False(l2.IsActive())
	// Release original lock
	success, err = l1.Release()
	assert.Empty(err)
	assert.True(success)
	assert.False(l1.IsActive())
	// Acquire lock, should succeed this time
	success, err = l2.Get(false)
	assert.Empty(err)
	assert.True(success)
	assert.True(l2.IsActive())
}
Esempio n. 4
0
func TestLockMutualExclusion(t *testing.T) {
	assert := assert.New(t)
	// Instantiation
	c := cluster.NewRedisCluster(rConfig)
	assert.NotEmpty(c)
	defer c.Close()
	// Create locks
	key := RandomKey()
	l1 := lock.CreateLock(c, key)
	l2 := lock.CreateLock(c, key)
	l1.Duration = 3 * time.Second
	l2.Duration = 3 * time.Second
	// Acquire lock on l1
	success, err := l1.Get(false)
	assert.Empty(err)
	assert.True(success)
	assert.True(l1.IsActive())
	// Acquire lock on l2, should fail
	success, err = l2.Get(false)
	assert.Empty(err)
	assert.False(success)
	assert.False(l2.IsActive())
}
Esempio n. 5
0
func TestLockAcquisition(t *testing.T) {
	assert := assert.New(t)
	// Instantiation
	c := cluster.NewRedisCluster(rConfig)
	assert.NotEmpty(c)
	defer c.Close()
	// Create lock
	key := RandomKey()
	l := lock.CreateLock(c, key)
	l.Duration = 3 * time.Second
	// Acquire lock
	success, err := l.Get(false)
	assert.Empty(err)
	assert.True(success)
	assert.True(l.IsActive())
}
Esempio n. 6
0
func TestLockContestTrio(t *testing.T) {
	assert := assert.New(t)
	// Instantiation
	clusters := []*cluster.RedisCluster{
		cluster.NewRedisCluster(rConfig),
		cluster.NewRedisCluster(rConfig),
		cluster.NewRedisCluster(rConfig),
	}
	defer func() {
		for _, c := range clusters {
			c.Close()
		}
	}()
	// Create 3 locks on the same key
	key := RandomKey()
	locks := []*lock.Lock{}
	for _, c := range clusters {
		l := lock.CreateLock(c, key)
		locks = append(locks, l)
	}
	// Unlease dogs of war
	result := make(chan int, 3)
	acquired := 0
	for _, l := range locks {
		func(l *lock.Lock) {
			go func() {
				success, err := l.Get(false)
				assert.Empty(err)
				if success {
					acquired++
				}
				result <- 1
			}()
		}(l)
	}
	// Wait for them to finish
	for i := 0; i < 3; i++ {
		<-result
	}
	assert.True(acquired <= 1)
}
Esempio n. 7
0
func (m *Magi) process(queueName string, id string) {
	var _lock *lock.Lock
	// Catch panics
	defer func() {
		if err := recover(); err != nil {
			err, ok := err.(error)
			if ok && err.Error() == lock.ErrLockLost.Error() {
				// Lock is lost, release remaining lock segments
				_lock.Release()
			} else {
				panic(err)
			}
		}
	}()
	// Check if the processor is available
	processor, exists := m.processors[queueName]
	if !exists {
		return
	}
	// Get job details
	_job, err := m.GetJob(id)
	if err != nil {
		return
	}
	// Acquire lock
	_lock = lock.CreateLock(m.rCluster, id)
	result, err := _lock.Get((*processor).ShouldAutoRenew(_job))
	// If lock cannot be acquired, return and do not acknowledge
	if err != nil {
		return
	}
	if !result {
		return
	}
	// Start the auto wait extension for the job in queue
	control := make(chan bool, 1)
	_job.IsProcessing = true
	go m.autoWait(_job, &control)
	// Process the job
	(*processor).Process(_job)
	// Stop the auto wait extension
	_job.IsProcessing = false
	control <- true
	// Ack the job
	err = m.dqCluster.Ack(id)
	if err != nil {
		return
	}
	if !result {
		return
	}
	// Release the lock
	result, err = _lock.Release()
	if err != nil {
		return
	}
	if !result {
		return
	}
	return
}