Snowflake增加方法:根据传入时间戳,计算ID起终点

This commit is contained in:
Looly 2023-10-25 11:24:50 +08:00
parent 47c07d94ad
commit 3ef6b7ed8f
3 changed files with 66 additions and 4 deletions

View File

@ -14,8 +14,9 @@ package org.dromara.hutool.core.data.id;
import org.dromara.hutool.core.date.SystemClock;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.util.RandomUtil;
import org.dromara.hutool.core.lang.tuple.Pair;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.RandomUtil;
import java.io.Serializable;
import java.util.Date;
@ -259,6 +260,40 @@ public class Snowflake implements Serializable {
return Long.toString(nextId());
}
/**
* 根据传入时间戳-计算ID起终点
*
* @param timestampStart 开始时间戳
* @param timestampEnd 结束时间戳
* @return key-ID起点Value-ID终点
* @since 5.8.23
*/
public Pair<Long, Long> getIdScopeByTimestamp(final long timestampStart, final long timestampEnd) {
return getIdScopeByTimestamp(timestampStart, timestampEnd, true);
}
/**
* 根据传入时间戳-计算ID起终点 Gitee/issues/I60M14
*
* @param timestampStart 开始时间戳
* @param timestampEnd 结束时间戳
* @param ignoreCenterAndWorker 是否忽略数据中心和机器节点的占位忽略后可获得分布式环境全局可信赖的起终点
* @return key-ID起点Value-ID终点
* @since 5.8.23
*/
public Pair<Long, Long> getIdScopeByTimestamp(final long timestampStart, final long timestampEnd, final boolean ignoreCenterAndWorker) {
final long startTimeMinId = (timestampStart - twepoch) << TIMESTAMP_LEFT_SHIFT;
final long endTimeMinId = (timestampEnd - twepoch) << TIMESTAMP_LEFT_SHIFT;
if (ignoreCenterAndWorker) {
final long endId = endTimeMinId | ~(-1 << TIMESTAMP_LEFT_SHIFT);
return Pair.of(startTimeMinId, endId);
} else {
final long startId = startTimeMinId | (dataCenterId << DATA_CENTER_ID_SHIFT) | (workerId << WORKER_ID_SHIFT);
final long endId = endTimeMinId | (dataCenterId << DATA_CENTER_ID_SHIFT) | (workerId << WORKER_ID_SHIFT) | SEQUENCE_MASK;
return Pair.of(startId, endId);
}
}
// ------------------------------------------------------------------------------------------------------------------------------------ Private method start
/**

View File

@ -128,6 +128,7 @@ public class PathCopier extends SrcToDestCopier<Path, PathCopier> {
return copyFile(src, target, options);
}
// region private methods
/**
* 拷贝目录下的所有文件或目录到目标目录中此方法不支持文件对文件的拷贝
* <ul>
@ -161,8 +162,8 @@ public class PathCopier extends SrcToDestCopier<Path, PathCopier> {
* @throws IORuntimeException IO异常
*/
private static Path copyFile(final Path src, final Path target, final CopyOption... options) throws IORuntimeException {
Assert.notNull(src, "Source File is null !");
Assert.notNull(target, "Destination File or directory is null !");
Assert.notNull(src, "Source file is null !");
Assert.notNull(target, "Target file or directory is null !");
final Path targetPath = PathUtil.isDirectory(target) ? target.resolve(src.getFileName()) : target;
// 创建级联父目录
@ -173,4 +174,5 @@ public class PathCopier extends SrcToDestCopier<Path, PathCopier> {
throw new IORuntimeException(e);
}
}
// endregion
}

View File

@ -13,11 +13,13 @@
package org.dromara.hutool.core.lang;
import org.dromara.hutool.core.collection.ConcurrentHashSet;
import org.dromara.hutool.core.exception.HutoolException;
import org.dromara.hutool.core.data.id.IdUtil;
import org.dromara.hutool.core.data.id.Snowflake;
import org.dromara.hutool.core.exception.HutoolException;
import org.dromara.hutool.core.lang.tuple.Pair;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.thread.ThreadUtil;
import org.dromara.hutool.core.util.RandomUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@ -116,4 +118,27 @@ public class SnowflakeTest {
}
});
}
/**
* 测试-根据传入时间戳-计算ID起终点
*/
@Test
public void snowflakeTestGetIdScope() {
final long workerId = RandomUtil.randomLong(31);
final long dataCenterId = RandomUtil.randomLong(31);
final Snowflake idWorker = new Snowflake(workerId, dataCenterId);
final long generatedId = idWorker.nextId();
// 随机忽略数据中心和工作机器的占位
final boolean ignore = RandomUtil.randomBoolean();
final long createTimestamp = idWorker.getGenerateDateTime(generatedId);
final Pair<Long, Long> idScope = idWorker.getIdScopeByTimestamp(createTimestamp, createTimestamp, ignore);
final long startId = idScope.getLeft();
final long endId = idScope.getRight();
// 起点终点相差比较
final long trueOffSet = endId - startId;
// 忽略数据中心和工作机器时差值为22个1否则为12个1
final long expectedOffSet = ignore ? ~(-1 << 22) : ~(-1 << 12);
Assertions.assertEquals(trueOffSet, expectedOffSet);
}
}