All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.craft.atom.lock.ShardedRedis24DLock Maven / Gradle / Ivy

package io.craft.atom.lock;

import io.craft.atom.lock.api.DLock;
import io.craft.atom.redis.api.RedisTransaction;
import io.craft.atom.redis.api.ShardedRedisCommand;

import java.util.List;
import java.util.concurrent.TimeUnit;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A implementation of the {@code DLock} base on redis version 2.4.x, which using sharded redis instance.
 * 
 * @author mindwind
 * @version 1.0, Jul 16, 2013
 */
@ToString(of = "shardedRedis")
public class ShardedRedis24DLock implements DLock {
	
	
	private static final Logger LOG = LoggerFactory.getLogger(ShardedRedis24DLock.class);
	
	
	@Getter @Setter private ShardedRedisCommand shardedRedis;
	
	
	// ~ ----------------------------------------------------------------------------------------------------------
	
	
	public ShardedRedis24DLock() {
		super();
	}
	
	public ShardedRedis24DLock(ShardedRedisCommand shardedRedis) {
		this.shardedRedis = shardedRedis;
	}
	
	
	// ~ ----------------------------------------------------------------------------------------------------------
	

	@Override
	public boolean tryLock(String lockKey, int ttl, TimeUnit unit) {
		if (lockKey == null || unit == null) {
			throw new IllegalArgumentException(String.format("Args=", lockKey, unit));
		}
		
		int ttlSeconds = (int) TimeUnit.SECONDS.convert(ttl, unit);
		if (ttlSeconds == 0) {
			ttlSeconds = 1;
		}
		
		boolean success = true;
		try {
			shardedRedis.watch(lockKey, lockKey);
			if (shardedRedis.get(lockKey, lockKey) == null) {
				success = tryLock0(lockKey, ttlSeconds);
			} else {
				success = false;
			}
		} catch (Exception e) {
			LOG.error("[CRAFT-ATOM-LOCK] Try lock fail, |lockKey={}, ttl={}, unit={}|", lockKey, ttl, unit, e);
			success = false;
		} finally {
			shardedRedis.unwatch(lockKey);
		}
		return success;
	}
	
	private boolean tryLock0(String lockKey, int ttlSeconds) {
		RedisTransaction t = shardedRedis.multi(lockKey);
		t.setex(lockKey, ttlSeconds, "1");
		List result = shardedRedis.exec(lockKey, t);
		return result != null && result.size() > 0;
	}

	@Override
	public boolean unlock(String lockKey) {
		boolean success = true;
		
		try {
			shardedRedis.del(lockKey, lockKey);
		} catch (Exception e) {
			LOG.error("Unlock fail, |lockKey={}|", lockKey, e);
			success = false;
		}
		
		return success;
	}
	
}