com.github.shoothzj.sdk.distribute.impl.mongo.MongoDistributeImpl Maven / Gradle / Ivy
package com.github.shoothzj.sdk.distribute.impl.mongo;
import com.github.shoothzj.javatool.util.CommonUtil;
import com.github.shoothzj.sdk.distribute.api.ElectionListener;
import com.github.shoothzj.sdk.distribute.api.IDistribute;
import com.github.shoothzj.sdk.distribute.impl.mongo.dao.ElectionId;
import com.github.shoothzj.sdk.distribute.impl.mongo.dao.MongoLock;
import com.github.shoothzj.sdk.distribute.impl.mongo.repo.ElectionIdRepo;
import com.github.shoothzj.sdk.distribute.impl.mongo.repo.MongoLockRepo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* @author hezhangjian
*/
@Slf4j
@Service
public class MongoDistributeImpl implements IDistribute {
private static final int RETRY_TIME = 20;
private static final int TIME_SLOP_MS = 10;
private MongoLockRepo mongoLockRepo;
private ElectionIdRepo electionIdRepo;
public MongoDistributeImpl(@Autowired MongoLockRepo mongoLockRepo, @Autowired ElectionIdRepo electionIdRepo) {
this.mongoLockRepo = mongoLockRepo;
this.electionIdRepo = electionIdRepo;
}
@Override
public void addElectionListener(String scene, ElectionListener listener) throws Exception {
}
@Override
public String requireLock(String scene, long time) throws Exception {
String uniqId = UUID.randomUUID().toString();
MongoLock mongoLock = mongoLockRepo.findMongoLockByScene(scene);
long expireTime = System.currentTimeMillis() + time;
if (mongoLock == null) {
//如果mongoLock存在,尝试插入,插入成功即获得了锁
try {
mongoLockRepo.insert(new MongoLock(scene, uniqId, expireTime));
return uniqId;
} catch (Exception e) {
log.error("insert mongo data failed, ", e);
throw new Exception("get lock failed", e);
}
} else {
if (mongoLock.getExpireTime() < System.currentTimeMillis()) {
//原来的锁过期,可以覆盖
mongoLockRepo.findAndModify(scene, mongoLock.getUniqId(), uniqId, expireTime);
return uniqId;
}
}
throw new Exception("get lock failed");
}
@Override
public void releaseLock(String scene, String uniqId) throws Exception {
Long result = mongoLockRepo.deleteBySceneAndUniqId(scene, uniqId);
log.debug("delete end result is [{}]", result);
}
@Override
public long getNumber(String scene) throws Exception {
for (int i = 0; i < RETRY_TIME; i++) {
try {
Long maxId = electionIdRepo.maxId(scene);
electionIdRepo.insert(new ElectionId(scene, maxId + 1));
return maxId + 1;
} catch (Exception e) {
log.error("id find or insert exception, retrying, cause is [{}]", e.getMessage());
CommonUtil.sleep(TimeUnit.MILLISECONDS, TIME_SLOP_MS);
}
}
throw new Exception("");
}
}