23 changed files with 814 additions and 119 deletions
@ -0,0 +1,89 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue; |
|||
|
|||
import lombok.Getter; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.msg.queue.RuleEngineException; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategy; |
|||
|
|||
import java.util.UUID; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
import java.util.concurrent.CountDownLatch; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
public class ProcessingAttemptContext { |
|||
|
|||
private final TbRuleEngineSubmitStrategy submitStrategy; |
|||
|
|||
private final CountDownLatch processingTimeoutLatch = new CountDownLatch(1); |
|||
@Getter |
|||
private final ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> pendingMap; |
|||
@Getter |
|||
private final ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> successMap = new ConcurrentHashMap<>(); |
|||
@Getter |
|||
private final ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> failedMap = new ConcurrentHashMap<>(); |
|||
@Getter |
|||
private final ConcurrentMap<TenantId, RuleEngineException> exceptionsMap = new ConcurrentHashMap<>(); |
|||
|
|||
public ProcessingAttemptContext(TbRuleEngineSubmitStrategy submitStrategy) { |
|||
this.submitStrategy = submitStrategy; |
|||
this.pendingMap = submitStrategy.getPendingMap(); |
|||
} |
|||
|
|||
public boolean await(long packProcessingTimeout, TimeUnit milliseconds) throws InterruptedException { |
|||
return processingTimeoutLatch.await(packProcessingTimeout, milliseconds); |
|||
} |
|||
|
|||
public void onSuccess(UUID id) { |
|||
TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg> msg; |
|||
boolean empty = false; |
|||
synchronized (pendingMap) { |
|||
msg = pendingMap.remove(id); |
|||
if (msg != null) { |
|||
empty = pendingMap.isEmpty(); |
|||
} |
|||
} |
|||
if (msg != null) { |
|||
successMap.put(id, msg); |
|||
} |
|||
submitStrategy.onSuccess(id); |
|||
if (empty) { |
|||
processingTimeoutLatch.countDown(); |
|||
} |
|||
} |
|||
|
|||
public void onFailure(TenantId tenantId, UUID id, RuleEngineException e) { |
|||
TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg> msg; |
|||
boolean empty = false; |
|||
synchronized (pendingMap) { |
|||
msg = pendingMap.remove(id); |
|||
if (msg != null) { |
|||
empty = pendingMap.isEmpty(); |
|||
} |
|||
} |
|||
if (msg != null) { |
|||
failedMap.put(id, msg); |
|||
exceptionsMap.putIfAbsent(tenantId, e); |
|||
} |
|||
if (empty) { |
|||
processingTimeoutLatch.countDown(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,71 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue.processing; |
|||
|
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
import java.util.stream.Collectors; |
|||
|
|||
public abstract class AbstractTbRuleEngineSubmitStrategy implements TbRuleEngineSubmitStrategy { |
|||
|
|||
protected final String queueName; |
|||
protected List<IdMsgPair> orderedMsgList; |
|||
private volatile boolean stopped; |
|||
|
|||
public AbstractTbRuleEngineSubmitStrategy(String queueName) { |
|||
this.queueName = queueName; |
|||
} |
|||
|
|||
protected abstract void doOnSuccess(UUID id); |
|||
|
|||
@Override |
|||
public void init(List<TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgs) { |
|||
orderedMsgList = msgs.stream().map(msg -> new IdMsgPair(UUID.randomUUID(), msg)).collect(Collectors.toList()); |
|||
} |
|||
|
|||
@Override |
|||
public ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> getPendingMap() { |
|||
return orderedMsgList.stream().collect(Collectors.toConcurrentMap(pair -> pair.uuid, pair -> pair.msg)); |
|||
} |
|||
|
|||
@Override |
|||
public void update(ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> reprocessMap) { |
|||
List<IdMsgPair> newOrderedMsgList = new ArrayList<>(reprocessMap.size()); |
|||
for (IdMsgPair pair : orderedMsgList) { |
|||
if (reprocessMap.containsKey(pair.uuid)) { |
|||
newOrderedMsgList.add(pair); |
|||
} |
|||
} |
|||
orderedMsgList = newOrderedMsgList; |
|||
} |
|||
|
|||
@Override |
|||
public void onSuccess(UUID id) { |
|||
if (!stopped) { |
|||
doOnSuccess(id); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void stop() { |
|||
stopped = true; |
|||
} |
|||
} |
|||
@ -0,0 +1,86 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue.processing; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
|
|||
import java.util.LinkedHashMap; |
|||
import java.util.Map; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
import java.util.concurrent.ExecutorService; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
import java.util.function.BiConsumer; |
|||
|
|||
@Slf4j |
|||
public class BatchTbRuleEngineSubmitStrategy extends AbstractTbRuleEngineSubmitStrategy { |
|||
|
|||
private final int batchSize; |
|||
private final AtomicInteger packIdx = new AtomicInteger(0); |
|||
private final Map<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> pendingPack = new LinkedHashMap<>(); |
|||
private volatile BiConsumer<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgConsumer; |
|||
|
|||
public BatchTbRuleEngineSubmitStrategy(String queueName, int batchSize) { |
|||
super(queueName); |
|||
this.batchSize = batchSize; |
|||
} |
|||
|
|||
@Override |
|||
public void submitAttempt(BiConsumer<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgConsumer) { |
|||
this.msgConsumer = msgConsumer; |
|||
submitNext(); |
|||
} |
|||
|
|||
@Override |
|||
public void update(ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> reprocessMap) { |
|||
super.update(reprocessMap); |
|||
packIdx.set(0); |
|||
} |
|||
|
|||
@Override |
|||
protected void doOnSuccess(UUID id) { |
|||
boolean endOfPendingPack; |
|||
synchronized (pendingPack) { |
|||
TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg> msg = pendingPack.remove(id); |
|||
endOfPendingPack = msg != null && pendingPack.isEmpty(); |
|||
} |
|||
if (endOfPendingPack) { |
|||
packIdx.incrementAndGet(); |
|||
submitNext(); |
|||
} |
|||
} |
|||
|
|||
private void submitNext() { |
|||
int listSize = orderedMsgList.size(); |
|||
int startIdx = Math.min(packIdx.get() * batchSize, listSize); |
|||
int endIdx = Math.min(startIdx + batchSize, listSize); |
|||
synchronized (pendingPack) { |
|||
pendingPack.clear(); |
|||
for (int i = startIdx; i < endIdx; i++) { |
|||
IdMsgPair pair = orderedMsgList.get(i); |
|||
pendingPack.put(pair.uuid, pair.msg); |
|||
} |
|||
} |
|||
int submitSize = pendingPack.size(); |
|||
if (log.isInfoEnabled() && submitSize > 0) { |
|||
log.info("[{}] submitting [{}] messages to rule engine", queueName, submitSize); |
|||
} |
|||
pendingPack.forEach(msgConsumer); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue.processing; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
import java.util.concurrent.ExecutorService; |
|||
import java.util.function.BiConsumer; |
|||
import java.util.function.Function; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Slf4j |
|||
public class BurstTbRuleEngineSubmitStrategy extends AbstractTbRuleEngineSubmitStrategy { |
|||
|
|||
public BurstTbRuleEngineSubmitStrategy(String queueName) { |
|||
super(queueName); |
|||
} |
|||
|
|||
@Override |
|||
public void submitAttempt(BiConsumer<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgConsumer) { |
|||
if (log.isInfoEnabled()) { |
|||
log.info("[{}] submitting [{}] messages to rule engine", queueName, orderedMsgList.size()); |
|||
} |
|||
orderedMsgList.forEach(pair -> msgConsumer.accept(pair.uuid, pair.msg)); |
|||
} |
|||
|
|||
@Override |
|||
protected void doOnSuccess(UUID id) { |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue.processing; |
|||
|
|||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
public class IdMsgPair { |
|||
final UUID uuid; |
|||
final TbProtoQueueMsg<ToRuleEngineMsg> msg; |
|||
|
|||
public IdMsgPair(UUID uuid, TbProtoQueueMsg<ToRuleEngineMsg> msg) { |
|||
this.uuid = uuid; |
|||
this.msg = msg; |
|||
} |
|||
} |
|||
@ -0,0 +1,108 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue.processing; |
|||
|
|||
import com.google.protobuf.InvalidProtocolBufferException; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.EntityIdFactory; |
|||
import org.thingsboard.server.common.msg.TbMsg; |
|||
import org.thingsboard.server.common.msg.gen.MsgProtos; |
|||
import org.thingsboard.server.common.msg.queue.TbMsgCallback; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.LinkedList; |
|||
import java.util.List; |
|||
import java.util.Queue; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
import java.util.function.BiConsumer; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Slf4j |
|||
public abstract class SequentialByEntityIdTbRuleEngineSubmitStrategy extends AbstractTbRuleEngineSubmitStrategy { |
|||
|
|||
private volatile BiConsumer<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgConsumer; |
|||
private volatile ConcurrentMap<UUID, EntityId> msgToEntityIdMap = new ConcurrentHashMap<>(); |
|||
private volatile ConcurrentMap<EntityId, Queue<IdMsgPair>> entityIdToListMap = new ConcurrentHashMap<>(); |
|||
|
|||
public SequentialByEntityIdTbRuleEngineSubmitStrategy(String queueName) { |
|||
super(queueName); |
|||
} |
|||
|
|||
@Override |
|||
public void init(List<TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgs) { |
|||
super.init(msgs); |
|||
initMaps(); |
|||
} |
|||
|
|||
@Override |
|||
public void submitAttempt(BiConsumer<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgConsumer) { |
|||
this.msgConsumer = msgConsumer; |
|||
entityIdToListMap.forEach((entityId, queue) -> { |
|||
IdMsgPair msg = queue.peek(); |
|||
if (msg != null) { |
|||
msgConsumer.accept(msg.uuid, msg.msg); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
@Override |
|||
public void update(ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> reprocessMap) { |
|||
super.update(reprocessMap); |
|||
initMaps(); |
|||
} |
|||
|
|||
@Override |
|||
protected void doOnSuccess(UUID id) { |
|||
EntityId entityId = msgToEntityIdMap.get(id); |
|||
if (entityId != null) { |
|||
Queue<IdMsgPair> queue = entityIdToListMap.get(entityId); |
|||
if (queue != null) { |
|||
IdMsgPair next = null; |
|||
synchronized (queue) { |
|||
IdMsgPair expected = queue.peek(); |
|||
if (expected != null && expected.uuid.equals(id)) { |
|||
queue.poll(); |
|||
next = queue.peek(); |
|||
} |
|||
} |
|||
if (next != null) { |
|||
msgConsumer.accept(next.uuid, next.msg); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void initMaps() { |
|||
msgToEntityIdMap.clear(); |
|||
entityIdToListMap.clear(); |
|||
for (IdMsgPair pair : orderedMsgList) { |
|||
EntityId entityId = getEntityId(pair.msg.getValue()); |
|||
if (entityId != null) { |
|||
msgToEntityIdMap.put(pair.uuid, entityId); |
|||
entityIdToListMap.computeIfAbsent(entityId, id -> new LinkedList<>()).add(pair); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected abstract EntityId getEntityId(TransportProtos.ToRuleEngineMsg msg); |
|||
|
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue.processing; |
|||
|
|||
import com.google.protobuf.InvalidProtocolBufferException; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.EntityIdFactory; |
|||
import org.thingsboard.server.common.msg.gen.MsgProtos; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
@Slf4j |
|||
public class SequentialByOriginatorIdTbRuleEngineSubmitStrategy extends SequentialByEntityIdTbRuleEngineSubmitStrategy { |
|||
|
|||
public SequentialByOriginatorIdTbRuleEngineSubmitStrategy(String queueName) { |
|||
super(queueName); |
|||
} |
|||
|
|||
@Override |
|||
protected EntityId getEntityId(TransportProtos.ToRuleEngineMsg msg) { |
|||
try { |
|||
MsgProtos.TbMsgProto proto = MsgProtos.TbMsgProto.parseFrom(msg.getTbMsg()); |
|||
return EntityIdFactory.getByTypeAndUuid(proto.getEntityType(), new UUID(proto.getEntityIdMSB(), proto.getEntityIdLSB())); |
|||
} catch (InvalidProtocolBufferException e) { |
|||
log.warn("[{}] Failed to parse TbMsg: {}", queueName, msg); |
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue.processing; |
|||
|
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
public class SequentialByTenantIdTbRuleEngineSubmitStrategy extends SequentialByEntityIdTbRuleEngineSubmitStrategy { |
|||
|
|||
public SequentialByTenantIdTbRuleEngineSubmitStrategy(String queueName) { |
|||
super(queueName); |
|||
} |
|||
|
|||
@Override |
|||
protected EntityId getEntityId(TransportProtos.ToRuleEngineMsg msg) { |
|||
return new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue.processing; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
|
|||
import java.util.LinkedHashMap; |
|||
import java.util.Map; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
import java.util.function.BiConsumer; |
|||
|
|||
@Slf4j |
|||
public class SequentialTbRuleEngineSubmitStrategy extends AbstractTbRuleEngineSubmitStrategy { |
|||
|
|||
private final AtomicInteger msgIdx = new AtomicInteger(0); |
|||
private volatile BiConsumer<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgConsumer; |
|||
private volatile UUID expectedMsgId; |
|||
|
|||
public SequentialTbRuleEngineSubmitStrategy(String queueName) { |
|||
super(queueName); |
|||
} |
|||
|
|||
@Override |
|||
public void submitAttempt(BiConsumer<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgConsumer) { |
|||
this.msgConsumer = msgConsumer; |
|||
msgIdx.set(0); |
|||
submitNext(); |
|||
} |
|||
|
|||
@Override |
|||
public void update(ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> reprocessMap) { |
|||
super.update(reprocessMap); |
|||
} |
|||
|
|||
@Override |
|||
protected void doOnSuccess(UUID id) { |
|||
if (expectedMsgId.equals(id)) { |
|||
msgIdx.incrementAndGet(); |
|||
submitNext(); |
|||
} |
|||
} |
|||
|
|||
private void submitNext() { |
|||
int listSize = orderedMsgList.size(); |
|||
int idx = msgIdx.get(); |
|||
if (idx < listSize) { |
|||
IdMsgPair pair = orderedMsgList.get(idx); |
|||
expectedMsgId = pair.uuid; |
|||
if (log.isInfoEnabled()) { |
|||
log.info("[{}] submitting [{}] message to rule engine", queueName, pair.msg); |
|||
} |
|||
msgConsumer.accept(pair.uuid, pair.msg); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue.processing; |
|||
|
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|||
|
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.ConcurrentMap; |
|||
import java.util.function.BiConsumer; |
|||
|
|||
public interface TbRuleEngineSubmitStrategy { |
|||
|
|||
void init(List<TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgs); |
|||
|
|||
ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> getPendingMap(); |
|||
|
|||
void submitAttempt(BiConsumer<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> msgConsumer); |
|||
|
|||
void update(ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> reprocessMap); |
|||
|
|||
void onSuccess(UUID id); |
|||
|
|||
void stop(); |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.service.queue.processing; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
import org.thingsboard.server.queue.settings.TbRuleEngineQueueSubmitStrategyConfiguration; |
|||
|
|||
@Component |
|||
@Slf4j |
|||
public class TbRuleEngineSubmitStrategyFactory { |
|||
|
|||
public TbRuleEngineSubmitStrategy newInstance(String name, TbRuleEngineQueueSubmitStrategyConfiguration configuration) { |
|||
switch (configuration.getType()) { |
|||
case "BURST": |
|||
return new BurstTbRuleEngineSubmitStrategy(name); |
|||
case "BATCH": |
|||
return new BatchTbRuleEngineSubmitStrategy(name, configuration.getBatchSize()); |
|||
case "SEQUENTIAL_WITHIN_ORIGINATOR": |
|||
return new SequentialByOriginatorIdTbRuleEngineSubmitStrategy(name); |
|||
case "SEQUENTIAL_WITHIN_TENANT": |
|||
return new SequentialByTenantIdTbRuleEngineSubmitStrategy(name); |
|||
case "SEQUENTIAL": |
|||
return new SequentialTbRuleEngineSubmitStrategy(name); |
|||
default: |
|||
throw new RuntimeException("TbRuleEngineProcessingStrategy with type " + configuration.getType() + " is not supported!"); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* 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 org.thingsboard.server.queue.settings; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class TbRuleEngineQueueSubmitStrategyConfiguration { |
|||
|
|||
private String type; |
|||
private int batchSize; |
|||
|
|||
} |
|||
Loading…
Reference in new issue