Skip to content

Commit

Permalink
feat: Support auto config GroupedIdSegmentDistributor . (#363)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ahoo-Wang authored Jun 29, 2023
1 parent 9f158e5 commit 1a07c0f
Show file tree
Hide file tree
Showing 25 changed files with 361 additions and 108 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright [2021-present] [ahoo wang <[email protected]> (https://github.com/Ahoo-Wang)].
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package me.ahoo.cosid.converter;

import me.ahoo.cosid.IdConverter;

import com.google.common.base.Preconditions;

import javax.annotation.Nonnull;
import java.time.Year;

/**
* Converter for setting string ID prefix.
*
* @author ahoo wang
*/
public class YearPrefixIdConverter implements IdConverter {

private final String delimiter;
private final IdConverter idConverter;

public YearPrefixIdConverter(String delimiter, IdConverter idConverter) {
Preconditions.checkNotNull(delimiter, "prefix can not be null!");
this.delimiter = delimiter;
this.idConverter = idConverter;
}

public String getDelimiter() {
return delimiter;
}

@Nonnull
@Override
public String asString(long id) {
String idStr = idConverter.asString(id);
Year nowYear = Year.now();
if (delimiter.isEmpty()) {
return nowYear + idStr;
}
return nowYear + delimiter + idStr;
}

@Override
public long asLong(@Nonnull String idString) {
int beginIndex = delimiter.length() + 4;
String idStr = idString.substring(beginIndex);
return idConverter.asLong(idStr);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
* @author ahoo wang
*/
public class DefaultIdSegment implements IdSegment {

public static final DefaultIdSegment OVERFLOW = new DefaultIdSegment(IdSegment.SEQUENCE_OVERFLOW, 0, Clock.CACHE.secondTime(), TIME_TO_LIVE_FOREVER);

public static final DefaultIdSegment OVERFLOW = new DefaultIdSegment(IdSegment.SEQUENCE_OVERFLOW, 0, Clock.SYSTEM.secondTime(), TIME_TO_LIVE_FOREVER);
/**
* include.
*/
Expand All @@ -37,13 +37,12 @@ public class DefaultIdSegment implements IdSegment {
private volatile long sequence;
private final long fetchTime;
private final long ttl;

private static final AtomicLongFieldUpdater<DefaultIdSegment> S = AtomicLongFieldUpdater.newUpdater(DefaultIdSegment.class, "sequence");

public DefaultIdSegment(long maxId, long step) {
this(maxId, step, Clock.CACHE.secondTime(), TIME_TO_LIVE_FOREVER);
this(maxId, step, Clock.SYSTEM.secondTime(), TIME_TO_LIVE_FOREVER);
}

public DefaultIdSegment(long maxId, long step, long fetchTime, long ttl) {
Preconditions.checkArgument(ttl > 0, "ttl:[%s] must be greater than 0.", ttl);
this.maxId = maxId;
Expand All @@ -53,51 +52,51 @@ public DefaultIdSegment(long maxId, long step, long fetchTime, long ttl) {
this.fetchTime = fetchTime;
this.ttl = ttl;
}

@Override
public long getFetchTime() {
return fetchTime;
}

@Override
public long getTtl() {
return ttl;
}

@Override
public long getMaxId() {
return maxId;
}

@Override
public long getOffset() {
return offset;
}

@Override
public long getSequence() {
return sequence;
}

@Override
public long getStep() {
return step;
}

@Override
public long incrementAndGet() {
if (isOverflow()) {
return SEQUENCE_OVERFLOW;
}

final long nextSeq = S.incrementAndGet(this);

if (isOverflow(nextSeq)) {
return SEQUENCE_OVERFLOW;
}
return nextSeq;
}

@Override
public String toString() {
return "DefaultIdSegment{"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,27 @@
*/
@Slf4j
public class DefaultSegmentId implements SegmentId {

private final long idSegmentTtl;
private final IdSegmentDistributor maxIdDistributor;

@GuardedBy("this")
private volatile IdSegment segment = DefaultIdSegment.OVERFLOW;

public DefaultSegmentId(IdSegmentDistributor maxIdDistributor) {
this(TIME_TO_LIVE_FOREVER, maxIdDistributor);
}

public DefaultSegmentId(long idSegmentTtl, IdSegmentDistributor maxIdDistributor) {
Preconditions.checkArgument(idSegmentTtl > 0, "idSegmentTtl:[%s] must be greater than 0.", idSegmentTtl);

this.idSegmentTtl = idSegmentTtl;
this.maxIdDistributor = maxIdDistributor;
}

@Override
public long generate() {

if (maxIdDistributor.getStep() == ONE_STEP) {
return maxIdDistributor.nextMaxId();
}
Expand All @@ -59,7 +59,7 @@ public long generate() {
return nextSeq;
}
}

synchronized (this) {
while (true) {
if (segment.isAvailable()) {
Expand All @@ -69,10 +69,12 @@ public long generate() {
}
}
IdSegment nextIdSegment = maxIdDistributor.nextIdSegment(idSegmentTtl);
segment.ensureNextIdSegment(nextIdSegment);
if (!maxIdDistributor.allowReset()) {
segment.ensureNextIdSegment(nextIdSegment);
}
segment = nextIdSegment;
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ default boolean isExpired() {
*/
return false;
}
return Clock.CACHE.secondTime() - getFetchTime() > getTtl();

return Clock.SYSTEM.secondTime() - getFetchTime() > getTtl();
}

default boolean isOverflow() {
Expand Down
60 changes: 35 additions & 25 deletions cosid-core/src/main/java/me/ahoo/cosid/segment/IdSegmentChain.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,23 @@
public class IdSegmentChain implements IdSegment {
public static final int ROOT_VERSION = -1;
public static final IdSegmentChain NOT_SET = null;

private final long version;
private final IdSegment idSegment;
@GuardedBy("this")
private volatile IdSegmentChain next;

public IdSegmentChain(IdSegmentChain previousChain, IdSegment idSegment) {
this(previousChain.getVersion() + 1, idSegment);
private final boolean allowReset;

public IdSegmentChain(IdSegmentChain previousChain, IdSegment idSegment, boolean allowReset) {
this(previousChain.getVersion() + 1, idSegment, allowReset);
}

public IdSegmentChain(long version, IdSegment idSegment) {
public IdSegmentChain(long version, IdSegment idSegment, boolean allowReset) {
this.version = version;
this.idSegment = idSegment;
this.allowReset = allowReset;
}

/**
* try set next Chained ID segment.
*
Expand All @@ -51,7 +53,7 @@ public boolean trySetNext(Function<IdSegmentChain, IdSegmentChain> idSegmentChai
if (NOT_SET != next) {
return false;
}

synchronized (this) {
if (NOT_SET != next) {
return false;
Expand All @@ -61,70 +63,78 @@ public boolean trySetNext(Function<IdSegmentChain, IdSegmentChain> idSegmentChai
return true;
}
}

public void setNext(IdSegmentChain nextIdSegmentChain) {
ensureNextIdSegment(nextIdSegmentChain);
if (!allowReset) {
ensureNextIdSegment(nextIdSegmentChain);
}

next = nextIdSegmentChain;
}

public IdSegmentChain ensureSetNext(Function<IdSegmentChain, IdSegmentChain> idSegmentChainSupplier) throws NextIdSegmentExpiredException {
IdSegmentChain currentChain = this;
while (!currentChain.trySetNext(idSegmentChainSupplier)) {
currentChain = currentChain.getNext();
}
return currentChain;
}

public IdSegmentChain getNext() {
return next;
}

public IdSegment getIdSegment() {
return idSegment;
}

public long getVersion() {
return version;
}

public int gap(IdSegmentChain end, long step) {
return (int) ((end.getMaxId() - getSequence()) / step);
}

public static IdSegmentChain newRoot() {
return new IdSegmentChain(IdSegmentChain.ROOT_VERSION, DefaultIdSegment.OVERFLOW);
public static IdSegmentChain newRoot(boolean allowReset) {
return new IdSegmentChain(IdSegmentChain.ROOT_VERSION, DefaultIdSegment.OVERFLOW, allowReset);
}

@Override
public long getFetchTime() {
return idSegment.getFetchTime();
}


@Override
public long getTtl() {
return idSegment.getTtl();
}

@Override
public long getMaxId() {
return idSegment.getMaxId();
}

@Override
public long getOffset() {
return idSegment.getOffset();
}

@Override
public long getSequence() {
return idSegment.getSequence();
}

@Override
public long getStep() {
return idSegment.getStep();
}

@Override
public long incrementAndGet() {
return idSegment.incrementAndGet();
}

@Override
public String toString() {
return "IdSegmentChain{"
Expand Down
Loading

0 comments on commit 1a07c0f

Please sign in to comment.