committed by
GitHub
61 changed files with 29 additions and 8190 deletions
@ -1,137 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.azure.servicebus; |
|
||||
|
|
||||
import com.microsoft.azure.servicebus.management.ManagementClient; |
|
||||
import com.microsoft.azure.servicebus.management.QueueDescription; |
|
||||
import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder; |
|
||||
import com.microsoft.azure.servicebus.primitives.MessagingEntityAlreadyExistsException; |
|
||||
import com.microsoft.azure.servicebus.primitives.ServiceBusException; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.util.PropertyUtils; |
|
||||
|
|
||||
import java.io.IOException; |
|
||||
import java.time.Duration; |
|
||||
import java.util.Map; |
|
||||
import java.util.Set; |
|
||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||
|
|
||||
@Slf4j |
|
||||
@Deprecated(forRemoval = true, since = "3.9") // for removal in 4.0
|
|
||||
public class TbServiceBusAdmin implements TbQueueAdmin { |
|
||||
private final String MAX_SIZE = "maxSizeInMb"; |
|
||||
private final String MESSAGE_TIME_TO_LIVE = "messageTimeToLiveInSec"; |
|
||||
private final String LOCK_DURATION = "lockDurationInSec"; |
|
||||
|
|
||||
private final Map<String, String> queueConfigs; |
|
||||
private final Set<String> queues = ConcurrentHashMap.newKeySet(); |
|
||||
|
|
||||
private final ManagementClient client; |
|
||||
|
|
||||
public TbServiceBusAdmin(TbServiceBusSettings serviceBusSettings, Map<String, String> queueConfigs) { |
|
||||
this.queueConfigs = queueConfigs; |
|
||||
|
|
||||
ConnectionStringBuilder builder = new ConnectionStringBuilder( |
|
||||
serviceBusSettings.getNamespaceName(), |
|
||||
"queues", |
|
||||
serviceBusSettings.getSasKeyName(), |
|
||||
serviceBusSettings.getSasKey()); |
|
||||
|
|
||||
client = new ManagementClient(builder); |
|
||||
|
|
||||
try { |
|
||||
client.getQueues().forEach(queueDescription -> queues.add(queueDescription.getPath())); |
|
||||
} catch (ServiceBusException | InterruptedException e) { |
|
||||
log.error("Failed to get queues.", e); |
|
||||
throw new RuntimeException("Failed to get queues.", e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void createTopicIfNotExists(String topic, String properties) { |
|
||||
if (queues.contains(topic)) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
QueueDescription queueDescription = new QueueDescription(topic); |
|
||||
queueDescription.setRequiresDuplicateDetection(false); |
|
||||
setQueueConfigs(queueDescription, PropertyUtils.getProps(queueConfigs, properties)); |
|
||||
|
|
||||
client.createQueue(queueDescription); |
|
||||
queues.add(topic); |
|
||||
} catch (ServiceBusException | InterruptedException e) { |
|
||||
if (e instanceof MessagingEntityAlreadyExistsException) { |
|
||||
queues.add(topic); |
|
||||
log.info("[{}] queue already exists.", topic); |
|
||||
} else { |
|
||||
log.error("Failed to create queue: [{}]", topic, e); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void deleteTopic(String topic) { |
|
||||
if (queues.contains(topic)) { |
|
||||
doDelete(topic); |
|
||||
} else { |
|
||||
try { |
|
||||
if (client.getQueue(topic) != null) { |
|
||||
doDelete(topic); |
|
||||
} else { |
|
||||
log.warn("Azure Service Bus Queue [{}] is not exist.", topic); |
|
||||
} |
|
||||
} catch (ServiceBusException | InterruptedException e) { |
|
||||
log.error("Failed to delete Azure Service Bus queue [{}]", topic, e); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void doDelete(String topic) { |
|
||||
try { |
|
||||
client.deleteTopic(topic); |
|
||||
} catch (ServiceBusException | InterruptedException e) { |
|
||||
log.error("Failed to delete Azure Service Bus queue [{}]", topic, e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void setQueueConfigs(QueueDescription queueDescription, Map<String, String> queueConfigs) { |
|
||||
queueConfigs.forEach((confKey, confValue) -> { |
|
||||
switch (confKey) { |
|
||||
case MAX_SIZE: |
|
||||
queueDescription.setMaxSizeInMB(Long.parseLong(confValue)); |
|
||||
break; |
|
||||
case MESSAGE_TIME_TO_LIVE: |
|
||||
queueDescription.setDefaultMessageTimeToLive(Duration.ofSeconds(Long.parseLong(confValue))); |
|
||||
break; |
|
||||
case LOCK_DURATION: |
|
||||
queueDescription.setLockDuration(Duration.ofSeconds(Long.parseLong(confValue))); |
|
||||
break; |
|
||||
default: |
|
||||
log.error("Unknown config: [{}]", confKey); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
public void destroy() { |
|
||||
try { |
|
||||
client.close(); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to close ManagementClient."); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,175 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.azure.servicebus; |
|
||||
|
|
||||
import com.google.gson.Gson; |
|
||||
import com.google.protobuf.InvalidProtocolBufferException; |
|
||||
import com.microsoft.azure.servicebus.TransactionContext; |
|
||||
import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder; |
|
||||
import com.microsoft.azure.servicebus.primitives.CoreMessageReceiver; |
|
||||
import com.microsoft.azure.servicebus.primitives.MessageWithDeliveryTag; |
|
||||
import com.microsoft.azure.servicebus.primitives.MessagingEntityType; |
|
||||
import com.microsoft.azure.servicebus.primitives.MessagingFactory; |
|
||||
import com.microsoft.azure.servicebus.primitives.SettleModePair; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.apache.qpid.proton.amqp.messaging.Data; |
|
||||
import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; |
|
||||
import org.apache.qpid.proton.amqp.transport.SenderSettleMode; |
|
||||
import org.springframework.util.CollectionUtils; |
|
||||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueMsgDecoder; |
|
||||
import org.thingsboard.server.queue.common.AbstractTbQueueConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|
||||
|
|
||||
import java.time.Duration; |
|
||||
import java.util.Collection; |
|
||||
import java.util.Collections; |
|
||||
import java.util.HashSet; |
|
||||
import java.util.List; |
|
||||
import java.util.Map; |
|
||||
import java.util.Set; |
|
||||
import java.util.concurrent.CompletableFuture; |
|
||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||
import java.util.concurrent.ExecutionException; |
|
||||
import java.util.stream.Collectors; |
|
||||
import java.util.stream.Stream; |
|
||||
|
|
||||
@Slf4j |
|
||||
public class TbServiceBusConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQueueConsumerTemplate<MessageWithDeliveryTag, T> { |
|
||||
private final TbQueueAdmin admin; |
|
||||
private final TbQueueMsgDecoder<T> decoder; |
|
||||
private final TbServiceBusSettings serviceBusSettings; |
|
||||
|
|
||||
private final Gson gson = new Gson(); |
|
||||
|
|
||||
private Set<CoreMessageReceiver> receivers; |
|
||||
private final Map<CoreMessageReceiver, Collection<MessageWithDeliveryTag>> pendingMessages = new ConcurrentHashMap<>(); |
|
||||
private volatile int messagesPerQueue; |
|
||||
|
|
||||
public TbServiceBusConsumerTemplate(TbQueueAdmin admin, TbServiceBusSettings serviceBusSettings, String topic, TbQueueMsgDecoder<T> decoder) { |
|
||||
super(topic); |
|
||||
this.admin = admin; |
|
||||
this.decoder = decoder; |
|
||||
this.serviceBusSettings = serviceBusSettings; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected List<MessageWithDeliveryTag> doPoll(long durationInMillis) { |
|
||||
List<CompletableFuture<Collection<MessageWithDeliveryTag>>> messageFutures = |
|
||||
receivers.stream() |
|
||||
.map(receiver -> receiver |
|
||||
.receiveAsync(messagesPerQueue, Duration.ofMillis(durationInMillis)) |
|
||||
.whenComplete((messages, err) -> { |
|
||||
if (!CollectionUtils.isEmpty(messages)) { |
|
||||
pendingMessages.put(receiver, messages); |
|
||||
} else if (err != null) { |
|
||||
log.error("Failed to receive messages.", err); |
|
||||
} |
|
||||
})) |
|
||||
.collect(Collectors.toList()); |
|
||||
try { |
|
||||
return fromList(messageFutures) |
|
||||
.get() |
|
||||
.stream() |
|
||||
.flatMap(messages -> CollectionUtils.isEmpty(messages) ? Stream.empty() : messages.stream()) |
|
||||
.collect(Collectors.toList()); |
|
||||
} catch (InterruptedException | ExecutionException e) { |
|
||||
if (stopped) { |
|
||||
log.info("[{}] Service Bus consumer is stopped.", getTopic()); |
|
||||
} else { |
|
||||
log.error("Failed to receive messages", e); |
|
||||
} |
|
||||
return Collections.emptyList(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doSubscribe(List<String> topicNames) { |
|
||||
createReceivers(); |
|
||||
messagesPerQueue = receivers.size() / Math.max(partitions.size(), 1); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doCommit() { |
|
||||
pendingMessages.forEach((receiver, msgs) -> |
|
||||
msgs.forEach(msg -> receiver.completeMessageAsync(msg.getDeliveryTag(), TransactionContext.NULL_TXN))); |
|
||||
pendingMessages.clear(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doUnsubscribe() { |
|
||||
receivers.forEach(CoreMessageReceiver::closeAsync); |
|
||||
} |
|
||||
|
|
||||
private void createReceivers() { |
|
||||
List<CompletableFuture<CoreMessageReceiver>> receiverFutures = partitions.stream() |
|
||||
.map(TopicPartitionInfo::getFullTopicName) |
|
||||
.map(queue -> { |
|
||||
MessagingFactory factory; |
|
||||
try { |
|
||||
factory = MessagingFactory.createFromConnectionStringBuilder(createConnection(queue)); |
|
||||
} catch (InterruptedException | ExecutionException e) { |
|
||||
log.error("Failed to create factory for the queue [{}]", queue); |
|
||||
throw new RuntimeException("Failed to create the factory", e); |
|
||||
} |
|
||||
|
|
||||
return CoreMessageReceiver.create(factory, queue, queue, 0, |
|
||||
new SettleModePair(SenderSettleMode.UNSETTLED, ReceiverSettleMode.SECOND), |
|
||||
MessagingEntityType.QUEUE); |
|
||||
}).collect(Collectors.toList()); |
|
||||
|
|
||||
try { |
|
||||
receivers = new HashSet<>(fromList(receiverFutures).get()); |
|
||||
} catch (InterruptedException | ExecutionException e) { |
|
||||
if (stopped) { |
|
||||
log.info("[{}] Service Bus consumer is stopped.", getTopic()); |
|
||||
} else { |
|
||||
log.error("Failed to create receivers", e); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private ConnectionStringBuilder createConnection(String queue) { |
|
||||
admin.createTopicIfNotExists(queue); |
|
||||
return new ConnectionStringBuilder( |
|
||||
serviceBusSettings.getNamespaceName(), |
|
||||
queue, |
|
||||
serviceBusSettings.getSasKeyName(), |
|
||||
serviceBusSettings.getSasKey()); |
|
||||
} |
|
||||
|
|
||||
private <V> CompletableFuture<List<V>> fromList(List<CompletableFuture<V>> futures) { |
|
||||
@SuppressWarnings("unchecked") |
|
||||
CompletableFuture<Collection<V>>[] arrayFuture = new CompletableFuture[futures.size()]; |
|
||||
futures.toArray(arrayFuture); |
|
||||
|
|
||||
return CompletableFuture |
|
||||
.allOf(arrayFuture) |
|
||||
.thenApply(v -> futures |
|
||||
.stream() |
|
||||
.map(CompletableFuture::join) |
|
||||
.collect(Collectors.toList())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected T decode(MessageWithDeliveryTag data) throws InvalidProtocolBufferException { |
|
||||
DefaultTbQueueMsg msg = gson.fromJson(new String(((Data) data.getMessage().getBody()).getValue().getArray()), DefaultTbQueueMsg.class); |
|
||||
return decoder.decode(msg); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,110 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.azure.servicebus; |
|
||||
|
|
||||
import com.google.gson.Gson; |
|
||||
import com.microsoft.azure.servicebus.IMessage; |
|
||||
import com.microsoft.azure.servicebus.Message; |
|
||||
import com.microsoft.azure.servicebus.QueueClient; |
|
||||
import com.microsoft.azure.servicebus.ReceiveMode; |
|
||||
import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder; |
|
||||
import com.microsoft.azure.servicebus.primitives.ServiceBusException; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueCallback; |
|
||||
import org.thingsboard.server.queue.TbQueueMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|
||||
|
|
||||
import java.util.Map; |
|
||||
import java.util.concurrent.CompletableFuture; |
|
||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||
import java.util.concurrent.ExecutorService; |
|
||||
import java.util.concurrent.Executors; |
|
||||
|
|
||||
@Slf4j |
|
||||
public class TbServiceBusProducerTemplate<T extends TbQueueMsg> implements TbQueueProducer<T> { |
|
||||
private final String defaultTopic; |
|
||||
private final Gson gson = new Gson(); |
|
||||
private final TbQueueAdmin admin; |
|
||||
private final TbServiceBusSettings serviceBusSettings; |
|
||||
private final Map<String, QueueClient> clients = new ConcurrentHashMap<>(); |
|
||||
private final ExecutorService executorService; |
|
||||
|
|
||||
public TbServiceBusProducerTemplate(TbQueueAdmin admin, TbServiceBusSettings serviceBusSettings, String defaultTopic) { |
|
||||
this.admin = admin; |
|
||||
this.defaultTopic = defaultTopic; |
|
||||
this.serviceBusSettings = serviceBusSettings; |
|
||||
executorService = Executors.newCachedThreadPool(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void init() { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public String getDefaultTopic() { |
|
||||
return defaultTopic; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) { |
|
||||
IMessage message = new Message(gson.toJson(new DefaultTbQueueMsg(msg))); |
|
||||
CompletableFuture<Void> future = getClient(tpi.getFullTopicName()).sendAsync(message); |
|
||||
future.whenCompleteAsync((success, err) -> { |
|
||||
if (err != null) { |
|
||||
callback.onFailure(err); |
|
||||
} else { |
|
||||
callback.onSuccess(null); |
|
||||
} |
|
||||
}, executorService); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void stop() { |
|
||||
clients.forEach((t, client) -> { |
|
||||
try { |
|
||||
client.close(); |
|
||||
} catch (ServiceBusException e) { |
|
||||
log.error("Failed to close QueueClient.", e); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
if (executorService != null) { |
|
||||
executorService.shutdownNow(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private QueueClient getClient(String topic) { |
|
||||
return clients.computeIfAbsent(topic, k -> { |
|
||||
admin.createTopicIfNotExists(topic); |
|
||||
ConnectionStringBuilder builder = |
|
||||
new ConnectionStringBuilder( |
|
||||
serviceBusSettings.getNamespaceName(), |
|
||||
topic, |
|
||||
serviceBusSettings.getSasKeyName(), |
|
||||
serviceBusSettings.getSasKey()); |
|
||||
try { |
|
||||
return new QueueClient(builder, ReceiveMode.PEEKLOCK); |
|
||||
} catch (InterruptedException | ServiceBusException e) { |
|
||||
log.error("Failed to create new client for the Queue: [{}]", topic, e); |
|
||||
throw new RuntimeException("Failed to create new client for the Queue", e); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
@ -1,72 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.azure.servicebus; |
|
||||
|
|
||||
import jakarta.annotation.PostConstruct; |
|
||||
import lombok.Getter; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.queue.util.PropertyUtils; |
|
||||
|
|
||||
import java.util.Map; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='service-bus'") |
|
||||
public class TbServiceBusQueueConfigs { |
|
||||
|
|
||||
@Value("${queue.service-bus.queue-properties.core:}") |
|
||||
private String coreProperties; |
|
||||
@Value("${queue.service-bus.queue-properties.rule-engine:}") |
|
||||
private String ruleEngineProperties; |
|
||||
@Value("${queue.service-bus.queue-properties.transport-api:}") |
|
||||
private String transportApiProperties; |
|
||||
@Value("${queue.service-bus.queue-properties.notifications:}") |
|
||||
private String notificationsProperties; |
|
||||
@Value("${queue.service-bus.queue-properties.js-executor:}") |
|
||||
private String jsExecutorProperties; |
|
||||
@Value("${queue.service-bus.queue-properties.version-control:}") |
|
||||
private String vcProperties; |
|
||||
@Value("${queue.service-bus.queue-properties.edge:}") |
|
||||
private String edgeProperties; |
|
||||
|
|
||||
@Getter |
|
||||
private Map<String, String> coreConfigs; |
|
||||
@Getter |
|
||||
private Map<String, String> ruleEngineConfigs; |
|
||||
@Getter |
|
||||
private Map<String, String> transportApiConfigs; |
|
||||
@Getter |
|
||||
private Map<String, String> notificationsConfigs; |
|
||||
@Getter |
|
||||
private Map<String, String> jsExecutorConfigs; |
|
||||
@Getter |
|
||||
private Map<String, String> vcConfigs; |
|
||||
@Getter |
|
||||
private Map<String, String> edgeConfigs; |
|
||||
|
|
||||
@PostConstruct |
|
||||
private void init() { |
|
||||
coreConfigs = PropertyUtils.getProps(coreProperties); |
|
||||
ruleEngineConfigs = PropertyUtils.getProps(ruleEngineProperties); |
|
||||
transportApiConfigs = PropertyUtils.getProps(transportApiProperties); |
|
||||
notificationsConfigs = PropertyUtils.getProps(notificationsProperties); |
|
||||
jsExecutorConfigs = PropertyUtils.getProps(jsExecutorProperties); |
|
||||
vcConfigs = PropertyUtils.getProps(vcProperties); |
|
||||
edgeConfigs = PropertyUtils.getProps(edgeProperties); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,37 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.azure.servicebus; |
|
||||
|
|
||||
import lombok.Data; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
@Slf4j |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='service-bus'") |
|
||||
@Component |
|
||||
@Data |
|
||||
public class TbServiceBusSettings { |
|
||||
@Value("${queue.service_bus.namespace_name}") |
|
||||
private String namespaceName; |
|
||||
@Value("${queue.service_bus.sas_key_name}") |
|
||||
private String sasKeyName; |
|
||||
@Value("${queue.service_bus.sas_key}") |
|
||||
private String sasKey; |
|
||||
@Value("${queue.service_bus.max_messages}") |
|
||||
private int maxMessages; |
|
||||
} |
|
||||
@ -1,317 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.queue.Queue; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeEventNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsAdmin; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && '${service.type:null}'=='monolith'") |
|
||||
public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngineQueueFactory, TbVersionControlQueueFactory { |
|
||||
|
|
||||
private final TopicService topicService; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbAwsSqsSettings sqsSettings; |
|
||||
private final TbQueueVersionControlSettings vcSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin otaAdmin; |
|
||||
private final TbQueueAdmin vcAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public AwsSqsMonolithQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbAwsSqsSettings sqsSettings, |
|
||||
TbQueueVersionControlSettings vcSettings, |
|
||||
TbQueueEdgeSettings edgeSettings, |
|
||||
TbAwsSqsQueueAttributes sqsQueueAttributes, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings) { |
|
||||
this.topicService = topicService; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.sqsSettings = sqsSettings; |
|
||||
this.vcSettings = vcSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); |
|
||||
this.ruleEngineAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getRuleEngineAttributes()); |
|
||||
this.jsExecutorAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getJsExecutorAttributes()); |
|
||||
this.transportApiAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getTransportApiAttributes()); |
|
||||
this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); |
|
||||
this.otaAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getOtaAttributes()); |
|
||||
this.vcAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getVcAttributes()); |
|
||||
this.edgeAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getEdgeAttributes()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|
||||
return new TbAwsSqsConsumerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(configuration.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(transportApiAdmin, sqsSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<RemoteJsRequest>, TbProtoQueueMsg<RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<RemoteJsRequest>> producer = new TbAwsSqsProducerTemplate<>(jsExecutorAdmin, sqsSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<RemoteJsResponse>> consumer = new TbAwsSqsConsumerTemplate<>(jsExecutorAdmin, sqsSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "_" + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
RemoteJsResponse.Builder builder = RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<RemoteJsRequest>, TbProtoQueueMsg<RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeEventNotificationMsg>> createEdgeEventMsgProducer() { |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (otaAdmin != null) { |
|
||||
otaAdmin.destroy(); |
|
||||
} |
|
||||
if (vcAdmin != null) { |
|
||||
vcAdmin.destroy(); |
|
||||
} |
|
||||
if (edgeAdmin != null) { |
|
||||
edgeAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,291 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsAdmin; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && '${service.type:null}'=='tb-core'") |
|
||||
public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory { |
|
||||
|
|
||||
private final TbAwsSqsSettings sqsSettings; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TopicService topicService; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbQueueVersionControlSettings vcSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin otaAdmin; |
|
||||
private final TbQueueAdmin vcAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public AwsSqsTbCoreQueueFactory(TbAwsSqsSettings sqsSettings, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TopicService topicService, |
|
||||
TbQueueVersionControlSettings vcSettings, |
|
||||
TbQueueEdgeSettings edgeSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbAwsSqsQueueAttributes sqsQueueAttributes, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings) { |
|
||||
this.sqsSettings = sqsSettings; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
this.topicService = topicService; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.vcSettings = vcSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); |
|
||||
this.ruleEngineAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getRuleEngineAttributes()); |
|
||||
this.jsExecutorAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getJsExecutorAttributes()); |
|
||||
this.transportApiAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getTransportApiAttributes()); |
|
||||
this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); |
|
||||
this.otaAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getOtaAttributes()); |
|
||||
this.vcAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getVcAttributes()); |
|
||||
this.edgeAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getEdgeAttributes()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(transportApiAdmin, sqsSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbAwsSqsProducerTemplate<>(jsExecutorAdmin, sqsSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbAwsSqsConsumerTemplate<>(jsExecutorAdmin, sqsSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "_" + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (otaAdmin != null) { |
|
||||
otaAdmin.destroy(); |
|
||||
} |
|
||||
if (vcAdmin != null) { |
|
||||
vcAdmin.destroy(); |
|
||||
} |
|
||||
if (edgeAdmin != null) { |
|
||||
edgeAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,208 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.queue.Queue; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsAdmin; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && '${service.type:null}'=='tb-rule-engine'") |
|
||||
public class AwsSqsTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { |
|
||||
|
|
||||
private final TopicService topicService; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbAwsSqsSettings sqsSettings; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin otaAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public AwsSqsTbRuleEngineQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbAwsSqsSettings sqsSettings, |
|
||||
TbAwsSqsQueueAttributes sqsQueueAttributes, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbQueueEdgeSettings edgeSettings) { |
|
||||
this.topicService = topicService; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.sqsSettings = sqsSettings; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); |
|
||||
this.ruleEngineAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getRuleEngineAttributes()); |
|
||||
this.jsExecutorAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getJsExecutorAttributes()); |
|
||||
this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); |
|
||||
this.otaAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getOtaAttributes()); |
|
||||
this.edgeAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getEdgeAttributes()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(edgeAdmin, sqsSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|
||||
return new TbAwsSqsConsumerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(configuration.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbAwsSqsProducerTemplate<>(jsExecutorAdmin, sqsSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbAwsSqsConsumerTemplate<>(jsExecutorAdmin, sqsSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "_" + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(otaAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (otaAdmin != null) { |
|
||||
otaAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,98 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsAdmin; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && '${service.type:null}'=='tb-vc-executor'") |
|
||||
public class AwsSqsTbVersionControlQueueFactory implements TbVersionControlQueueFactory { |
|
||||
|
|
||||
private final TbAwsSqsSettings sqsSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueVersionControlSettings vcSettings; |
|
||||
private final TopicService topicService; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin vcAdmin; |
|
||||
|
|
||||
public AwsSqsTbVersionControlQueueFactory(TbAwsSqsSettings sqsSettings, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueVersionControlSettings vcSettings, |
|
||||
TbAwsSqsQueueAttributes sqsQueueAttributes, |
|
||||
TopicService topicService |
|
||||
) { |
|
||||
this.sqsSettings = sqsSettings; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.vcSettings = vcSettings; |
|
||||
this.topicService = topicService; |
|
||||
|
|
||||
this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); |
|
||||
this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); |
|
||||
this.vcAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getVcAttributes()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(vcAdmin, sqsSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (vcAdmin != null) { |
|
||||
vcAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,153 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsAdmin; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; |
|
||||
import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && (('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport')") |
|
||||
@Slf4j |
|
||||
public class AwsSqsTransportQueueFactory implements TbTransportQueueFactory { |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbAwsSqsSettings sqsSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TopicService topicService; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
|
|
||||
public AwsSqsTransportQueueFactory(TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbAwsSqsSettings sqsSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbAwsSqsQueueAttributes sqsQueueAttributes, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TopicService topicService) { |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.sqsSettings = sqsSettings; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.topicService = topicService; |
|
||||
|
|
||||
this.coreAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getCoreAttributes()); |
|
||||
this.transportApiAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getTransportApiAttributes()); |
|
||||
this.notificationAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getNotificationsAttributes()); |
|
||||
this.ruleEngineAdmin = new TbAwsSqsAdmin(sqsSettings, sqsQueueAttributes.getRuleEngineAttributes()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueRequestTemplate<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoQueueMsg<TransportApiRequestMsg>> producerTemplate = |
|
||||
new TbAwsSqsProducerTemplate<>(transportApiAdmin, sqsSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic())); |
|
||||
|
|
||||
TbQueueConsumer<TbProtoQueueMsg<TransportApiResponseMsg>> consumerTemplate = |
|
||||
new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, |
|
||||
topicService.buildTopicName(transportApiSettings.getResponsesTopic() + "_" + serviceInfoProvider.getServiceId()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiResponseMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> templateBuilder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
templateBuilder.queueAdmin(transportApiAdmin); |
|
||||
templateBuilder.requestTemplate(producerTemplate); |
|
||||
templateBuilder.responseTemplate(consumerTemplate); |
|
||||
templateBuilder.maxPendingRequests(transportApiSettings.getMaxPendingRequests()); |
|
||||
templateBuilder.maxRequestTimeout(transportApiSettings.getMaxRequestsTimeout()); |
|
||||
templateBuilder.pollInterval(transportApiSettings.getResponsePollInterval()); |
|
||||
return templateBuilder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(ruleEngineAdmin, sqsSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsConsumer() { |
|
||||
return new TbAwsSqsConsumerTemplate<>(notificationAdmin, sqsSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic() + "_" + serviceInfoProvider.getServiceId()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToTransportMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,315 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.queue.Queue; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeEventNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubAdmin; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubSettings; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='pubsub' && '${service.type:null}'=='monolith'") |
|
||||
public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngineQueueFactory, TbVersionControlQueueFactory { |
|
||||
|
|
||||
private final TbPubSubSettings pubSubSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TopicService topicService; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueVersionControlSettings vcSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin vcAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public PubSubMonolithQueueFactory(TbPubSubSettings pubSubSettings, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TopicService topicService, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbPubSubSubscriptionSettings pubSubSubscriptionSettings, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbQueueVersionControlSettings vcSettings, |
|
||||
TbQueueEdgeSettings edgeSettings) { |
|
||||
this.pubSubSettings = pubSubSettings; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.topicService = topicService; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.vcSettings = vcSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); |
|
||||
this.ruleEngineAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getRuleEngineSettings()); |
|
||||
this.jsExecutorAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getJsExecutorSettings()); |
|
||||
this.transportApiAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getTransportApiSettings()); |
|
||||
this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); |
|
||||
this.vcAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getVcSettings()); |
|
||||
this.edgeAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getEdgeSettings()); |
|
||||
|
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(ruleEngineAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(vcAdmin, pubSubSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|
||||
return new TbPubSubConsumerTemplate<>(ruleEngineAdmin, pubSubSettings, topicService.buildTopicName(configuration.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(transportApiAdmin, pubSubSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(transportApiAdmin, pubSubSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<RemoteJsRequest>, TbProtoQueueMsg<RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<RemoteJsRequest>> producer = new TbPubSubProducerTemplate<>(jsExecutorAdmin, pubSubSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<RemoteJsResponse>> consumer = new TbPubSubConsumerTemplate<>(jsExecutorAdmin, pubSubSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
RemoteJsResponse.Builder builder = RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<RemoteJsRequest>, TbProtoQueueMsg<RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(vcAdmin, pubSubSettings, topicService.buildTopicName(vcSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeEventNotificationMsg>> createEdgeEventMsgProducer() { |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (vcAdmin != null) { |
|
||||
vcAdmin.destroy(); |
|
||||
} |
|
||||
if (edgeAdmin != null) { |
|
||||
edgeAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,278 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubAdmin; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubSettings; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='pubsub' && '${service.type:null}'=='tb-core'") |
|
||||
public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory { |
|
||||
|
|
||||
private final TbPubSubSettings pubSubSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TopicService topicService; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public PubSubTbCoreQueueFactory(TbPubSubSettings pubSubSettings, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueTransportApiSettings transportApiSettings, |
|
||||
TopicService topicService, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbQueueEdgeSettings edgeSettings, |
|
||||
TbPubSubSubscriptionSettings pubSubSubscriptionSettings) { |
|
||||
this.pubSubSettings = pubSubSettings; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.topicService = topicService; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); |
|
||||
this.jsExecutorAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getJsExecutorSettings()); |
|
||||
this.transportApiAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getTransportApiSettings()); |
|
||||
this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); |
|
||||
this.ruleEngineAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getRuleEngineSettings()); |
|
||||
this.edgeAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getEdgeSettings()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(transportApiAdmin, pubSubSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(transportApiAdmin, pubSubSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbPubSubProducerTemplate<>(jsExecutorAdmin, pubSubSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbPubSubConsumerTemplate<>(jsExecutorAdmin, pubSubSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|
||||
//TODO: version-control
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (edgeAdmin != null) { |
|
||||
edgeAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,209 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.queue.Queue; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeEventNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubAdmin; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubSettings; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='pubsub' && '${service.type:null}'=='tb-rule-engine'") |
|
||||
public class PubSubTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { |
|
||||
|
|
||||
private final TbPubSubSettings pubSubSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TopicService topicService; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public PubSubTbRuleEngineQueueFactory(TbPubSubSettings pubSubSettings, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TopicService topicService, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbPubSubSubscriptionSettings pubSubSubscriptionSettings, |
|
||||
TbQueueEdgeSettings edgeSettings) { |
|
||||
this.pubSubSettings = pubSubSettings; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.topicService = topicService; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); |
|
||||
this.ruleEngineAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getRuleEngineSettings()); |
|
||||
this.jsExecutorAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getJsExecutorSettings()); |
|
||||
this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); |
|
||||
this.edgeAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getEdgeSettings()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(ruleEngineAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(edgeAdmin, pubSubSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeEventNotificationMsg>> createEdgeEventMsgProducer() { |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|
||||
return new TbPubSubConsumerTemplate<>(ruleEngineAdmin, pubSubSettings, topicService.buildTopicName(configuration.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbPubSubProducerTemplate<>(jsExecutorAdmin, pubSubSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbPubSubConsumerTemplate<>(jsExecutorAdmin, pubSubSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,98 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubAdmin; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubSettings; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='pubsub' && '${service.type:null}'=='tb-vc-executor'") |
|
||||
public class PubSubTbVersionControlQueueFactory implements TbVersionControlQueueFactory { |
|
||||
|
|
||||
private final TbPubSubSettings pubSubSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueVersionControlSettings vcSettings; |
|
||||
private final TopicService topicService; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin vcAdmin; |
|
||||
|
|
||||
public PubSubTbVersionControlQueueFactory(TbPubSubSettings pubSubSettings, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueVersionControlSettings vcSettings, |
|
||||
TbPubSubSubscriptionSettings pubSubSubscriptionSettings, |
|
||||
TopicService topicService |
|
||||
) { |
|
||||
this.pubSubSettings = pubSubSettings; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.vcSettings = vcSettings; |
|
||||
this.topicService = topicService; |
|
||||
|
|
||||
this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); |
|
||||
this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); |
|
||||
this.vcAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getVcSettings()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(vcAdmin, pubSubSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (vcAdmin != null) { |
|
||||
vcAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,153 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubAdmin; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubProducerTemplate; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubSettings; |
|
||||
import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='pubsub' && (('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport')") |
|
||||
@Slf4j |
|
||||
public class PubSubTransportQueueFactory implements TbTransportQueueFactory { |
|
||||
|
|
||||
private final TbPubSubSettings pubSubSettings; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TopicService topicService; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
|
|
||||
public PubSubTransportQueueFactory(TbPubSubSettings pubSubSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbPubSubSubscriptionSettings pubSubSubscriptionSettings, |
|
||||
TopicService topicService) { |
|
||||
this.pubSubSettings = pubSubSettings; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.topicService = topicService; |
|
||||
|
|
||||
this.coreAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getCoreSettings()); |
|
||||
this.ruleEngineAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getRuleEngineSettings()); |
|
||||
this.transportApiAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getTransportApiSettings()); |
|
||||
this.notificationAdmin = new TbPubSubAdmin(pubSubSettings, pubSubSubscriptionSettings.getNotificationsSettings()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueRequestTemplate<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoQueueMsg<TransportApiRequestMsg>> producer = new TbPubSubProducerTemplate<>(transportApiAdmin, pubSubSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic())); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<TransportApiResponseMsg>> consumer = new TbPubSubConsumerTemplate<>(transportApiAdmin, pubSubSettings, |
|
||||
topicService.buildTopicName(transportApiSettings.getResponsesTopic() + "." + serviceInfoProvider.getServiceId()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiResponseMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> templateBuilder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
templateBuilder.queueAdmin(transportApiAdmin); |
|
||||
templateBuilder.requestTemplate(producer); |
|
||||
templateBuilder.responseTemplate(consumer); |
|
||||
templateBuilder.maxPendingRequests(transportApiSettings.getMaxPendingRequests()); |
|
||||
templateBuilder.maxRequestTimeout(transportApiSettings.getMaxRequestsTimeout()); |
|
||||
templateBuilder.pollInterval(transportApiSettings.getResponsePollInterval()); |
|
||||
return templateBuilder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(ruleEngineAdmin, pubSubSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(notificationAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsConsumer() { |
|
||||
return new TbPubSubConsumerTemplate<>(notificationAdmin, pubSubSettings, |
|
||||
topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic() + "." + serviceInfoProvider.getServiceId()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToTransportMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,313 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.queue.Queue; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeEventNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqAdmin; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqQueueArguments; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && '${service.type:null}'=='monolith'") |
|
||||
public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngineQueueFactory, TbVersionControlQueueFactory { |
|
||||
|
|
||||
private final TopicService topicService; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbRabbitMqSettings rabbitMqSettings; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueVersionControlSettings vcSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin vcAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public RabbitMqMonolithQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbRabbitMqSettings rabbitMqSettings, |
|
||||
TbRabbitMqQueueArguments queueArguments, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbQueueVersionControlSettings vcSettings, |
|
||||
TbQueueEdgeSettings edgeSettings) { |
|
||||
this.topicService = topicService; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.rabbitMqSettings = rabbitMqSettings; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
this.vcSettings = vcSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getCoreArgs()); |
|
||||
this.ruleEngineAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getRuleEngineArgs()); |
|
||||
this.jsExecutorAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getJsExecutorArgs()); |
|
||||
this.transportApiAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getTransportApiArgs()); |
|
||||
this.notificationAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getNotificationsArgs()); |
|
||||
this.vcAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getVcArgs()); |
|
||||
this.edgeAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getEdgeArgs()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(ruleEngineAdmin, rabbitMqSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(vcAdmin, rabbitMqSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|
||||
return new TbRabbitMqConsumerTemplate<>(ruleEngineAdmin, rabbitMqSettings, topicService.buildTopicName(configuration.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(notificationAdmin, rabbitMqSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(notificationAdmin, rabbitMqSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(transportApiAdmin, rabbitMqSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(transportApiAdmin, rabbitMqSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<RemoteJsRequest>, TbProtoQueueMsg<RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<RemoteJsRequest>> producer = new TbRabbitMqProducerTemplate<>(jsExecutorAdmin, rabbitMqSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<RemoteJsResponse>> consumer = new TbRabbitMqConsumerTemplate<>(jsExecutorAdmin, rabbitMqSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
RemoteJsResponse.Builder builder = RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<RemoteJsRequest>, TbProtoQueueMsg<RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(vcAdmin, rabbitMqSettings, topicService.buildTopicName(vcSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(edgeAdmin, rabbitMqSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(edgeAdmin, rabbitMqSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(notificationAdmin, rabbitMqSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeEventNotificationMsg>> createEdgeEventMsgProducer() { |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (vcAdmin != null) { |
|
||||
vcAdmin.destroy(); |
|
||||
} |
|
||||
if (edgeAdmin != null) { |
|
||||
edgeAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,278 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqAdmin; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqQueueArguments; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && '${service.type:null}'=='tb-core'") |
|
||||
public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory { |
|
||||
|
|
||||
private final TbRabbitMqSettings rabbitMqSettings; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TopicService topicService; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public RabbitMqTbCoreQueueFactory(TbRabbitMqSettings rabbitMqSettings, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TopicService topicService, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbQueueEdgeSettings edgeSettings, |
|
||||
TbRabbitMqQueueArguments queueArguments) { |
|
||||
this.rabbitMqSettings = rabbitMqSettings; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.topicService = topicService; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getCoreArgs()); |
|
||||
this.ruleEngineAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getRuleEngineArgs()); |
|
||||
this.jsExecutorAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getJsExecutorArgs()); |
|
||||
this.transportApiAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getTransportApiArgs()); |
|
||||
this.notificationAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getNotificationsArgs()); |
|
||||
this.edgeAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getEdgeArgs()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(notificationAdmin, rabbitMqSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(edgeAdmin, rabbitMqSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(edgeAdmin, rabbitMqSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(notificationAdmin, rabbitMqSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(transportApiAdmin, rabbitMqSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(transportApiAdmin, rabbitMqSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbRabbitMqProducerTemplate<>(jsExecutorAdmin, rabbitMqSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbRabbitMqConsumerTemplate<>(jsExecutorAdmin, rabbitMqSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|
||||
//TODO: version-control
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (edgeAdmin != null) { |
|
||||
edgeAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,202 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.queue.Queue; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqAdmin; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqQueueArguments; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && '${service.type:null}'=='tb-rule-engine'") |
|
||||
public class RabbitMqTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { |
|
||||
|
|
||||
private final TopicService topicService; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbRabbitMqSettings rabbitMqSettings; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public RabbitMqTbRuleEngineQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbRabbitMqSettings rabbitMqSettings, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbQueueEdgeSettings edgeSettings, |
|
||||
TbRabbitMqQueueArguments queueArguments) { |
|
||||
this.topicService = topicService; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.rabbitMqSettings = rabbitMqSettings; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getCoreArgs()); |
|
||||
this.ruleEngineAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getRuleEngineArgs()); |
|
||||
this.jsExecutorAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getJsExecutorArgs()); |
|
||||
this.notificationAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getNotificationsArgs()); |
|
||||
this.edgeAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getEdgeArgs()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(ruleEngineAdmin, rabbitMqSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(edgeAdmin, rabbitMqSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|
||||
return new TbRabbitMqConsumerTemplate<>(ruleEngineAdmin, rabbitMqSettings, topicService.buildTopicName(configuration.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(notificationAdmin, rabbitMqSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbRabbitMqProducerTemplate<>(jsExecutorAdmin, rabbitMqSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbRabbitMqConsumerTemplate<>(jsExecutorAdmin, rabbitMqSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,98 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqAdmin; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqQueueArguments; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && '${service.type:null}'=='tb-vc-executor'") |
|
||||
public class RabbitMqTbVersionControlQueueFactory implements TbVersionControlQueueFactory { |
|
||||
|
|
||||
private final TbRabbitMqSettings rabbitMqSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueVersionControlSettings vcSettings; |
|
||||
private final TopicService topicService; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin vcAdmin; |
|
||||
|
|
||||
public RabbitMqTbVersionControlQueueFactory(TbRabbitMqSettings rabbitMqSettings, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueVersionControlSettings vcSettings, |
|
||||
TbRabbitMqQueueArguments queueArguments, |
|
||||
TopicService topicService |
|
||||
) { |
|
||||
this.rabbitMqSettings = rabbitMqSettings; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.vcSettings = vcSettings; |
|
||||
this.topicService = topicService; |
|
||||
|
|
||||
this.coreAdmin = new TbRabbitMqAdmin(this.rabbitMqSettings, queueArguments.getCoreArgs()); |
|
||||
this.notificationAdmin = new TbRabbitMqAdmin(this.rabbitMqSettings, queueArguments.getNotificationsArgs()); |
|
||||
this.vcAdmin = new TbRabbitMqAdmin(this.rabbitMqSettings, queueArguments.getVcArgs()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(vcAdmin, rabbitMqSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (vcAdmin != null) { |
|
||||
vcAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,154 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqAdmin; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqProducerTemplate; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqQueueArguments; |
|
||||
import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && (('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport')") |
|
||||
@Slf4j |
|
||||
public class RabbitMqTransportQueueFactory implements TbTransportQueueFactory { |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbRabbitMqSettings rabbitMqSettings; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TopicService topicService; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
|
|
||||
public RabbitMqTransportQueueFactory(TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbRabbitMqSettings rabbitMqSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbRabbitMqQueueArguments queueArguments, |
|
||||
TopicService topicService) { |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.rabbitMqSettings = rabbitMqSettings; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.topicService = topicService; |
|
||||
|
|
||||
this.coreAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getCoreArgs()); |
|
||||
this.ruleEngineAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getRuleEngineArgs()); |
|
||||
this.transportApiAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getTransportApiArgs()); |
|
||||
this.notificationAdmin = new TbRabbitMqAdmin(rabbitMqSettings, queueArguments.getNotificationsArgs()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueRequestTemplate<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoQueueMsg<TransportApiRequestMsg>> producerTemplate = |
|
||||
new TbRabbitMqProducerTemplate<>(transportApiAdmin, rabbitMqSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic())); |
|
||||
|
|
||||
TbQueueConsumer<TbProtoQueueMsg<TransportApiResponseMsg>> consumerTemplate = |
|
||||
new TbRabbitMqConsumerTemplate<>(transportApiAdmin, rabbitMqSettings, |
|
||||
topicService.buildTopicName(transportApiSettings.getResponsesTopic() + "." + serviceInfoProvider.getServiceId()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiResponseMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> templateBuilder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
templateBuilder.queueAdmin(transportApiAdmin); |
|
||||
templateBuilder.requestTemplate(producerTemplate); |
|
||||
templateBuilder.responseTemplate(consumerTemplate); |
|
||||
templateBuilder.maxPendingRequests(transportApiSettings.getMaxPendingRequests()); |
|
||||
templateBuilder.maxRequestTimeout(transportApiSettings.getMaxRequestsTimeout()); |
|
||||
templateBuilder.pollInterval(transportApiSettings.getResponsePollInterval()); |
|
||||
return templateBuilder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(ruleEngineAdmin, rabbitMqSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsConsumer() { |
|
||||
return new TbRabbitMqConsumerTemplate<>(notificationAdmin, rabbitMqSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic() + "." + serviceInfoProvider.getServiceId()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToTransportMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,312 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.queue.Queue; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeEventNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusAdmin; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusProducerTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusQueueConfigs; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusSettings; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='service-bus' && '${service.type:null}'=='monolith'") |
|
||||
public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngineQueueFactory, TbVersionControlQueueFactory { |
|
||||
|
|
||||
private final TopicService topicService; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbServiceBusSettings serviceBusSettings; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueVersionControlSettings vcSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin vcAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public ServiceBusMonolithQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbServiceBusSettings serviceBusSettings, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbQueueVersionControlSettings vcSettings, |
|
||||
TbQueueEdgeSettings edgeSettings, |
|
||||
TbServiceBusQueueConfigs serviceBusQueueConfigs) { |
|
||||
this.topicService = topicService; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.serviceBusSettings = serviceBusSettings; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
this.vcSettings = vcSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getCoreConfigs()); |
|
||||
this.ruleEngineAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getRuleEngineConfigs()); |
|
||||
this.jsExecutorAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getJsExecutorConfigs()); |
|
||||
this.transportApiAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getTransportApiConfigs()); |
|
||||
this.notificationAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getNotificationsConfigs()); |
|
||||
this.vcAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getVcConfigs()); |
|
||||
this.edgeAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getEdgeConfigs()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(ruleEngineAdmin, serviceBusSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(vcAdmin, serviceBusSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|
||||
return new TbServiceBusConsumerTemplate<>(ruleEngineAdmin, serviceBusSettings, configuration.getTopic(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(transportApiAdmin, serviceBusSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(transportApiAdmin, serviceBusSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbServiceBusProducerTemplate<>(jsExecutorAdmin, serviceBusSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbServiceBusConsumerTemplate<>(jsExecutorAdmin, serviceBusSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(vcAdmin, serviceBusSettings, topicService.buildTopicName(vcSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(edgeAdmin, serviceBusSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(edgeAdmin, serviceBusSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeEventNotificationMsg>> createEdgeEventMsgProducer() { |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (vcAdmin != null) { |
|
||||
vcAdmin.destroy(); |
|
||||
} |
|
||||
if (edgeAdmin != null) { |
|
||||
edgeAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,278 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusAdmin; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusProducerTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusQueueConfigs; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusSettings; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='service-bus' && '${service.type:null}'=='tb-core'") |
|
||||
public class ServiceBusTbCoreQueueFactory implements TbCoreQueueFactory { |
|
||||
|
|
||||
private final TbServiceBusSettings serviceBusSettings; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TopicService topicService; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public ServiceBusTbCoreQueueFactory(TbServiceBusSettings serviceBusSettings, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TopicService topicService, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbQueueEdgeSettings edgeSettings, |
|
||||
TbServiceBusQueueConfigs serviceBusQueueConfigs) { |
|
||||
this.serviceBusSettings = serviceBusSettings; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.topicService = topicService; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getCoreConfigs()); |
|
||||
this.ruleEngineAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getRuleEngineConfigs()); |
|
||||
this.jsExecutorAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getJsExecutorConfigs()); |
|
||||
this.transportApiAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getTransportApiConfigs()); |
|
||||
this.notificationAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getNotificationsConfigs()); |
|
||||
this.edgeAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getEdgeConfigs()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> createToCoreMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToCoreNotificationMsg>> createToCoreNotificationsMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_CORE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToCoreNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportApiRequestMsg>> createTransportApiRequestConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(transportApiAdmin, serviceBusSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiResponseProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(transportApiAdmin, serviceBusSettings, topicService.buildTopicName(transportApiSettings.getResponsesTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbServiceBusProducerTemplate<>(jsExecutorAdmin, serviceBusSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbServiceBusConsumerTemplate<>(jsExecutorAdmin, serviceBusSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToUsageStatsServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToVersionControlServiceMsg>> createVersionControlMsgProducer() { |
|
||||
//TODO: version-control
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperReprocessingMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperReprocessingTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToHousekeeperServiceMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(edgeAdmin, serviceBusSettings, topicService.buildTopicName(edgeSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(edgeAdmin, serviceBusSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createToEdgeNotificationsMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToEdgeNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (edgeAdmin != null) { |
|
||||
edgeAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,202 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import com.google.protobuf.util.JsonFormat; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.context.annotation.Bean; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.queue.Queue; |
|
||||
import org.thingsboard.server.common.msg.queue.ServiceType; |
|
||||
import org.thingsboard.server.gen.js.JsInvokeProtos; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToEdgeNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusAdmin; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusProducerTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusQueueConfigs; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusSettings; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueEdgeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
|
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='service-bus' && '${service.type:null}'=='tb-rule-engine'") |
|
||||
public class ServiceBusTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { |
|
||||
|
|
||||
private final TopicService topicService; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TbServiceBusSettings serviceBusSettings; |
|
||||
private final TbQueueRemoteJsInvokeSettings jsInvokeSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbQueueEdgeSettings edgeSettings; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
private final TbQueueAdmin jsExecutorAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin edgeAdmin; |
|
||||
|
|
||||
public ServiceBusTbRuleEngineQueueFactory(TopicService topicService, TbQueueCoreSettings coreSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbServiceBusSettings serviceBusSettings, |
|
||||
TbQueueRemoteJsInvokeSettings jsInvokeSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbQueueEdgeSettings edgeSettings, |
|
||||
TbServiceBusQueueConfigs serviceBusQueueConfigs) { |
|
||||
this.topicService = topicService; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.serviceBusSettings = serviceBusSettings; |
|
||||
this.jsInvokeSettings = jsInvokeSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.edgeSettings = edgeSettings; |
|
||||
|
|
||||
this.coreAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getCoreConfigs()); |
|
||||
this.ruleEngineAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getRuleEngineConfigs()); |
|
||||
this.jsExecutorAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getJsExecutorConfigs()); |
|
||||
this.notificationAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getNotificationsConfigs()); |
|
||||
this.edgeAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getEdgeConfigs()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(ruleEngineAdmin, serviceBusSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createRuleEngineNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeMsg>> createEdgeMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(edgeAdmin, serviceBusSettings, topicService.buildTopicName(edgeSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToEdgeNotificationMsg>> createEdgeNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.getEdgeNotificationsTopic(serviceInfoProvider.getServiceId()).getFullTopicName()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> createToRuleEngineMsgConsumer(Queue configuration) { |
|
||||
return new TbServiceBusConsumerTemplate<>(ruleEngineAdmin, serviceBusSettings, topicService.buildTopicName(configuration.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> createToRuleEngineNotificationsMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName(), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
@Bean |
|
||||
public TbQueueRequestTemplate<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> createRemoteJsRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>> producer = new TbServiceBusProducerTemplate<>(jsExecutorAdmin, serviceBusSettings, jsInvokeSettings.getRequestTopic()); |
|
||||
TbQueueConsumer<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> consumer = new TbServiceBusConsumerTemplate<>(jsExecutorAdmin, serviceBusSettings, |
|
||||
jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId(), |
|
||||
msg -> { |
|
||||
JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); |
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); |
|
||||
return new TbProtoQueueMsg<>(msg.getKey(), builder.build(), msg.getHeaders()); |
|
||||
}); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoJsQueueMsg<JsInvokeProtos.RemoteJsRequest>, TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> builder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
builder.queueAdmin(jsExecutorAdmin); |
|
||||
builder.requestTemplate(producer); |
|
||||
builder.responseTemplate(consumer); |
|
||||
builder.maxPendingRequests(jsInvokeSettings.getMaxPendingRequests()); |
|
||||
builder.maxRequestTimeout(jsInvokeSettings.getMaxRequestsTimeout()); |
|
||||
builder.pollInterval(jsInvokeSettings.getResponsePollInterval()); |
|
||||
return builder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getOtaPackageTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
if (jsExecutorAdmin != null) { |
|
||||
jsExecutorAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,98 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusAdmin; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusProducerTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusQueueConfigs; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusSettings; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='service-bus' && '${service.type:null}'=='tb-vc-executor'") |
|
||||
public class ServiceBusTbVersionControlQueueFactory implements TbVersionControlQueueFactory { |
|
||||
|
|
||||
private final TbServiceBusSettings serviceBusSettings; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueVersionControlSettings vcSettings; |
|
||||
private final TopicService topicService; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin vcAdmin; |
|
||||
|
|
||||
public ServiceBusTbVersionControlQueueFactory(TbServiceBusSettings serviceBusSettings, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbQueueVersionControlSettings vcSettings, |
|
||||
TbServiceBusQueueConfigs serviceBusQueueConfigs, |
|
||||
TopicService topicService |
|
||||
) { |
|
||||
this.serviceBusSettings = serviceBusSettings; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.vcSettings = vcSettings; |
|
||||
this.topicService = topicService; |
|
||||
|
|
||||
this.coreAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getCoreConfigs()); |
|
||||
this.notificationAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getNotificationsConfigs()); |
|
||||
this.vcAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getVcConfigs()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToVersionControlServiceMsg>> createToVersionControlMsgConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(vcAdmin, serviceBusSettings, topicService.buildTopicName(vcSettings.getTopic()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportProtos.ToVersionControlServiceMsg.parseFrom(msg.getData()), msg.getHeaders()) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (vcAdmin != null) { |
|
||||
vcAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,155 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.provider; |
|
||||
|
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToHousekeeperServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
|
||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueConsumer; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.TbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusAdmin; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusProducerTemplate; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusQueueConfigs; |
|
||||
import org.thingsboard.server.queue.azure.servicebus.TbServiceBusSettings; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueRequestTemplate; |
|
||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
|
||||
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; |
|
||||
import org.thingsboard.server.queue.discovery.TopicService; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueCoreSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; |
|
||||
import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='service-bus' && (('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport')") |
|
||||
@Slf4j |
|
||||
public class ServiceBusTransportQueueFactory implements TbTransportQueueFactory { |
|
||||
private final TbQueueTransportApiSettings transportApiSettings; |
|
||||
private final TbQueueTransportNotificationSettings transportNotificationSettings; |
|
||||
private final TbServiceBusSettings serviceBusSettings; |
|
||||
private final TbServiceInfoProvider serviceInfoProvider; |
|
||||
private final TbQueueCoreSettings coreSettings; |
|
||||
private final TbQueueRuleEngineSettings ruleEngineSettings; |
|
||||
private final TopicService topicService; |
|
||||
|
|
||||
private final TbQueueAdmin coreAdmin; |
|
||||
private final TbQueueAdmin transportApiAdmin; |
|
||||
private final TbQueueAdmin notificationAdmin; |
|
||||
private final TbQueueAdmin ruleEngineAdmin; |
|
||||
|
|
||||
public ServiceBusTransportQueueFactory(TbQueueTransportApiSettings transportApiSettings, |
|
||||
TbQueueTransportNotificationSettings transportNotificationSettings, |
|
||||
TbServiceBusSettings serviceBusSettings, |
|
||||
TbQueueRuleEngineSettings ruleEngineSettings, |
|
||||
TbServiceInfoProvider serviceInfoProvider, |
|
||||
TbQueueCoreSettings coreSettings, |
|
||||
TbServiceBusQueueConfigs serviceBusQueueConfigs, |
|
||||
TopicService topicService) { |
|
||||
this.transportApiSettings = transportApiSettings; |
|
||||
this.transportNotificationSettings = transportNotificationSettings; |
|
||||
this.serviceBusSettings = serviceBusSettings; |
|
||||
this.serviceInfoProvider = serviceInfoProvider; |
|
||||
this.coreSettings = coreSettings; |
|
||||
this.ruleEngineSettings = ruleEngineSettings; |
|
||||
this.topicService = topicService; |
|
||||
|
|
||||
this.coreAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getCoreConfigs()); |
|
||||
this.transportApiAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getTransportApiConfigs()); |
|
||||
this.notificationAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getNotificationsConfigs()); |
|
||||
this.ruleEngineAdmin = new TbServiceBusAdmin(serviceBusSettings, serviceBusQueueConfigs.getRuleEngineConfigs()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueRequestTemplate<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> createTransportApiRequestTemplate() { |
|
||||
TbQueueProducer<TbProtoQueueMsg<TransportApiRequestMsg>> producerTemplate = |
|
||||
new TbServiceBusProducerTemplate<>(transportApiAdmin, serviceBusSettings, topicService.buildTopicName(transportApiSettings.getRequestsTopic())); |
|
||||
|
|
||||
TbQueueConsumer<TbProtoQueueMsg<TransportApiResponseMsg>> consumerTemplate = |
|
||||
new TbServiceBusConsumerTemplate<>(transportApiAdmin, serviceBusSettings, |
|
||||
topicService.buildTopicName(transportApiSettings.getResponsesTopic() + "." + serviceInfoProvider.getServiceId()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiResponseMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
|
|
||||
DefaultTbQueueRequestTemplate.DefaultTbQueueRequestTemplateBuilder |
|
||||
<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> templateBuilder = DefaultTbQueueRequestTemplate.builder(); |
|
||||
templateBuilder.queueAdmin(transportApiAdmin); |
|
||||
templateBuilder.requestTemplate(producerTemplate); |
|
||||
templateBuilder.responseTemplate(consumerTemplate); |
|
||||
templateBuilder.maxPendingRequests(transportApiSettings.getMaxPendingRequests()); |
|
||||
templateBuilder.maxRequestTimeout(transportApiSettings.getMaxRequestsTimeout()); |
|
||||
templateBuilder.pollInterval(transportApiSettings.getResponsePollInterval()); |
|
||||
return templateBuilder.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> createRuleEngineMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(ruleEngineAdmin, serviceBusSettings, topicService.buildTopicName(ruleEngineSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> createTbCoreMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> createTbCoreNotificationsMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(notificationAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueConsumer<TbProtoQueueMsg<ToTransportMsg>> createTransportNotificationsConsumer() { |
|
||||
return new TbServiceBusConsumerTemplate<>(notificationAdmin, serviceBusSettings, |
|
||||
topicService.buildTopicName(transportNotificationSettings.getNotificationsTopic() + "." + serviceInfoProvider.getServiceId()), |
|
||||
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToTransportMsg.parseFrom(msg.getData()), msg.getHeaders())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> createToUsageStatsServiceMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getUsageStatsTopic())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public TbQueueProducer<TbProtoQueueMsg<ToHousekeeperServiceMsg>> createHousekeeperMsgProducer() { |
|
||||
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, topicService.buildTopicName(coreSettings.getHousekeeperTopic())); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (coreAdmin != null) { |
|
||||
coreAdmin.destroy(); |
|
||||
} |
|
||||
if (transportApiAdmin != null) { |
|
||||
transportApiAdmin.destroy(); |
|
||||
} |
|
||||
if (notificationAdmin != null) { |
|
||||
notificationAdmin.destroy(); |
|
||||
} |
|
||||
if (ruleEngineAdmin != null) { |
|
||||
ruleEngineAdmin.destroy(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,232 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.pubsub; |
|
||||
|
|
||||
import com.google.api.gax.rpc.AlreadyExistsException; |
|
||||
import com.google.cloud.pubsub.v1.SubscriptionAdminClient; |
|
||||
import com.google.cloud.pubsub.v1.SubscriptionAdminSettings; |
|
||||
import com.google.cloud.pubsub.v1.TopicAdminClient; |
|
||||
import com.google.cloud.pubsub.v1.TopicAdminSettings; |
|
||||
import com.google.protobuf.Duration; |
|
||||
import com.google.pubsub.v1.ListSubscriptionsRequest; |
|
||||
import com.google.pubsub.v1.ListTopicsRequest; |
|
||||
import com.google.pubsub.v1.ProjectName; |
|
||||
import com.google.pubsub.v1.ProjectSubscriptionName; |
|
||||
import com.google.pubsub.v1.Subscription; |
|
||||
import com.google.pubsub.v1.Topic; |
|
||||
import com.google.pubsub.v1.TopicName; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
|
|
||||
import java.io.IOException; |
|
||||
import java.util.Map; |
|
||||
import java.util.Set; |
|
||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||
|
|
||||
@Slf4j |
|
||||
@Deprecated(forRemoval = true, since = "3.9") // for removal in 4.0
|
|
||||
public class TbPubSubAdmin implements TbQueueAdmin { |
|
||||
private static final String ACK_DEADLINE = "ackDeadlineInSec"; |
|
||||
private static final String MESSAGE_RETENTION = "messageRetentionInSec"; |
|
||||
|
|
||||
private final TopicAdminClient topicAdminClient; |
|
||||
private final SubscriptionAdminClient subscriptionAdminClient; |
|
||||
|
|
||||
private final TbPubSubSettings pubSubSettings; |
|
||||
private final Set<String> topicSet = ConcurrentHashMap.newKeySet(); |
|
||||
private final Set<String> subscriptionSet = ConcurrentHashMap.newKeySet(); |
|
||||
private final Map<String, String> subscriptionProperties; |
|
||||
|
|
||||
public TbPubSubAdmin(TbPubSubSettings pubSubSettings, Map<String, String> subscriptionSettings) { |
|
||||
this.pubSubSettings = pubSubSettings; |
|
||||
this.subscriptionProperties = subscriptionSettings; |
|
||||
|
|
||||
TopicAdminSettings topicAdminSettings; |
|
||||
try { |
|
||||
topicAdminSettings = TopicAdminSettings.newBuilder().setCredentialsProvider(pubSubSettings.getCredentialsProvider()).build(); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to create TopicAdminSettings"); |
|
||||
throw new RuntimeException("Failed to create TopicAdminSettings."); |
|
||||
} |
|
||||
|
|
||||
SubscriptionAdminSettings subscriptionAdminSettings; |
|
||||
try { |
|
||||
subscriptionAdminSettings = SubscriptionAdminSettings.newBuilder().setCredentialsProvider(pubSubSettings.getCredentialsProvider()).build(); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to create SubscriptionAdminSettings"); |
|
||||
throw new RuntimeException("Failed to create SubscriptionAdminSettings."); |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
topicAdminClient = TopicAdminClient.create(topicAdminSettings); |
|
||||
|
|
||||
ListTopicsRequest listTopicsRequest = |
|
||||
ListTopicsRequest.newBuilder().setProject(ProjectName.format(pubSubSettings.getProjectId())).build(); |
|
||||
TopicAdminClient.ListTopicsPagedResponse response = topicAdminClient.listTopics(listTopicsRequest); |
|
||||
for (Topic topic : response.iterateAll()) { |
|
||||
topicSet.add(topic.getName()); |
|
||||
} |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to get topics.", e); |
|
||||
throw new RuntimeException("Failed to get topics.", e); |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
subscriptionAdminClient = SubscriptionAdminClient.create(subscriptionAdminSettings); |
|
||||
|
|
||||
ListSubscriptionsRequest listSubscriptionsRequest = |
|
||||
ListSubscriptionsRequest.newBuilder() |
|
||||
.setProject(ProjectName.of(pubSubSettings.getProjectId()).toString()) |
|
||||
.build(); |
|
||||
SubscriptionAdminClient.ListSubscriptionsPagedResponse response = |
|
||||
subscriptionAdminClient.listSubscriptions(listSubscriptionsRequest); |
|
||||
|
|
||||
for (Subscription subscription : response.iterateAll()) { |
|
||||
subscriptionSet.add(subscription.getName()); |
|
||||
} |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to get subscriptions.", e); |
|
||||
throw new RuntimeException("Failed to get subscriptions.", e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void createTopicIfNotExists(String partition, String properties) { |
|
||||
TopicName topicName = TopicName.newBuilder() |
|
||||
.setTopic(partition) |
|
||||
.setProject(pubSubSettings.getProjectId()) |
|
||||
.build(); |
|
||||
|
|
||||
if (topicSet.contains(topicName.toString())) { |
|
||||
createSubscriptionIfNotExists(partition, topicName); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
ListTopicsRequest listTopicsRequest = |
|
||||
ListTopicsRequest.newBuilder().setProject(ProjectName.format(pubSubSettings.getProjectId())).build(); |
|
||||
TopicAdminClient.ListTopicsPagedResponse response = topicAdminClient.listTopics(listTopicsRequest); |
|
||||
for (Topic topic : response.iterateAll()) { |
|
||||
if (topic.getName().contains(topicName.toString())) { |
|
||||
topicSet.add(topic.getName()); |
|
||||
createSubscriptionIfNotExists(partition, topicName); |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
topicAdminClient.createTopic(topicName); |
|
||||
log.info("Created new topic: [{}]", topicName.toString()); |
|
||||
} catch (AlreadyExistsException e) { |
|
||||
log.info("[{}] Topic already exist.", topicName.toString()); |
|
||||
} finally { |
|
||||
topicSet.add(topicName.toString()); |
|
||||
} |
|
||||
createSubscriptionIfNotExists(partition, topicName); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void deleteTopic(String topic) { |
|
||||
TopicName topicName = TopicName.newBuilder() |
|
||||
.setTopic(topic) |
|
||||
.setProject(pubSubSettings.getProjectId()) |
|
||||
.build(); |
|
||||
|
|
||||
ProjectSubscriptionName subscriptionName = |
|
||||
ProjectSubscriptionName.of(pubSubSettings.getProjectId(), topic); |
|
||||
|
|
||||
if (topicSet.contains(topicName.toString())) { |
|
||||
topicAdminClient.deleteTopic(topicName); |
|
||||
} else { |
|
||||
if (topicAdminClient.getTopic(topicName) != null) { |
|
||||
topicAdminClient.deleteTopic(topicName); |
|
||||
} else { |
|
||||
log.warn("PubSub topic [{}] does not exist.", topic); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (subscriptionSet.contains(subscriptionName.toString())) { |
|
||||
subscriptionAdminClient.deleteSubscription(subscriptionName); |
|
||||
} else { |
|
||||
if (subscriptionAdminClient.getSubscription(subscriptionName) != null) { |
|
||||
subscriptionAdminClient.deleteSubscription(subscriptionName); |
|
||||
} else { |
|
||||
log.warn("PubSub subscription [{}] does not exist.", topic); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void createSubscriptionIfNotExists(String partition, TopicName topicName) { |
|
||||
ProjectSubscriptionName subscriptionName = |
|
||||
ProjectSubscriptionName.of(pubSubSettings.getProjectId(), partition); |
|
||||
|
|
||||
if (subscriptionSet.contains(subscriptionName.toString())) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
ListSubscriptionsRequest listSubscriptionsRequest = |
|
||||
ListSubscriptionsRequest.newBuilder().setProject(ProjectName.of(pubSubSettings.getProjectId()).toString()).build(); |
|
||||
SubscriptionAdminClient.ListSubscriptionsPagedResponse response = subscriptionAdminClient.listSubscriptions(listSubscriptionsRequest); |
|
||||
for (Subscription subscription : response.iterateAll()) { |
|
||||
if (subscription.getName().equals(subscriptionName.toString())) { |
|
||||
subscriptionSet.add(subscription.getName()); |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
Subscription.Builder subscriptionBuilder = Subscription |
|
||||
.newBuilder() |
|
||||
.setName(subscriptionName.toString()) |
|
||||
.setTopic(topicName.toString()); |
|
||||
|
|
||||
setAckDeadline(subscriptionBuilder); |
|
||||
setMessageRetention(subscriptionBuilder); |
|
||||
|
|
||||
try { |
|
||||
subscriptionAdminClient.createSubscription(subscriptionBuilder.build()); |
|
||||
log.info("Created new subscription: [{}]", subscriptionName.toString()); |
|
||||
} catch (AlreadyExistsException e) { |
|
||||
log.info("[{}] Subscription already exist.", subscriptionName.toString()); |
|
||||
} finally { |
|
||||
subscriptionSet.add(subscriptionName.toString()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void setAckDeadline(Subscription.Builder builder) { |
|
||||
if (subscriptionProperties.containsKey(ACK_DEADLINE)) { |
|
||||
builder.setAckDeadlineSeconds(Integer.parseInt(subscriptionProperties.get(ACK_DEADLINE))); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void setMessageRetention(Subscription.Builder builder) { |
|
||||
if (subscriptionProperties.containsKey(MESSAGE_RETENTION)) { |
|
||||
Duration duration = Duration |
|
||||
.newBuilder() |
|
||||
.setSeconds(Long.parseLong(subscriptionProperties.get(MESSAGE_RETENTION))) |
|
||||
.build(); |
|
||||
builder.setMessageRetentionDuration(duration); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void destroy() { |
|
||||
if (topicAdminClient != null) { |
|
||||
topicAdminClient.close(); |
|
||||
} |
|
||||
if (subscriptionAdminClient != null) { |
|
||||
subscriptionAdminClient.close(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,175 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.pubsub; |
|
||||
|
|
||||
import com.google.api.core.ApiFuture; |
|
||||
import com.google.api.core.ApiFutures; |
|
||||
import com.google.cloud.pubsub.v1.stub.GrpcSubscriberStub; |
|
||||
import com.google.cloud.pubsub.v1.stub.SubscriberStub; |
|
||||
import com.google.cloud.pubsub.v1.stub.SubscriberStubSettings; |
|
||||
import com.google.gson.Gson; |
|
||||
import com.google.protobuf.InvalidProtocolBufferException; |
|
||||
import com.google.pubsub.v1.AcknowledgeRequest; |
|
||||
import com.google.pubsub.v1.ProjectSubscriptionName; |
|
||||
import com.google.pubsub.v1.PubsubMessage; |
|
||||
import com.google.pubsub.v1.PullRequest; |
|
||||
import com.google.pubsub.v1.PullResponse; |
|
||||
import com.google.pubsub.v1.ReceivedMessage; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.util.CollectionUtils; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueMsgDecoder; |
|
||||
import org.thingsboard.server.queue.common.AbstractParallelTbQueueConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|
||||
|
|
||||
import java.io.IOException; |
|
||||
import java.util.ArrayList; |
|
||||
import java.util.Collections; |
|
||||
import java.util.LinkedHashSet; |
|
||||
import java.util.List; |
|
||||
import java.util.Objects; |
|
||||
import java.util.Set; |
|
||||
import java.util.concurrent.CopyOnWriteArrayList; |
|
||||
import java.util.concurrent.ExecutionException; |
|
||||
import java.util.stream.Collectors; |
|
||||
|
|
||||
@Slf4j |
|
||||
public class TbPubSubConsumerTemplate<T extends TbQueueMsg> extends AbstractParallelTbQueueConsumerTemplate<PubsubMessage, T> { |
|
||||
|
|
||||
private final Gson gson = new Gson(); |
|
||||
private final TbQueueAdmin admin; |
|
||||
private final String topic; |
|
||||
private final TbQueueMsgDecoder<T> decoder; |
|
||||
private final TbPubSubSettings pubSubSettings; |
|
||||
|
|
||||
private volatile Set<String> subscriptionNames; |
|
||||
private final List<AcknowledgeRequest> acknowledgeRequests = new CopyOnWriteArrayList<>(); |
|
||||
|
|
||||
private final SubscriberStub subscriber; |
|
||||
private volatile int messagesPerTopic; |
|
||||
|
|
||||
public TbPubSubConsumerTemplate(TbQueueAdmin admin, TbPubSubSettings pubSubSettings, String topic, TbQueueMsgDecoder<T> decoder) { |
|
||||
super(topic); |
|
||||
this.admin = admin; |
|
||||
this.pubSubSettings = pubSubSettings; |
|
||||
this.topic = topic; |
|
||||
this.decoder = decoder; |
|
||||
try { |
|
||||
SubscriberStubSettings subscriberStubSettings = |
|
||||
SubscriberStubSettings.newBuilder() |
|
||||
.setCredentialsProvider(pubSubSettings.getCredentialsProvider()) |
|
||||
.setTransportChannelProvider( |
|
||||
SubscriberStubSettings.defaultGrpcTransportProviderBuilder() |
|
||||
.setMaxInboundMessageSize(pubSubSettings.getMaxMsgSize()) |
|
||||
.build()) |
|
||||
.setExecutorProvider(pubSubSettings.getExecutorProvider()) |
|
||||
.build(); |
|
||||
this.subscriber = GrpcSubscriberStub.create(subscriberStubSettings); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to create subscriber.", e); |
|
||||
throw new RuntimeException("Failed to create subscriber.", e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected List<PubsubMessage> doPoll(long durationInMillis) { |
|
||||
try { |
|
||||
List<ReceivedMessage> messages = receiveMessages(); |
|
||||
if (!messages.isEmpty()) { |
|
||||
return messages.stream().map(ReceivedMessage::getMessage).collect(Collectors.toList()); |
|
||||
} |
|
||||
} catch (ExecutionException | InterruptedException e) { |
|
||||
if (stopped) { |
|
||||
log.info("[{}] Pub/Sub consumer is stopped.", topic); |
|
||||
} else { |
|
||||
log.error("Failed to receive messages", e); |
|
||||
} |
|
||||
} |
|
||||
return Collections.emptyList(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doSubscribe(List<String> topicNames) { |
|
||||
subscriptionNames = new LinkedHashSet<>(topicNames); |
|
||||
subscriptionNames.forEach(admin::createTopicIfNotExists); |
|
||||
initNewExecutor(subscriptionNames.size() + 1); |
|
||||
messagesPerTopic = pubSubSettings.getMaxMessages() / Math.max(subscriptionNames.size(), 1); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doCommit() { |
|
||||
acknowledgeRequests.forEach(subscriber.acknowledgeCallable()::futureCall); |
|
||||
acknowledgeRequests.clear(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doUnsubscribe() { |
|
||||
if (subscriber != null) { |
|
||||
subscriber.close(); |
|
||||
} |
|
||||
shutdownExecutor(); |
|
||||
} |
|
||||
|
|
||||
private List<ReceivedMessage> receiveMessages() throws ExecutionException, InterruptedException { |
|
||||
List<ApiFuture<List<ReceivedMessage>>> result = subscriptionNames.stream().map(subscriptionId -> { |
|
||||
String subscriptionName = ProjectSubscriptionName.format(pubSubSettings.getProjectId(), subscriptionId); |
|
||||
PullRequest pullRequest = |
|
||||
PullRequest.newBuilder() |
|
||||
.setMaxMessages(messagesPerTopic) |
|
||||
// .setReturnImmediately(false) // return immediately if messages are not available
|
|
||||
.setSubscription(subscriptionName) |
|
||||
.build(); |
|
||||
|
|
||||
ApiFuture<PullResponse> pullResponseApiFuture = subscriber.pullCallable().futureCall(pullRequest); |
|
||||
|
|
||||
return ApiFutures.transform(pullResponseApiFuture, pullResponse -> { |
|
||||
if (pullResponse != null && !pullResponse.getReceivedMessagesList().isEmpty()) { |
|
||||
List<String> ackIds = new ArrayList<>(); |
|
||||
for (ReceivedMessage message : pullResponse.getReceivedMessagesList()) { |
|
||||
ackIds.add(message.getAckId()); |
|
||||
} |
|
||||
AcknowledgeRequest acknowledgeRequest = |
|
||||
AcknowledgeRequest.newBuilder() |
|
||||
.setSubscription(subscriptionName) |
|
||||
.addAllAckIds(ackIds) |
|
||||
.build(); |
|
||||
|
|
||||
acknowledgeRequests.add(acknowledgeRequest); |
|
||||
return pullResponse.getReceivedMessagesList(); |
|
||||
} |
|
||||
return null; |
|
||||
}, consumerExecutor); |
|
||||
|
|
||||
}).collect(Collectors.toList()); |
|
||||
|
|
||||
ApiFuture<List<ReceivedMessage>> transform = ApiFutures.transform(ApiFutures.allAsList(result), listMessages -> { |
|
||||
if (!CollectionUtils.isEmpty(listMessages)) { |
|
||||
return listMessages.stream().filter(Objects::nonNull).flatMap(List::stream).collect(Collectors.toList()); |
|
||||
} |
|
||||
return Collections.emptyList(); |
|
||||
}, consumerExecutor); |
|
||||
|
|
||||
return transform.get(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public T decode(PubsubMessage message) throws InvalidProtocolBufferException { |
|
||||
DefaultTbQueueMsg msg = gson.fromJson(message.getData().toStringUtf8(), DefaultTbQueueMsg.class); |
|
||||
return decoder.decode(msg); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,137 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.pubsub; |
|
||||
|
|
||||
import com.google.api.core.ApiFuture; |
|
||||
import com.google.api.core.ApiFutureCallback; |
|
||||
import com.google.api.core.ApiFutures; |
|
||||
import com.google.cloud.pubsub.v1.Publisher; |
|
||||
import com.google.gson.Gson; |
|
||||
import com.google.protobuf.ByteString; |
|
||||
import com.google.pubsub.v1.ProjectTopicName; |
|
||||
import com.google.pubsub.v1.PubsubMessage; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueCallback; |
|
||||
import org.thingsboard.server.queue.TbQueueMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|
||||
|
|
||||
import java.io.IOException; |
|
||||
import java.util.Map; |
|
||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||
import java.util.concurrent.ExecutorService; |
|
||||
import java.util.concurrent.Executors; |
|
||||
import java.util.concurrent.TimeUnit; |
|
||||
|
|
||||
@Slf4j |
|
||||
public class TbPubSubProducerTemplate<T extends TbQueueMsg> implements TbQueueProducer<T> { |
|
||||
|
|
||||
private final Gson gson = new Gson(); |
|
||||
|
|
||||
private final String defaultTopic; |
|
||||
private final TbQueueAdmin admin; |
|
||||
private final TbPubSubSettings pubSubSettings; |
|
||||
|
|
||||
private final Map<String, Publisher> publisherMap = new ConcurrentHashMap<>(); |
|
||||
|
|
||||
private final ExecutorService pubExecutor = Executors.newCachedThreadPool(); |
|
||||
|
|
||||
public TbPubSubProducerTemplate(TbQueueAdmin admin, TbPubSubSettings pubSubSettings, String defaultTopic) { |
|
||||
this.defaultTopic = defaultTopic; |
|
||||
this.admin = admin; |
|
||||
this.pubSubSettings = pubSubSettings; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void init() { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public String getDefaultTopic() { |
|
||||
return defaultTopic; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) { |
|
||||
PubsubMessage.Builder pubsubMessageBuilder = PubsubMessage.newBuilder(); |
|
||||
pubsubMessageBuilder.setData(getMsg(msg)); |
|
||||
|
|
||||
Publisher publisher = getOrCreatePublisher(tpi.getFullTopicName()); |
|
||||
ApiFuture<String> future = publisher.publish(pubsubMessageBuilder.build()); |
|
||||
|
|
||||
ApiFutures.addCallback(future, new ApiFutureCallback<String>() { |
|
||||
public void onSuccess(String messageId) { |
|
||||
if (callback != null) { |
|
||||
callback.onSuccess(null); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public void onFailure(Throwable t) { |
|
||||
if (callback != null) { |
|
||||
callback.onFailure(t); |
|
||||
} |
|
||||
} |
|
||||
}, pubExecutor); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void stop() { |
|
||||
publisherMap.forEach((k, v) -> { |
|
||||
if (v != null) { |
|
||||
try { |
|
||||
v.shutdown(); |
|
||||
v.awaitTermination(1, TimeUnit.SECONDS); |
|
||||
} catch (Exception e) { |
|
||||
log.error("Failed to shutdown PubSub client during destroy()", e); |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
if (pubExecutor != null) { |
|
||||
pubExecutor.shutdownNow(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private ByteString getMsg(T msg) { |
|
||||
String json = gson.toJson(new DefaultTbQueueMsg(msg)); |
|
||||
return ByteString.copyFrom(json.getBytes()); |
|
||||
} |
|
||||
|
|
||||
private Publisher getOrCreatePublisher(String topic) { |
|
||||
if (publisherMap.containsKey(topic)) { |
|
||||
return publisherMap.get(topic); |
|
||||
} else { |
|
||||
try { |
|
||||
admin.createTopicIfNotExists(topic); |
|
||||
ProjectTopicName topicName = ProjectTopicName.of(pubSubSettings.getProjectId(), topic); |
|
||||
Publisher publisher = Publisher.newBuilder(topicName) |
|
||||
.setCredentialsProvider(pubSubSettings.getCredentialsProvider()) |
|
||||
.setExecutorProvider(pubSubSettings.getExecutorProvider()) |
|
||||
.build(); |
|
||||
publisherMap.put(topic, publisher); |
|
||||
return publisher; |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to create Publisher for the topic [{}].", topic, e); |
|
||||
throw new RuntimeException("Failed to create Publisher for the topic.", e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,82 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.pubsub; |
|
||||
|
|
||||
import com.google.api.gax.core.CredentialsProvider; |
|
||||
import com.google.api.gax.core.FixedCredentialsProvider; |
|
||||
import com.google.api.gax.core.FixedExecutorProvider; |
|
||||
import com.google.auth.oauth2.ServiceAccountCredentials; |
|
||||
import jakarta.annotation.PostConstruct; |
|
||||
import jakarta.annotation.PreDestroy; |
|
||||
import lombok.Data; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.common.util.ThingsBoardExecutors; |
|
||||
|
|
||||
import java.io.ByteArrayInputStream; |
|
||||
import java.io.IOException; |
|
||||
|
|
||||
@Slf4j |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='pubsub'") |
|
||||
@Component |
|
||||
@Data |
|
||||
public class TbPubSubSettings { |
|
||||
|
|
||||
@Value("${queue.pubsub.project_id}") |
|
||||
private String projectId; |
|
||||
|
|
||||
@Value("${queue.pubsub.service_account}") |
|
||||
private String serviceAccount; |
|
||||
|
|
||||
@Value("${queue.pubsub.max_msg_size}") |
|
||||
private int maxMsgSize; |
|
||||
|
|
||||
@Value("${queue.pubsub.max_messages}") |
|
||||
private int maxMessages; |
|
||||
|
|
||||
@Value("${queue.pubsub.executor_thread_pool_size:0}") |
|
||||
private int threadPoolSize; |
|
||||
|
|
||||
/** |
|
||||
* Refers to com.google.cloud.pubsub.v1.Publisher default executor configuration |
|
||||
*/ |
|
||||
private static final int THREADS_PER_CPU = 5; |
|
||||
|
|
||||
private FixedExecutorProvider executorProvider; |
|
||||
|
|
||||
private CredentialsProvider credentialsProvider; |
|
||||
|
|
||||
@PostConstruct |
|
||||
private void init() throws IOException { |
|
||||
ServiceAccountCredentials credentials = ServiceAccountCredentials.fromStream( |
|
||||
new ByteArrayInputStream(serviceAccount.getBytes())); |
|
||||
credentialsProvider = FixedCredentialsProvider.create(credentials); |
|
||||
if (threadPoolSize == 0) { |
|
||||
threadPoolSize = THREADS_PER_CPU * Runtime.getRuntime().availableProcessors(); |
|
||||
} |
|
||||
executorProvider = FixedExecutorProvider |
|
||||
.create(ThingsBoardExecutors.newScheduledThreadPool(threadPoolSize, "pubsub-queue-executor")); |
|
||||
} |
|
||||
|
|
||||
@PreDestroy |
|
||||
private void destroy() { |
|
||||
if (executorProvider != null) { |
|
||||
executorProvider.getExecutor().shutdownNow(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,72 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.pubsub; |
|
||||
|
|
||||
import jakarta.annotation.PostConstruct; |
|
||||
import lombok.Getter; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.queue.util.PropertyUtils; |
|
||||
|
|
||||
import java.util.Map; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='pubsub'") |
|
||||
public class TbPubSubSubscriptionSettings { |
|
||||
|
|
||||
@Value("${queue.pubsub.queue-properties.core:}") |
|
||||
private String coreProperties; |
|
||||
@Value("${queue.pubsub.queue-properties.rule-engine:}") |
|
||||
private String ruleEngineProperties; |
|
||||
@Value("${queue.pubsub.queue-properties.transport-api:}") |
|
||||
private String transportApiProperties; |
|
||||
@Value("${queue.pubsub.queue-properties.notifications:}") |
|
||||
private String notificationsProperties; |
|
||||
@Value("${queue.pubsub.queue-properties.js-executor:}") |
|
||||
private String jsExecutorProperties; |
|
||||
@Value("${queue.pubsub.queue-properties.version-control:}") |
|
||||
private String vcProperties; |
|
||||
@Value("${queue.pubsub.queue-properties.edge:}") |
|
||||
private String edgeProperties; |
|
||||
|
|
||||
@Getter |
|
||||
private Map<String, String> coreSettings; |
|
||||
@Getter |
|
||||
private Map<String, String> ruleEngineSettings; |
|
||||
@Getter |
|
||||
private Map<String, String> transportApiSettings; |
|
||||
@Getter |
|
||||
private Map<String, String> notificationsSettings; |
|
||||
@Getter |
|
||||
private Map<String, String> jsExecutorSettings; |
|
||||
@Getter |
|
||||
private Map<String, String> vcSettings; |
|
||||
@Getter |
|
||||
private Map<String, String> edgeSettings; |
|
||||
|
|
||||
@PostConstruct |
|
||||
private void init() { |
|
||||
coreSettings = PropertyUtils.getProps(coreProperties); |
|
||||
ruleEngineSettings = PropertyUtils.getProps(ruleEngineProperties); |
|
||||
transportApiSettings = PropertyUtils.getProps(transportApiProperties); |
|
||||
notificationsSettings = PropertyUtils.getProps(notificationsProperties); |
|
||||
jsExecutorSettings = PropertyUtils.getProps(jsExecutorProperties); |
|
||||
vcSettings = PropertyUtils.getProps(vcProperties); |
|
||||
edgeSettings = PropertyUtils.getProps(edgeProperties); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,95 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.rabbitmq; |
|
||||
|
|
||||
import com.rabbitmq.client.Channel; |
|
||||
import com.rabbitmq.client.Connection; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.apache.commons.lang3.StringUtils; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
|
|
||||
import java.io.IOException; |
|
||||
import java.util.HashMap; |
|
||||
import java.util.Map; |
|
||||
import java.util.concurrent.TimeoutException; |
|
||||
|
|
||||
@Slf4j |
|
||||
@Deprecated(forRemoval = true, since = "3.9") // for removal in 4.0
|
|
||||
public class TbRabbitMqAdmin implements TbQueueAdmin { |
|
||||
|
|
||||
private final Channel channel; |
|
||||
private final Connection connection; |
|
||||
private final Map<String, Object> arguments; |
|
||||
|
|
||||
public TbRabbitMqAdmin(TbRabbitMqSettings rabbitMqSettings, Map<String, Object> arguments) { |
|
||||
this.arguments = arguments; |
|
||||
|
|
||||
try { |
|
||||
connection = rabbitMqSettings.getConnectionFactory().newConnection(); |
|
||||
} catch (IOException | TimeoutException e) { |
|
||||
log.error("Failed to create connection.", e); |
|
||||
throw new RuntimeException("Failed to create connection.", e); |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
channel = connection.createChannel(); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to create chanel.", e); |
|
||||
throw new RuntimeException("Failed to create chanel.", e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void createTopicIfNotExists(String topic, String properties) { |
|
||||
Map<String, Object> arguments = this.arguments; |
|
||||
if (StringUtils.isNotBlank(properties)) { |
|
||||
arguments = new HashMap<>(arguments); |
|
||||
arguments.putAll(TbRabbitMqQueueArguments.getArgs(properties)); |
|
||||
} |
|
||||
try { |
|
||||
channel.queueDeclare(topic, false, false, false, arguments); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to bind queue: [{}]", topic, e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void deleteTopic(String topic) { |
|
||||
try { |
|
||||
channel.queueDelete(topic); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to delete RabbitMq queue [{}].", topic); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void destroy() { |
|
||||
if (channel != null) { |
|
||||
try { |
|
||||
channel.close(); |
|
||||
} catch (IOException | TimeoutException e) { |
|
||||
log.error("Failed to close Chanel.", e); |
|
||||
} |
|
||||
} |
|
||||
if (connection != null) { |
|
||||
try { |
|
||||
connection.close(); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to close Connection.", e); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,144 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.rabbitmq; |
|
||||
|
|
||||
import com.google.gson.Gson; |
|
||||
import com.google.protobuf.InvalidProtocolBufferException; |
|
||||
import com.rabbitmq.client.Channel; |
|
||||
import com.rabbitmq.client.Connection; |
|
||||
import com.rabbitmq.client.GetResponse; |
|
||||
import java.util.ArrayList; |
|
||||
import java.util.Collection; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueMsgDecoder; |
|
||||
import org.thingsboard.server.queue.common.AbstractTbQueueConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|
||||
|
|
||||
import java.io.IOException; |
|
||||
import java.util.Collections; |
|
||||
import java.util.List; |
|
||||
import java.util.Set; |
|
||||
import java.util.concurrent.TimeoutException; |
|
||||
import java.util.stream.Collectors; |
|
||||
|
|
||||
@Slf4j |
|
||||
public class TbRabbitMqConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQueueConsumerTemplate<GetResponse, T> { |
|
||||
|
|
||||
private final Gson gson = new Gson(); |
|
||||
private final TbQueueAdmin admin; |
|
||||
private final TbQueueMsgDecoder<T> decoder; |
|
||||
private final Channel channel; |
|
||||
private final Connection connection; |
|
||||
private final int maxPollMessages; |
|
||||
|
|
||||
private volatile Set<String> queues; |
|
||||
|
|
||||
public TbRabbitMqConsumerTemplate(TbQueueAdmin admin, TbRabbitMqSettings rabbitMqSettings, String topic, TbQueueMsgDecoder<T> decoder) { |
|
||||
super(topic); |
|
||||
this.admin = admin; |
|
||||
this.decoder = decoder; |
|
||||
this.maxPollMessages = rabbitMqSettings.getMaxPollMessages(); |
|
||||
try { |
|
||||
connection = rabbitMqSettings.getConnectionFactory().newConnection(); |
|
||||
} catch (IOException | TimeoutException e) { |
|
||||
log.error("Failed to create connection.", e); |
|
||||
throw new RuntimeException("Failed to create connection.", e); |
|
||||
} |
|
||||
try { |
|
||||
channel = connection.createChannel(); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to create chanel.", e); |
|
||||
throw new RuntimeException("Failed to create chanel.", e); |
|
||||
} |
|
||||
stopped = false; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected List<GetResponse> doPoll(long durationInMillis) { |
|
||||
List<GetResponse> result = queues.stream() |
|
||||
.map(queue -> { |
|
||||
List<GetResponse> messages = new ArrayList<>(); |
|
||||
for (int i = 0; i < maxPollMessages; i++) { |
|
||||
GetResponse response = doQueuePoll(queue); |
|
||||
if (response == null) { |
|
||||
break; |
|
||||
} |
|
||||
messages.add(response); |
|
||||
} |
|
||||
return messages; |
|
||||
}) |
|
||||
.filter(r -> !r.isEmpty()) |
|
||||
.flatMap(Collection::stream) |
|
||||
.collect(Collectors.toList()); |
|
||||
if (result.size() > 0) { |
|
||||
return result; |
|
||||
} else { |
|
||||
return Collections.emptyList(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected GetResponse doQueuePoll(String queue) { |
|
||||
try { |
|
||||
return channel.basicGet(queue, false); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to get messages from queue: [{}]", queue); |
|
||||
throw new RuntimeException("Failed to get messages from queue.", e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doSubscribe(List<String> topicNames) { |
|
||||
queues = partitions.stream() |
|
||||
.map(TopicPartitionInfo::getFullTopicName) |
|
||||
.collect(Collectors.toSet()); |
|
||||
queues.forEach(admin::createTopicIfNotExists); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doCommit() { |
|
||||
try { |
|
||||
channel.basicAck(0, true); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to ack messages.", e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doUnsubscribe() { |
|
||||
if (channel != null) { |
|
||||
try { |
|
||||
channel.close(); |
|
||||
} catch (IOException | TimeoutException e) { |
|
||||
log.error("Failed to close the channel."); |
|
||||
} |
|
||||
} |
|
||||
if (connection != null) { |
|
||||
try { |
|
||||
connection.close(); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to close the connection."); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public T decode(GetResponse message) throws InvalidProtocolBufferException { |
|
||||
DefaultTbQueueMsg msg = gson.fromJson(new String(message.getBody()), DefaultTbQueueMsg.class); |
|
||||
return decoder.decode(msg); |
|
||||
} |
|
||||
} |
|
||||
@ -1,125 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.rabbitmq; |
|
||||
|
|
||||
import com.google.common.util.concurrent.ListeningExecutorService; |
|
||||
import com.google.common.util.concurrent.MoreExecutors; |
|
||||
import com.google.gson.Gson; |
|
||||
import com.rabbitmq.client.AMQP; |
|
||||
import com.rabbitmq.client.Channel; |
|
||||
import com.rabbitmq.client.Connection; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueCallback; |
|
||||
import org.thingsboard.server.queue.TbQueueMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|
||||
|
|
||||
import java.io.IOException; |
|
||||
import java.util.Set; |
|
||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||
import java.util.concurrent.Executors; |
|
||||
import java.util.concurrent.TimeoutException; |
|
||||
|
|
||||
@Slf4j |
|
||||
public class TbRabbitMqProducerTemplate<T extends TbQueueMsg> implements TbQueueProducer<T> { |
|
||||
private final String defaultTopic; |
|
||||
private final Gson gson = new Gson(); |
|
||||
private final TbQueueAdmin admin; |
|
||||
private final TbRabbitMqSettings rabbitMqSettings; |
|
||||
private final ListeningExecutorService producerExecutor; |
|
||||
private final Channel channel; |
|
||||
private final Connection connection; |
|
||||
|
|
||||
private final Set<TopicPartitionInfo> topics = ConcurrentHashMap.newKeySet(); |
|
||||
|
|
||||
public TbRabbitMqProducerTemplate(TbQueueAdmin admin, TbRabbitMqSettings rabbitMqSettings, String defaultTopic) { |
|
||||
this.admin = admin; |
|
||||
this.defaultTopic = defaultTopic; |
|
||||
this.rabbitMqSettings = rabbitMqSettings; |
|
||||
producerExecutor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()); |
|
||||
try { |
|
||||
connection = rabbitMqSettings.getConnectionFactory().newConnection(); |
|
||||
} catch (IOException | TimeoutException e) { |
|
||||
log.error("Failed to create connection.", e); |
|
||||
throw new RuntimeException("Failed to create connection.", e); |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
channel = connection.createChannel(); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to create chanel.", e); |
|
||||
throw new RuntimeException("Failed to create chanel.", e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void init() { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public String getDefaultTopic() { |
|
||||
return defaultTopic; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) { |
|
||||
createTopicIfNotExist(tpi); |
|
||||
AMQP.BasicProperties properties = new AMQP.BasicProperties(); |
|
||||
try { |
|
||||
channel.basicPublish(rabbitMqSettings.getExchangeName(), tpi.getFullTopicName(), properties, gson.toJson(new DefaultTbQueueMsg(msg)).getBytes()); |
|
||||
if (callback != null) { |
|
||||
callback.onSuccess(null); |
|
||||
} |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed publish message: [{}].", msg, e); |
|
||||
if (callback != null) { |
|
||||
callback.onFailure(e); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void stop() { |
|
||||
if (producerExecutor != null) { |
|
||||
producerExecutor.shutdownNow(); |
|
||||
} |
|
||||
if (channel != null) { |
|
||||
try { |
|
||||
channel.close(); |
|
||||
} catch (IOException | TimeoutException e) { |
|
||||
log.error("Failed to close the channel."); |
|
||||
} |
|
||||
} |
|
||||
if (connection != null) { |
|
||||
try { |
|
||||
connection.close(); |
|
||||
} catch (IOException e) { |
|
||||
log.error("Failed to close the connection."); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void createTopicIfNotExist(TopicPartitionInfo tpi) { |
|
||||
if (topics.contains(tpi)) { |
|
||||
return; |
|
||||
} |
|
||||
admin.createTopicIfNotExists(tpi.getFullTopicName()); |
|
||||
topics.add(tpi); |
|
||||
} |
|
||||
} |
|
||||
@ -1,111 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.rabbitmq; |
|
||||
|
|
||||
import jakarta.annotation.PostConstruct; |
|
||||
import lombok.Getter; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.StringUtils; |
|
||||
|
|
||||
import java.util.HashMap; |
|
||||
import java.util.Map; |
|
||||
import java.util.regex.Pattern; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq'") |
|
||||
public class TbRabbitMqQueueArguments { |
|
||||
@Value("${queue.rabbitmq.queue-properties.core:}") |
|
||||
private String coreProperties; |
|
||||
@Value("${queue.rabbitmq.queue-properties.rule-engine:}") |
|
||||
private String ruleEngineProperties; |
|
||||
@Value("${queue.rabbitmq.queue-properties.transport-api:}") |
|
||||
private String transportApiProperties; |
|
||||
@Value("${queue.rabbitmq.queue-properties.notifications:}") |
|
||||
private String notificationsProperties; |
|
||||
@Value("${queue.rabbitmq.queue-properties.js-executor:}") |
|
||||
private String jsExecutorProperties; |
|
||||
@Value("${queue.rabbitmq.queue-properties.version-control:}") |
|
||||
private String vcProperties; |
|
||||
@Value("${queue.rabbitmq.queue-properties.edge:}") |
|
||||
private String edgeProperties; |
|
||||
|
|
||||
@Getter |
|
||||
private Map<String, Object> coreArgs; |
|
||||
@Getter |
|
||||
private Map<String, Object> ruleEngineArgs; |
|
||||
@Getter |
|
||||
private Map<String, Object> transportApiArgs; |
|
||||
@Getter |
|
||||
private Map<String, Object> notificationsArgs; |
|
||||
@Getter |
|
||||
private Map<String, Object> jsExecutorArgs; |
|
||||
@Getter |
|
||||
private Map<String, Object> vcArgs; |
|
||||
@Getter |
|
||||
private Map<String, Object> edgeArgs; |
|
||||
|
|
||||
@PostConstruct |
|
||||
private void init() { |
|
||||
coreArgs = getArgs(coreProperties); |
|
||||
ruleEngineArgs = getArgs(ruleEngineProperties); |
|
||||
transportApiArgs = getArgs(transportApiProperties); |
|
||||
notificationsArgs = getArgs(notificationsProperties); |
|
||||
jsExecutorArgs = getArgs(jsExecutorProperties); |
|
||||
vcArgs = getArgs(vcProperties); |
|
||||
edgeArgs = getArgs(edgeProperties); |
|
||||
} |
|
||||
|
|
||||
public static Map<String, Object> getArgs(String properties) { |
|
||||
Map<String, Object> configs = new HashMap<>(); |
|
||||
if (StringUtils.isNotEmpty(properties)) { |
|
||||
for (String property : properties.split(";")) { |
|
||||
int delimiterPosition = property.indexOf(":"); |
|
||||
String key = property.substring(0, delimiterPosition); |
|
||||
String strValue = property.substring(delimiterPosition + 1); |
|
||||
configs.put(key, getObjectValue(strValue)); |
|
||||
} |
|
||||
} |
|
||||
return configs; |
|
||||
} |
|
||||
|
|
||||
private static Object getObjectValue(String str) { |
|
||||
if (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false")) { |
|
||||
return Boolean.valueOf(str); |
|
||||
} else if (isNumeric(str)) { |
|
||||
return getNumericValue(str); |
|
||||
} |
|
||||
return str; |
|
||||
} |
|
||||
|
|
||||
private static Object getNumericValue(String str) { |
|
||||
if (str.contains(".")) { |
|
||||
return Double.valueOf(str); |
|
||||
} else { |
|
||||
return Long.valueOf(str); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static final Pattern PATTERN = Pattern.compile("-?\\d+(\\.\\d+)?"); |
|
||||
|
|
||||
private static boolean isNumeric(String strNum) { |
|
||||
if (strNum == null) { |
|
||||
return false; |
|
||||
} |
|
||||
return PATTERN.matcher(strNum).matches(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,66 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.rabbitmq; |
|
||||
|
|
||||
import com.rabbitmq.client.ConnectionFactory; |
|
||||
import jakarta.annotation.PostConstruct; |
|
||||
import lombok.Data; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
@Slf4j |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq'") |
|
||||
@Component |
|
||||
@Data |
|
||||
public class TbRabbitMqSettings { |
|
||||
@Value("${queue.rabbitmq.exchange_name:}") |
|
||||
private String exchangeName; |
|
||||
@Value("${queue.rabbitmq.host:}") |
|
||||
private String host; |
|
||||
@Value("${queue.rabbitmq.port:}") |
|
||||
private int port; |
|
||||
@Value("${queue.rabbitmq.virtual_host:}") |
|
||||
private String virtualHost; |
|
||||
@Value("${queue.rabbitmq.username:}") |
|
||||
private String username; |
|
||||
@Value("${queue.rabbitmq.password:}") |
|
||||
private String password; |
|
||||
@Value("${queue.rabbitmq.automatic_recovery_enabled:}") |
|
||||
private boolean automaticRecoveryEnabled; |
|
||||
@Value("${queue.rabbitmq.connection_timeout:}") |
|
||||
private int connectionTimeout; |
|
||||
@Value("${queue.rabbitmq.handshake_timeout:}") |
|
||||
private int handshakeTimeout; |
|
||||
@Value("${queue.rabbitmq.max_poll_messages:1}") |
|
||||
private int maxPollMessages; |
|
||||
|
|
||||
private ConnectionFactory connectionFactory; |
|
||||
|
|
||||
@PostConstruct |
|
||||
private void init() { |
|
||||
connectionFactory = new ConnectionFactory(); |
|
||||
connectionFactory.setHost(host); |
|
||||
connectionFactory.setPort(port); |
|
||||
connectionFactory.setVirtualHost(virtualHost); |
|
||||
connectionFactory.setUsername(username); |
|
||||
connectionFactory.setPassword(password); |
|
||||
connectionFactory.setAutomaticRecoveryEnabled(automaticRecoveryEnabled); |
|
||||
connectionFactory.setConnectionTimeout(connectionTimeout); |
|
||||
connectionFactory.setHandshakeTimeout(handshakeTimeout); |
|
||||
} |
|
||||
} |
|
||||
@ -1,28 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.sqs; |
|
||||
|
|
||||
import com.amazonaws.http.SdkHttpMetadata; |
|
||||
import lombok.AllArgsConstructor; |
|
||||
import lombok.Data; |
|
||||
import org.thingsboard.server.queue.TbQueueMsgMetadata; |
|
||||
|
|
||||
@Data |
|
||||
@AllArgsConstructor |
|
||||
public class AwsSqsTbQueueMsgMetadata implements TbQueueMsgMetadata { |
|
||||
|
|
||||
private final SdkHttpMetadata metadata; |
|
||||
} |
|
||||
@ -1,118 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.sqs; |
|
||||
|
|
||||
import com.amazonaws.auth.AWSCredentials; |
|
||||
import com.amazonaws.auth.AWSCredentialsProvider; |
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider; |
|
||||
import com.amazonaws.auth.BasicAWSCredentials; |
|
||||
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; |
|
||||
import com.amazonaws.services.sqs.AmazonSQS; |
|
||||
import com.amazonaws.services.sqs.AmazonSQSClientBuilder; |
|
||||
import com.amazonaws.services.sqs.model.CreateQueueRequest; |
|
||||
import com.amazonaws.services.sqs.model.GetQueueUrlResult; |
|
||||
import lombok.Getter; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.thingsboard.common.util.ThingsBoardExecutors; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.util.PropertyUtils; |
|
||||
|
|
||||
import java.util.Map; |
|
||||
import java.util.concurrent.ExecutorService; |
|
||||
import java.util.function.Function; |
|
||||
import java.util.stream.Collectors; |
|
||||
|
|
||||
@Slf4j |
|
||||
@Deprecated(forRemoval = true, since = "3.9") // for removal in 4.0
|
|
||||
public class TbAwsSqsAdmin implements TbQueueAdmin { |
|
||||
|
|
||||
private final Map<String, String> attributes; |
|
||||
private final AmazonSQS sqsClient; |
|
||||
private final Map<String, String> queues; |
|
||||
@Getter |
|
||||
private final ExecutorService producerExecutor; |
|
||||
|
|
||||
public TbAwsSqsAdmin(TbAwsSqsSettings sqsSettings, Map<String, String> attributes) { |
|
||||
this.attributes = attributes; |
|
||||
|
|
||||
AWSCredentialsProvider credentialsProvider; |
|
||||
if (sqsSettings.getUseDefaultCredentialProviderChain()) { |
|
||||
credentialsProvider = new DefaultAWSCredentialsProviderChain(); |
|
||||
} else { |
|
||||
AWSCredentials awsCredentials = new BasicAWSCredentials(sqsSettings.getAccessKeyId(), sqsSettings.getSecretAccessKey()); |
|
||||
credentialsProvider = new AWSStaticCredentialsProvider(awsCredentials); |
|
||||
} |
|
||||
producerExecutor = ThingsBoardExecutors.newWorkStealingPool(sqsSettings.getThreadPoolSize(), "aws-sqs-queue-executor"); |
|
||||
|
|
||||
sqsClient = AmazonSQSClientBuilder.standard() |
|
||||
.withCredentials(credentialsProvider) |
|
||||
.withRegion(sqsSettings.getRegion()) |
|
||||
.build(); |
|
||||
|
|
||||
queues = sqsClient |
|
||||
.listQueues() |
|
||||
.getQueueUrls() |
|
||||
.stream() |
|
||||
.map(this::getQueueNameFromUrl) |
|
||||
.collect(Collectors.toMap(this::convertTopicToQueueName, Function.identity())); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void createTopicIfNotExists(String topic, String properties) { |
|
||||
String queueName = convertTopicToQueueName(topic); |
|
||||
if (queues.containsKey(queueName)) { |
|
||||
return; |
|
||||
} |
|
||||
Map<String, String> attributes = PropertyUtils.getProps(this.attributes, properties, TbAwsSqsQueueAttributes::toConfigs); |
|
||||
final CreateQueueRequest createQueueRequest = new CreateQueueRequest(queueName).withAttributes(attributes); |
|
||||
String queueUrl = sqsClient.createQueue(createQueueRequest).getQueueUrl(); |
|
||||
queues.put(getQueueNameFromUrl(queueUrl), queueUrl); |
|
||||
} |
|
||||
|
|
||||
private String convertTopicToQueueName(String topic) { |
|
||||
return topic.replaceAll("\\.", "_") + ".fifo"; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void deleteTopic(String topic) { |
|
||||
String queueName = convertTopicToQueueName(topic); |
|
||||
if (queues.containsKey(queueName)) { |
|
||||
sqsClient.deleteQueue(queues.get(queueName)); |
|
||||
} else { |
|
||||
GetQueueUrlResult queueUrl = sqsClient.getQueueUrl(queueName); |
|
||||
if (queueUrl != null) { |
|
||||
sqsClient.deleteQueue(queueUrl.getQueueUrl()); |
|
||||
} else { |
|
||||
log.warn("Aws SQS queue [{}] does not exist!", queueName); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private String getQueueNameFromUrl(String queueUrl) { |
|
||||
int delimiterIndex = queueUrl.lastIndexOf("/"); |
|
||||
return queueUrl.substring(delimiterIndex + 1); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void destroy() { |
|
||||
if (sqsClient != null) { |
|
||||
sqsClient.shutdown(); |
|
||||
} |
|
||||
if (producerExecutor != null) { |
|
||||
producerExecutor.shutdownNow(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,188 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.sqs; |
|
||||
|
|
||||
import com.amazonaws.auth.AWSCredentials; |
|
||||
import com.amazonaws.auth.AWSCredentialsProvider; |
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider; |
|
||||
import com.amazonaws.auth.BasicAWSCredentials; |
|
||||
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; |
|
||||
import com.amazonaws.services.sqs.AmazonSQS; |
|
||||
import com.amazonaws.services.sqs.AmazonSQSClientBuilder; |
|
||||
import com.amazonaws.services.sqs.model.DeleteMessageBatchRequestEntry; |
|
||||
import com.amazonaws.services.sqs.model.Message; |
|
||||
import com.amazonaws.services.sqs.model.ReceiveMessageRequest; |
|
||||
import com.google.common.util.concurrent.Futures; |
|
||||
import com.google.common.util.concurrent.ListenableFuture; |
|
||||
import com.google.gson.Gson; |
|
||||
import com.google.protobuf.InvalidProtocolBufferException; |
|
||||
import lombok.Data; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.util.CollectionUtils; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueMsgDecoder; |
|
||||
import org.thingsboard.server.queue.common.AbstractParallelTbQueueConsumerTemplate; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|
||||
|
|
||||
import java.util.ArrayList; |
|
||||
import java.util.Collections; |
|
||||
import java.util.List; |
|
||||
import java.util.Objects; |
|
||||
import java.util.Set; |
|
||||
import java.util.concurrent.CopyOnWriteArrayList; |
|
||||
import java.util.concurrent.ExecutionException; |
|
||||
import java.util.concurrent.TimeUnit; |
|
||||
import java.util.stream.Collectors; |
|
||||
import java.util.stream.Stream; |
|
||||
|
|
||||
@Slf4j |
|
||||
public class TbAwsSqsConsumerTemplate<T extends TbQueueMsg> extends AbstractParallelTbQueueConsumerTemplate<Message, T> { |
|
||||
|
|
||||
private static final int MAX_NUM_MSGS = 10; |
|
||||
|
|
||||
private final Gson gson = new Gson(); |
|
||||
private final TbQueueAdmin admin; |
|
||||
private final AmazonSQS sqsClient; |
|
||||
private final TbQueueMsgDecoder<T> decoder; |
|
||||
private final TbAwsSqsSettings sqsSettings; |
|
||||
|
|
||||
private final List<AwsSqsMsgWrapper> pendingMessages = new CopyOnWriteArrayList<>(); |
|
||||
private volatile Set<String> queueUrls; |
|
||||
|
|
||||
public TbAwsSqsConsumerTemplate(TbQueueAdmin admin, TbAwsSqsSettings sqsSettings, String topic, TbQueueMsgDecoder<T> decoder) { |
|
||||
super(topic); |
|
||||
this.admin = admin; |
|
||||
this.decoder = decoder; |
|
||||
this.sqsSettings = sqsSettings; |
|
||||
|
|
||||
AWSCredentialsProvider credentialsProvider; |
|
||||
if (sqsSettings.getUseDefaultCredentialProviderChain()) { |
|
||||
credentialsProvider = new DefaultAWSCredentialsProviderChain(); |
|
||||
} else { |
|
||||
AWSCredentials awsCredentials = new BasicAWSCredentials(sqsSettings.getAccessKeyId(), sqsSettings.getSecretAccessKey()); |
|
||||
credentialsProvider = new AWSStaticCredentialsProvider(awsCredentials); |
|
||||
} |
|
||||
|
|
||||
sqsClient = AmazonSQSClientBuilder.standard() |
|
||||
.withCredentials(credentialsProvider) |
|
||||
.withRegion(sqsSettings.getRegion()) |
|
||||
.build(); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doSubscribe(List<String> topicNames) { |
|
||||
queueUrls = topicNames.stream().map(this::getQueueUrl).collect(Collectors.toSet()); |
|
||||
initNewExecutor(queueUrls.size() * sqsSettings.getThreadsPerTopic() + 1); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected List<Message> doPoll(long durationInMillis) { |
|
||||
int duration = (int) TimeUnit.MILLISECONDS.toSeconds(durationInMillis); |
|
||||
List<ListenableFuture<List<Message>>> futureList = queueUrls |
|
||||
.stream() |
|
||||
.map(url -> poll(url, duration)) |
|
||||
.collect(Collectors.toList()); |
|
||||
ListenableFuture<List<List<Message>>> futureResult = Futures.allAsList(futureList); |
|
||||
try { |
|
||||
return futureResult.get().stream() |
|
||||
.flatMap(List::stream) |
|
||||
.filter(Objects::nonNull) |
|
||||
.collect(Collectors.toList()); |
|
||||
} catch (InterruptedException | ExecutionException e) { |
|
||||
if (stopped) { |
|
||||
log.info("[{}] Aws SQS consumer is stopped.", getTopic()); |
|
||||
} else { |
|
||||
log.error("Failed to pool messages.", e); |
|
||||
} |
|
||||
return Collections.emptyList(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public T decode(Message message) throws InvalidProtocolBufferException { |
|
||||
DefaultTbQueueMsg msg = gson.fromJson(message.getBody(), DefaultTbQueueMsg.class); |
|
||||
return decoder.decode(msg); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doCommit() { |
|
||||
pendingMessages.forEach(msg -> |
|
||||
consumerExecutor.submit(() -> { |
|
||||
List<DeleteMessageBatchRequestEntry> entries = msg.getMessages() |
|
||||
.stream() |
|
||||
.map(message -> new DeleteMessageBatchRequestEntry(message.getMessageId(), message.getReceiptHandle())) |
|
||||
.collect(Collectors.toList()); |
|
||||
sqsClient.deleteMessageBatch(msg.getUrl(), entries); |
|
||||
})); |
|
||||
pendingMessages.clear(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void doUnsubscribe() { |
|
||||
stopped = true; |
|
||||
if (sqsClient != null) { |
|
||||
sqsClient.shutdown(); |
|
||||
} |
|
||||
shutdownExecutor(); |
|
||||
} |
|
||||
|
|
||||
private ListenableFuture<List<Message>> poll(String url, int waitTimeSeconds) { |
|
||||
List<ListenableFuture<List<Message>>> result = new ArrayList<>(); |
|
||||
|
|
||||
for (int i = 0; i < sqsSettings.getThreadsPerTopic(); i++) { |
|
||||
result.add(consumerExecutor.submit(() -> { |
|
||||
ReceiveMessageRequest request = new ReceiveMessageRequest(); |
|
||||
request |
|
||||
.withWaitTimeSeconds(waitTimeSeconds) |
|
||||
.withQueueUrl(url) |
|
||||
.withMaxNumberOfMessages(MAX_NUM_MSGS); |
|
||||
return sqsClient.receiveMessage(request).getMessages(); |
|
||||
})); |
|
||||
} |
|
||||
return Futures.transform(Futures.allAsList(result), list -> { |
|
||||
if (!CollectionUtils.isEmpty(list)) { |
|
||||
return list.stream() |
|
||||
.flatMap(messageList -> { |
|
||||
if (!messageList.isEmpty()) { |
|
||||
this.pendingMessages.add(new AwsSqsMsgWrapper(url, messageList)); |
|
||||
return messageList.stream(); |
|
||||
} |
|
||||
return Stream.empty(); |
|
||||
}) |
|
||||
.collect(Collectors.toList()); |
|
||||
} |
|
||||
return Collections.emptyList(); |
|
||||
}, consumerExecutor); |
|
||||
} |
|
||||
|
|
||||
@Data |
|
||||
private static class AwsSqsMsgWrapper { |
|
||||
private final String url; |
|
||||
private final List<Message> messages; |
|
||||
|
|
||||
public AwsSqsMsgWrapper(String url, List<Message> messages) { |
|
||||
this.url = url; |
|
||||
this.messages = messages; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private String getQueueUrl(String topic) { |
|
||||
admin.createTopicIfNotExists(topic); |
|
||||
return sqsClient.getQueueUrl(topic.replaceAll("\\.", "_") + ".fifo").getQueueUrl(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,117 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.sqs; |
|
||||
|
|
||||
import com.amazonaws.auth.AWSCredentials; |
|
||||
import com.amazonaws.auth.AWSCredentialsProvider; |
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider; |
|
||||
import com.amazonaws.auth.BasicAWSCredentials; |
|
||||
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; |
|
||||
import com.amazonaws.handlers.AsyncHandler; |
|
||||
import com.amazonaws.services.sqs.AmazonSQSAsync; |
|
||||
import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder; |
|
||||
import com.amazonaws.services.sqs.model.SendMessageRequest; |
|
||||
import com.amazonaws.services.sqs.model.SendMessageResult; |
|
||||
import com.google.gson.Gson; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueCallback; |
|
||||
import org.thingsboard.server.queue.TbQueueMsg; |
|
||||
import org.thingsboard.server.queue.TbQueueProducer; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|
||||
|
|
||||
import java.util.Map; |
|
||||
import java.util.UUID; |
|
||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||
|
|
||||
@Slf4j |
|
||||
public class TbAwsSqsProducerTemplate<T extends TbQueueMsg> implements TbQueueProducer<T> { |
|
||||
private final String defaultTopic; |
|
||||
private final AmazonSQSAsync sqsClient; |
|
||||
private final Gson gson = new Gson(); |
|
||||
private final Map<String, String> queueUrlMap = new ConcurrentHashMap<>(); |
|
||||
private final TbAwsSqsAdmin admin; |
|
||||
|
|
||||
public TbAwsSqsProducerTemplate(TbQueueAdmin admin, TbAwsSqsSettings sqsSettings, String defaultTopic) { |
|
||||
this.admin = (TbAwsSqsAdmin) admin; |
|
||||
this.defaultTopic = defaultTopic; |
|
||||
|
|
||||
AWSCredentialsProvider credentialsProvider; |
|
||||
if (sqsSettings.getUseDefaultCredentialProviderChain()) { |
|
||||
credentialsProvider = new DefaultAWSCredentialsProviderChain(); |
|
||||
} else { |
|
||||
AWSCredentials awsCredentials = new BasicAWSCredentials(sqsSettings.getAccessKeyId(), sqsSettings.getSecretAccessKey()); |
|
||||
credentialsProvider = new AWSStaticCredentialsProvider(awsCredentials); |
|
||||
} |
|
||||
|
|
||||
sqsClient = AmazonSQSAsyncClientBuilder.standard() |
|
||||
.withCredentials(credentialsProvider) |
|
||||
.withRegion(sqsSettings.getRegion()) |
|
||||
.withExecutorFactory(this.admin::getProducerExecutor) |
|
||||
.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void init() { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public String getDefaultTopic() { |
|
||||
return defaultTopic; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) { |
|
||||
SendMessageRequest sendMsgRequest = new SendMessageRequest(); |
|
||||
sendMsgRequest.withQueueUrl(getQueueUrl(tpi.getFullTopicName())); |
|
||||
sendMsgRequest.withMessageBody(gson.toJson(new DefaultTbQueueMsg(msg))); |
|
||||
|
|
||||
String sqsMsgId = UUID.randomUUID().toString(); |
|
||||
sendMsgRequest.withMessageGroupId(sqsMsgId); |
|
||||
sendMsgRequest.withMessageDeduplicationId(sqsMsgId); |
|
||||
|
|
||||
sqsClient.sendMessageAsync(sendMsgRequest, new AsyncHandler<SendMessageRequest, SendMessageResult>() { |
|
||||
@Override public void onError(Exception e) { |
|
||||
if (callback != null) { |
|
||||
callback.onFailure(e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override public void onSuccess(SendMessageRequest request, |
|
||||
SendMessageResult sendMessageResult) { |
|
||||
if (callback != null) { |
|
||||
callback.onSuccess(new AwsSqsTbQueueMsgMetadata(sendMessageResult.getSdkHttpMetadata())); |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void stop() { |
|
||||
if (sqsClient != null) { |
|
||||
sqsClient.shutdown(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private String getQueueUrl(String topic) { |
|
||||
return queueUrlMap.computeIfAbsent(topic, k -> { |
|
||||
admin.createTopicIfNotExists(topic); |
|
||||
return sqsClient.getQueueUrl(topic.replaceAll("\\.", "_") + ".fifo").getQueueUrl(); |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
@ -1,105 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.sqs; |
|
||||
|
|
||||
import com.amazonaws.services.sqs.model.QueueAttributeName; |
|
||||
import jakarta.annotation.PostConstruct; |
|
||||
import lombok.Getter; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
import org.thingsboard.server.common.data.StringUtils; |
|
||||
|
|
||||
import java.util.HashMap; |
|
||||
import java.util.Map; |
|
||||
|
|
||||
@Component |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs'") |
|
||||
public class TbAwsSqsQueueAttributes { |
|
||||
@Value("${queue.aws-sqs.queue-properties.core:}") |
|
||||
private String coreProperties; |
|
||||
@Value("${queue.aws-sqs.queue-properties.rule-engine:}") |
|
||||
private String ruleEngineProperties; |
|
||||
@Value("${queue.aws-sqs.queue-properties.transport-api:}") |
|
||||
private String transportApiProperties; |
|
||||
@Value("${queue.aws-sqs.queue-properties.notifications:}") |
|
||||
private String notificationsProperties; |
|
||||
@Value("${queue.aws-sqs.queue-properties.js-executor:}") |
|
||||
private String jsExecutorProperties; |
|
||||
@Value("${queue.aws-sqs.queue-properties.ota-updates:}") |
|
||||
private String otaProperties; |
|
||||
@Value("${queue.aws-sqs.queue-properties.version-control:}") |
|
||||
private String vcProperties; |
|
||||
@Value("${queue.aws-sqs.queue-properties.edge:}") |
|
||||
private String edgeProperties; |
|
||||
|
|
||||
@Getter |
|
||||
private Map<String, String> coreAttributes; |
|
||||
@Getter |
|
||||
private Map<String, String> ruleEngineAttributes; |
|
||||
@Getter |
|
||||
private Map<String, String> transportApiAttributes; |
|
||||
@Getter |
|
||||
private Map<String, String> notificationsAttributes; |
|
||||
@Getter |
|
||||
private Map<String, String> jsExecutorAttributes; |
|
||||
@Getter |
|
||||
private Map<String, String> otaAttributes; |
|
||||
@Getter |
|
||||
private Map<String, String> vcAttributes; |
|
||||
@Getter |
|
||||
private Map<String, String> edgeAttributes; |
|
||||
|
|
||||
private final Map<String, String> defaultAttributes = new HashMap<>(); |
|
||||
|
|
||||
@PostConstruct |
|
||||
private void init() { |
|
||||
defaultAttributes.put(QueueAttributeName.FifoQueue.toString(), "true"); |
|
||||
|
|
||||
coreAttributes = getConfigs(coreProperties); |
|
||||
ruleEngineAttributes = getConfigs(ruleEngineProperties); |
|
||||
transportApiAttributes = getConfigs(transportApiProperties); |
|
||||
notificationsAttributes = getConfigs(notificationsProperties); |
|
||||
jsExecutorAttributes = getConfigs(jsExecutorProperties); |
|
||||
otaAttributes = getConfigs(otaProperties); |
|
||||
vcAttributes = getConfigs(vcProperties); |
|
||||
edgeAttributes = getConfigs(edgeProperties); |
|
||||
} |
|
||||
|
|
||||
private Map<String, String> getConfigs(String properties) { |
|
||||
Map<String, String> configs = new HashMap<>(defaultAttributes); |
|
||||
configs.putAll(toConfigs(properties)); |
|
||||
return configs; |
|
||||
} |
|
||||
|
|
||||
public static Map<String, String> toConfigs(String properties) { |
|
||||
Map<String, String> configs = new HashMap<>(); |
|
||||
if (StringUtils.isNotEmpty(properties)) { |
|
||||
for (String property : properties.split(";")) { |
|
||||
int delimiterPosition = property.indexOf(":"); |
|
||||
String key = property.substring(0, delimiterPosition); |
|
||||
String value = property.substring(delimiterPosition + 1); |
|
||||
validateAttributeName(key); |
|
||||
configs.put(key, value); |
|
||||
} |
|
||||
} |
|
||||
return configs; |
|
||||
} |
|
||||
|
|
||||
private static void validateAttributeName(String key) { |
|
||||
QueueAttributeName.fromValue(key); |
|
||||
} |
|
||||
} |
|
||||
@ -1,48 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.sqs; |
|
||||
|
|
||||
import lombok.Data; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
@Slf4j |
|
||||
@ConditionalOnExpression("'${queue.type:null}'=='aws-sqs'") |
|
||||
@Component |
|
||||
@Data |
|
||||
public class TbAwsSqsSettings { |
|
||||
|
|
||||
@Value("${queue.aws_sqs.use_default_credential_provider_chain}") |
|
||||
private Boolean useDefaultCredentialProviderChain; |
|
||||
|
|
||||
@Value("${queue.aws_sqs.access_key_id}") |
|
||||
private String accessKeyId; |
|
||||
|
|
||||
@Value("${queue.aws_sqs.secret_access_key}") |
|
||||
private String secretAccessKey; |
|
||||
|
|
||||
@Value("${queue.aws_sqs.region}") |
|
||||
private String region; |
|
||||
|
|
||||
@Value("${queue.aws_sqs.threads_per_topic}") |
|
||||
private int threadsPerTopic; |
|
||||
|
|
||||
@Value("${queue.aws_sqs.producer_thread_pool_size:50}") |
|
||||
private int threadPoolSize; |
|
||||
|
|
||||
} |
|
||||
@ -1,128 +0,0 @@ |
|||||
/** |
|
||||
* Copyright © 2016-2024 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.rabbitmq; |
|
||||
|
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean; |
|
||||
import static org.mockito.ArgumentMatchers.anyString; |
|
||||
import static org.mockito.Mockito.times; |
|
||||
import static org.mockito.Mockito.verify; |
|
||||
import static org.mockito.Mockito.when; |
|
||||
|
|
||||
import com.rabbitmq.client.Channel; |
|
||||
import com.rabbitmq.client.Connection; |
|
||||
import com.rabbitmq.client.ConnectionFactory; |
|
||||
import com.rabbitmq.client.GetResponse; |
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
import java.util.Set; |
|
||||
import java.util.UUID; |
|
||||
import org.junit.jupiter.api.Test; |
|
||||
import org.junit.jupiter.api.extension.ExtendWith; |
|
||||
import org.mockito.Mock; |
|
||||
import org.mockito.junit.jupiter.MockitoExtension; |
|
||||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
|
||||
import org.thingsboard.server.queue.TbQueueAdmin; |
|
||||
import org.thingsboard.server.queue.TbQueueMsgDecoder; |
|
||||
import org.thingsboard.server.queue.common.DefaultTbQueueMsg; |
|
||||
|
|
||||
@ExtendWith(MockitoExtension.class) |
|
||||
class TbRabbitMqConsumerTemplateTest { |
|
||||
|
|
||||
private static final String TOPIC = "some-topic"; |
|
||||
|
|
||||
@Mock |
|
||||
private TbQueueAdmin admin; |
|
||||
|
|
||||
@Mock |
|
||||
private ConnectionFactory connectionFactory; |
|
||||
|
|
||||
@Mock |
|
||||
private TbQueueMsgDecoder<DefaultTbQueueMsg> decoder; |
|
||||
|
|
||||
@Mock |
|
||||
private Connection connection; |
|
||||
|
|
||||
@Mock |
|
||||
private Channel channel; |
|
||||
|
|
||||
@Mock |
|
||||
private TopicPartitionInfo partition; |
|
||||
|
|
||||
@Mock |
|
||||
private GetResponse getResponse; |
|
||||
|
|
||||
private TbRabbitMqConsumerTemplate<DefaultTbQueueMsg> consumer; |
|
||||
|
|
||||
private void setUpConsumerWithMaxPollMessages(int maxPollMessages) throws Exception { |
|
||||
when(connectionFactory.newConnection()).thenReturn(connection); |
|
||||
when(connection.createChannel()).thenReturn(channel); |
|
||||
TbRabbitMqSettings settings = new TbRabbitMqSettings(); |
|
||||
settings.setMaxPollMessages(maxPollMessages); |
|
||||
settings.setConnectionFactory(connectionFactory); |
|
||||
|
|
||||
consumer = new TbRabbitMqConsumerTemplate<>(admin, settings, TOPIC, decoder); |
|
||||
when(partition.getFullTopicName()).thenReturn(TOPIC); |
|
||||
consumer.subscribe(Set.of(partition)); |
|
||||
} |
|
||||
|
|
||||
@Test |
|
||||
void pollWithMax5PollMessagesReturnsEmptyListIfNoMessages() throws Exception { |
|
||||
setUpConsumerWithMaxPollMessages(5); |
|
||||
when(channel.basicGet(anyString(), anyBoolean())).thenReturn(null); |
|
||||
|
|
||||
assertThat(consumer.poll(0L)).isEmpty(); |
|
||||
|
|
||||
verify(channel).basicGet(anyString(), anyBoolean()); |
|
||||
} |
|
||||
|
|
||||
@Test |
|
||||
void pollWithMax5PollMessagesReturns5MessagesIfQueueContains5() throws Exception { |
|
||||
setUpConsumerWithMaxPollMessages(5); |
|
||||
when(getResponse.getBody()).thenReturn(newMessageBody()); |
|
||||
when(channel.basicGet(anyString(), anyBoolean())).thenReturn(getResponse); |
|
||||
|
|
||||
assertThat(consumer.poll(0L)).hasSize(5); |
|
||||
|
|
||||
verify(channel, times(5)).basicGet(anyString(), anyBoolean()); |
|
||||
} |
|
||||
|
|
||||
@Test |
|
||||
void pollWithMax1PollMessageReturns1MessageIfQueueContainsMore() throws Exception { |
|
||||
setUpConsumerWithMaxPollMessages(1); |
|
||||
when(getResponse.getBody()).thenReturn(newMessageBody()); |
|
||||
when(channel.basicGet(anyString(), anyBoolean())).thenReturn(getResponse); |
|
||||
|
|
||||
assertThat(consumer.poll(0L)).hasSize(1); |
|
||||
|
|
||||
verify(channel).basicGet(anyString(), anyBoolean()); |
|
||||
} |
|
||||
|
|
||||
@Test |
|
||||
void pollWithMax3PollMessagesReturns2MessagesIfQueueContains2() throws Exception { |
|
||||
setUpConsumerWithMaxPollMessages(3); |
|
||||
when(getResponse.getBody()).thenReturn(newMessageBody()); |
|
||||
when(channel.basicGet(anyString(), anyBoolean())).thenReturn(getResponse, getResponse, null); |
|
||||
|
|
||||
assertThat(consumer.poll(0L)).hasSize(2); |
|
||||
|
|
||||
verify(channel, times(3)).basicGet(anyString(), anyBoolean()); |
|
||||
} |
|
||||
|
|
||||
private byte[] newMessageBody() { |
|
||||
return ("{\"key\": \"" + UUID.randomUUID() + "\"}").getBytes(StandardCharsets.UTF_8); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,198 +0,0 @@ |
|||||
///
|
|
||||
/// Copyright © 2016-2024 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.
|
|
||||
///
|
|
||||
|
|
||||
import config from 'config'; |
|
||||
import { _logger } from '../config/logger'; |
|
||||
import { JsInvokeMessageProcessor } from '../api/jsInvokeMessageProcessor' |
|
||||
import { IQueue } from './queue.models'; |
|
||||
import { |
|
||||
CreateQueueCommand, |
|
||||
CreateQueueRequest, |
|
||||
DeleteMessageBatchCommand, |
|
||||
DeleteMessageBatchRequest, |
|
||||
DeleteMessageBatchRequestEntry, |
|
||||
ListQueuesCommand, |
|
||||
ListQueuesResult, |
|
||||
ReceiveMessageCommand, |
|
||||
ReceiveMessageRequest, |
|
||||
ReceiveMessageResult, |
|
||||
SendMessageCommand, |
|
||||
SendMessageRequest, |
|
||||
SQSClient |
|
||||
} from '@aws-sdk/client-sqs'; |
|
||||
import uuid from 'uuid-random'; |
|
||||
|
|
||||
export class AwsSqsTemplate implements IQueue { |
|
||||
|
|
||||
private logger = _logger(`awsSqsTemplate`); |
|
||||
private queuePrefix: string = config.get('queue_prefix'); |
|
||||
private requestTopic: string = this.queuePrefix ? this.queuePrefix + "." + config.get('request_topic') : config.get('request_topic'); |
|
||||
private accessKeyId: string = config.get('aws_sqs.access_key_id'); |
|
||||
private secretAccessKey: string = config.get('aws_sqs.secret_access_key'); |
|
||||
private region: string = config.get('aws_sqs.region'); |
|
||||
private queueProperties: string = config.get('aws_sqs.queue_properties'); |
|
||||
private pollInterval = Number(config.get('js.response_poll_interval')); |
|
||||
|
|
||||
private sqsClient: SQSClient; |
|
||||
private requestQueueURL: string |
|
||||
private queueUrls = new Map<string, string>(); |
|
||||
private queueAttributes: { [n: string]: string } = { |
|
||||
FifoQueue: 'true' |
|
||||
}; |
|
||||
private timer: NodeJS.Timeout; |
|
||||
|
|
||||
name = 'AWS SQS'; |
|
||||
|
|
||||
constructor() { |
|
||||
} |
|
||||
|
|
||||
async init() { |
|
||||
this.sqsClient = new SQSClient({ |
|
||||
apiVersion: '2012-11-05', |
|
||||
credentials: { |
|
||||
accessKeyId: this.accessKeyId, |
|
||||
secretAccessKey: this.secretAccessKey |
|
||||
}, |
|
||||
region: this.region |
|
||||
}); |
|
||||
|
|
||||
const queues = await this.getQueues(); |
|
||||
|
|
||||
if (queues.QueueUrls) { |
|
||||
queues.QueueUrls.forEach(queueUrl => { |
|
||||
const delimiterPosition = queueUrl.lastIndexOf('/'); |
|
||||
const queueName = queueUrl.substring(delimiterPosition + 1); |
|
||||
this.queueUrls.set(queueName, queueUrl); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
this.parseQueueProperties(); |
|
||||
|
|
||||
this.requestQueueURL = this.queueUrls.get(AwsSqsTemplate.topicToSqsQueueName(this.requestTopic)) || ''; |
|
||||
if (!this.requestQueueURL) { |
|
||||
this.requestQueueURL = await this.createQueue(this.requestTopic); |
|
||||
} |
|
||||
|
|
||||
const messageProcessor = new JsInvokeMessageProcessor(this); |
|
||||
|
|
||||
const params: ReceiveMessageRequest = { |
|
||||
MaxNumberOfMessages: 10, |
|
||||
QueueUrl: this.requestQueueURL, |
|
||||
WaitTimeSeconds: Math.ceil(this.pollInterval / 10) |
|
||||
}; |
|
||||
this.timer = setTimeout(() => {this.getAndProcessMessage(messageProcessor, params)}, this.pollInterval); |
|
||||
} |
|
||||
|
|
||||
private async getAndProcessMessage(messageProcessor: JsInvokeMessageProcessor, params: ReceiveMessageRequest) { |
|
||||
const messagesResponse: ReceiveMessageResult = await this.sqsClient.send(new ReceiveMessageCommand(params)); |
|
||||
const messages = messagesResponse.Messages; |
|
||||
|
|
||||
if (messages && messages.length > 0) { |
|
||||
const entries: DeleteMessageBatchRequestEntry[] = []; |
|
||||
|
|
||||
messages.forEach(message => { |
|
||||
entries.push({ |
|
||||
Id: message.MessageId, |
|
||||
ReceiptHandle: message.ReceiptHandle |
|
||||
}); |
|
||||
messageProcessor.onJsInvokeMessage(JSON.parse(message.Body || '')); |
|
||||
}); |
|
||||
|
|
||||
const deleteBatch: DeleteMessageBatchRequest = { |
|
||||
QueueUrl: this.requestQueueURL, |
|
||||
Entries: entries |
|
||||
}; |
|
||||
try { |
|
||||
await this.sqsClient.send(new DeleteMessageBatchCommand(deleteBatch)) |
|
||||
} catch (err: any) { |
|
||||
this.logger.error("Failed to delete messages from queue.", err.message); |
|
||||
} |
|
||||
} |
|
||||
this.timer = setTimeout(() => {this.getAndProcessMessage(messageProcessor, params)}, this.pollInterval); |
|
||||
} |
|
||||
|
|
||||
async send(responseTopic: string, msgKey: string, rawResponse: Buffer, headers: any): Promise<any> { |
|
||||
let msgBody = JSON.stringify( |
|
||||
{ |
|
||||
key: msgKey, |
|
||||
data: [...rawResponse], |
|
||||
headers: headers |
|
||||
}); |
|
||||
|
|
||||
let responseQueueUrl = this.queueUrls.get(AwsSqsTemplate.topicToSqsQueueName(responseTopic)); |
|
||||
|
|
||||
if (!responseQueueUrl) { |
|
||||
responseQueueUrl = await this.createQueue(responseTopic); |
|
||||
this.queueUrls.set(responseTopic, responseQueueUrl); |
|
||||
} |
|
||||
|
|
||||
let msgId = uuid(); |
|
||||
|
|
||||
let params: SendMessageRequest = { |
|
||||
MessageBody: msgBody, |
|
||||
QueueUrl: responseQueueUrl, |
|
||||
MessageGroupId: msgId, |
|
||||
MessageDeduplicationId: msgId |
|
||||
}; |
|
||||
|
|
||||
return this.sqsClient.send(new SendMessageCommand(params)) |
|
||||
} |
|
||||
|
|
||||
private async getQueues(): Promise<ListQueuesResult> { |
|
||||
return this.sqsClient.send(new ListQueuesCommand({})); |
|
||||
} |
|
||||
|
|
||||
private parseQueueProperties() { |
|
||||
const props = this.queueProperties.split(';'); |
|
||||
props.forEach(p => { |
|
||||
const delimiterPosition = p.indexOf(':'); |
|
||||
this.queueAttributes[p.substring(0, delimiterPosition)] = p.substring(delimiterPosition + 1); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
private static topicToSqsQueueName(topic: string): string { |
|
||||
return topic.replace(/\./g, '_') + '.fifo'; |
|
||||
} |
|
||||
|
|
||||
private async createQueue(topic: string): Promise<string> { |
|
||||
let queueName = AwsSqsTemplate.topicToSqsQueueName(topic); |
|
||||
let queueParams: CreateQueueRequest = { |
|
||||
QueueName: queueName, |
|
||||
Attributes: this.queueAttributes |
|
||||
}; |
|
||||
|
|
||||
const result = await this.sqsClient.send(new CreateQueueCommand(queueParams)); |
|
||||
return result.QueueUrl || ''; |
|
||||
} |
|
||||
|
|
||||
async destroy(): Promise<void> { |
|
||||
this.logger.info('Stopping AWS SQS resources...'); |
|
||||
clearTimeout(this.timer); |
|
||||
if (this.sqsClient) { |
|
||||
this.logger.info('Stopping AWS SQS client...'); |
|
||||
try { |
|
||||
const _sqsClient = this.sqsClient; |
|
||||
// @ts-ignore
|
|
||||
delete this.sqsClient; |
|
||||
_sqsClient.destroy(); |
|
||||
this.logger.info('AWS SQS client stopped.'); |
|
||||
} catch (e: any) { |
|
||||
this.logger.info('AWS SQS client stop error.'); |
|
||||
} |
|
||||
} |
|
||||
this.logger.info('AWS SQS resources stopped.') |
|
||||
} |
|
||||
} |
|
||||
@ -1,162 +0,0 @@ |
|||||
///
|
|
||||
/// Copyright © 2016-2024 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.
|
|
||||
///
|
|
||||
|
|
||||
import config from 'config'; |
|
||||
import { _logger } from '../config/logger'; |
|
||||
import { JsInvokeMessageProcessor } from '../api/jsInvokeMessageProcessor' |
|
||||
import { PubSub } from '@google-cloud/pubsub'; |
|
||||
import { IQueue } from './queue.models'; |
|
||||
import { Message } from '@google-cloud/pubsub/build/src/subscriber'; |
|
||||
|
|
||||
export class PubSubTemplate implements IQueue { |
|
||||
|
|
||||
private logger = _logger(`pubSubTemplate`); |
|
||||
private projectId: string = config.get('pubsub.project_id'); |
|
||||
private credentials = JSON.parse(config.get('pubsub.service_account')); |
|
||||
private queuePrefix: string = config.get('queue_prefix'); |
|
||||
private requestTopic: string = this.queuePrefix ? this.queuePrefix + "." + config.get('request_topic') : config.get('request_topic'); |
|
||||
private queueProperties: string = config.get('pubsub.queue_properties'); |
|
||||
|
|
||||
private pubSubClient: PubSub; |
|
||||
private queueProps: { [n: string]: string } = {}; |
|
||||
private topics: string[] = []; |
|
||||
private subscriptions: string[] = []; |
|
||||
|
|
||||
name = 'Pub/Sub'; |
|
||||
|
|
||||
constructor() { |
|
||||
} |
|
||||
|
|
||||
async init() { |
|
||||
this.pubSubClient = new PubSub({ |
|
||||
projectId: this.projectId, |
|
||||
credentials: this.credentials |
|
||||
}); |
|
||||
|
|
||||
this.parseQueueProperties(); |
|
||||
|
|
||||
const topicList = await this.pubSubClient.getTopics(); |
|
||||
|
|
||||
if (topicList) { |
|
||||
topicList[0].forEach(topic => { |
|
||||
this.topics.push(PubSubTemplate.getName(topic.name)); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
const subscriptionList = await this.pubSubClient.getSubscriptions(); |
|
||||
|
|
||||
if (subscriptionList) { |
|
||||
topicList[0].forEach(sub => { |
|
||||
this.subscriptions.push(PubSubTemplate.getName(sub.name)); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
if (!(this.subscriptions.includes(this.requestTopic) && this.topics.includes(this.requestTopic))) { |
|
||||
await this.createTopic(this.requestTopic); |
|
||||
await this.createSubscription(this.requestTopic); |
|
||||
} |
|
||||
|
|
||||
const subscription = this.pubSubClient.subscription(this.requestTopic); |
|
||||
|
|
||||
const messageProcessor = new JsInvokeMessageProcessor(this); |
|
||||
|
|
||||
const messageHandler = (message: Message) => { |
|
||||
messageProcessor.onJsInvokeMessage(JSON.parse(message.data.toString('utf8'))); |
|
||||
message.ack(); |
|
||||
}; |
|
||||
|
|
||||
subscription.on('message', messageHandler); |
|
||||
} |
|
||||
|
|
||||
async send(responseTopic: string, msgKey: string, rawResponse: Buffer, headers: any): Promise<any> { |
|
||||
if (!(this.subscriptions.includes(responseTopic) && this.topics.includes(this.requestTopic))) { |
|
||||
await this.createTopic(this.requestTopic); |
|
||||
await this.createSubscription(this.requestTopic); |
|
||||
} |
|
||||
|
|
||||
let data = JSON.stringify( |
|
||||
{ |
|
||||
key: msgKey, |
|
||||
data: [...rawResponse], |
|
||||
headers: headers |
|
||||
}); |
|
||||
let dataBuffer = Buffer.from(data); |
|
||||
return this.pubSubClient.topic(responseTopic).publishMessage({data: dataBuffer}); |
|
||||
} |
|
||||
|
|
||||
private parseQueueProperties() { |
|
||||
const props = this.queueProperties.split(';'); |
|
||||
props.forEach(p => { |
|
||||
const delimiterPosition = p.indexOf(':'); |
|
||||
this.queueProps[p.substring(0, delimiterPosition)] = p.substring(delimiterPosition + 1); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
private static getName(fullName: string): string { |
|
||||
const delimiterPosition = fullName.lastIndexOf('/'); |
|
||||
return fullName.substring(delimiterPosition + 1); |
|
||||
} |
|
||||
|
|
||||
private async createTopic(topic: string) { |
|
||||
if (!this.topics.includes(topic)) { |
|
||||
try { |
|
||||
await this.pubSubClient.createTopic(topic); |
|
||||
this.logger.info('Created new Pub/Sub topic: %s', topic); |
|
||||
} catch (e) { |
|
||||
this.logger.info('Pub/Sub topic already exists'); |
|
||||
} |
|
||||
this.topics.push(topic); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private async createSubscription(topic: string) { |
|
||||
if (!this.subscriptions.includes(topic)) { |
|
||||
try { |
|
||||
await this.pubSubClient.createSubscription(topic, topic, { |
|
||||
topic: topic, |
|
||||
name: topic, |
|
||||
ackDeadlineSeconds: Number(this.queueProps['ackDeadlineInSec']), |
|
||||
messageRetentionDuration: { |
|
||||
seconds: this.queueProps['messageRetentionInSec'] |
|
||||
} |
|
||||
}); |
|
||||
this.logger.info('Created new Pub/Sub subscription: %s', topic); |
|
||||
} catch (e) { |
|
||||
this.logger.info('Pub/Sub subscription already exists.'); |
|
||||
} |
|
||||
|
|
||||
this.subscriptions.push(topic); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
async destroy(): Promise<void> { |
|
||||
this.logger.info('Stopping Pub/Sub resources...'); |
|
||||
if (this.pubSubClient) { |
|
||||
this.logger.info('Stopping Pub/Sub client...'); |
|
||||
try { |
|
||||
const _pubSubClient = this.pubSubClient; |
|
||||
// @ts-ignore
|
|
||||
delete this.pubSubClient; |
|
||||
await _pubSubClient.close(); |
|
||||
this.logger.info('Pub/Sub client stopped.'); |
|
||||
} catch (e) { |
|
||||
this.logger.info('Pub/Sub client stop error.'); |
|
||||
} |
|
||||
} |
|
||||
this.logger.info('Pub/Sub resources stopped.'); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@ -1,128 +0,0 @@ |
|||||
///
|
|
||||
/// Copyright © 2016-2024 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.
|
|
||||
///
|
|
||||
|
|
||||
import config from 'config'; |
|
||||
import { _logger } from '../config/logger'; |
|
||||
import { JsInvokeMessageProcessor } from '../api/jsInvokeMessageProcessor' |
|
||||
import { IQueue } from './queue.models'; |
|
||||
import amqp, { ConfirmChannel, Connection } from 'amqplib'; |
|
||||
import { Options, Replies } from 'amqplib/properties'; |
|
||||
|
|
||||
export class RabbitMqTemplate implements IQueue { |
|
||||
|
|
||||
private logger = _logger(`rabbitmqTemplate`); |
|
||||
private queuePrefix: string = config.get('queue_prefix'); |
|
||||
private requestTopic: string = this.queuePrefix ? this.queuePrefix + "." + config.get('request_topic') : config.get('request_topic'); |
|
||||
private host = config.get('rabbitmq.host'); |
|
||||
private port = config.get('rabbitmq.port'); |
|
||||
private vhost = config.get('rabbitmq.virtual_host'); |
|
||||
private username = config.get('rabbitmq.username'); |
|
||||
private password = config.get('rabbitmq.password'); |
|
||||
private queueProperties: string = config.get('rabbitmq.queue_properties'); |
|
||||
|
|
||||
private queueOptions: Options.AssertQueue = { |
|
||||
durable: false, |
|
||||
exclusive: false, |
|
||||
autoDelete: false |
|
||||
}; |
|
||||
private connection: Connection; |
|
||||
private channel: ConfirmChannel; |
|
||||
private topics: string[] = []; |
|
||||
|
|
||||
name = 'RabbitMQ'; |
|
||||
|
|
||||
constructor() { |
|
||||
} |
|
||||
|
|
||||
async init(): Promise<void> { |
|
||||
const url = `amqp://${this.username}:${this.password}@${this.host}:${this.port}${this.vhost}`; |
|
||||
this.connection = await amqp.connect(url); |
|
||||
this.channel = await this.connection.createConfirmChannel(); |
|
||||
|
|
||||
this.parseQueueProperties(); |
|
||||
|
|
||||
await this.createQueue(this.requestTopic); |
|
||||
|
|
||||
const messageProcessor = new JsInvokeMessageProcessor(this); |
|
||||
|
|
||||
await this.channel.consume(this.requestTopic, (message) => { |
|
||||
if (message) { |
|
||||
messageProcessor.onJsInvokeMessage(JSON.parse(message.content.toString('utf8'))); |
|
||||
this.channel.ack(message); |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
async send(responseTopic: string, msgKey: string, rawResponse: Buffer, headers: any): Promise<any> { |
|
||||
|
|
||||
if (!this.topics.includes(responseTopic)) { |
|
||||
await this.createQueue(responseTopic); |
|
||||
this.topics.push(responseTopic); |
|
||||
} |
|
||||
|
|
||||
let data = JSON.stringify( |
|
||||
{ |
|
||||
key: msgKey, |
|
||||
data: [...rawResponse], |
|
||||
headers: headers |
|
||||
}); |
|
||||
let dataBuffer = Buffer.from(data); |
|
||||
this.channel.sendToQueue(responseTopic, dataBuffer); |
|
||||
return this.channel.waitForConfirms() |
|
||||
} |
|
||||
|
|
||||
private parseQueueProperties() { |
|
||||
let args: { [n: string]: number } = {}; |
|
||||
const props = this.queueProperties.split(';'); |
|
||||
props.forEach(p => { |
|
||||
const delimiterPosition = p.indexOf(':'); |
|
||||
args[p.substring(0, delimiterPosition)] = Number(p.substring(delimiterPosition + 1)); |
|
||||
}); |
|
||||
this.queueOptions['arguments'] = args; |
|
||||
} |
|
||||
|
|
||||
private async createQueue(topic: string): Promise<Replies.AssertQueue> { |
|
||||
return this.channel.assertQueue(topic, this.queueOptions); |
|
||||
} |
|
||||
|
|
||||
async destroy() { |
|
||||
this.logger.info('Stopping RabbitMQ resources...'); |
|
||||
|
|
||||
if (this.channel) { |
|
||||
this.logger.info('Stopping RabbitMQ chanel...'); |
|
||||
const _channel = this.channel; |
|
||||
// @ts-ignore
|
|
||||
delete this.channel; |
|
||||
await _channel.close(); |
|
||||
this.logger.info('RabbitMQ chanel stopped'); |
|
||||
} |
|
||||
|
|
||||
if (this.connection) { |
|
||||
this.logger.info('Stopping RabbitMQ connection...') |
|
||||
try { |
|
||||
const _connection = this.connection; |
|
||||
// @ts-ignore
|
|
||||
delete this.connection; |
|
||||
await _connection.close(); |
|
||||
this.logger.info('RabbitMQ client connection.'); |
|
||||
} catch (e) { |
|
||||
this.logger.info('RabbitMQ connection stop error.'); |
|
||||
} |
|
||||
} |
|
||||
this.logger.info('RabbitMQ resources stopped.') |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,175 +0,0 @@ |
|||||
///
|
|
||||
/// Copyright © 2016-2024 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.
|
|
||||
///
|
|
||||
|
|
||||
import config from 'config'; |
|
||||
import { _logger } from '../config/logger'; |
|
||||
import { JsInvokeMessageProcessor } from '../api/jsInvokeMessageProcessor' |
|
||||
import { IQueue } from './queue.models'; |
|
||||
import { |
|
||||
CreateQueueOptions, |
|
||||
ProcessErrorArgs, |
|
||||
ServiceBusAdministrationClient, |
|
||||
ServiceBusClient, |
|
||||
ServiceBusReceivedMessage, |
|
||||
ServiceBusReceiver, |
|
||||
ServiceBusSender |
|
||||
} from '@azure/service-bus'; |
|
||||
|
|
||||
export class ServiceBusTemplate implements IQueue { |
|
||||
|
|
||||
private logger = _logger(`serviceBusTemplate`); |
|
||||
private queuePrefix: string = config.get('queue_prefix'); |
|
||||
private requestTopic: string = this.queuePrefix ? this.queuePrefix + "." + config.get('request_topic') : config.get('request_topic'); |
|
||||
private namespaceName = config.get('service_bus.namespace_name'); |
|
||||
private sasKeyName = config.get('service_bus.sas_key_name'); |
|
||||
private sasKey = config.get('service_bus.sas_key'); |
|
||||
private queueProperties: string = config.get('service_bus.queue_properties'); |
|
||||
|
|
||||
private sbClient: ServiceBusClient; |
|
||||
private serviceBusService: ServiceBusAdministrationClient; |
|
||||
private queueOptions: CreateQueueOptions = {}; |
|
||||
private queues: string[] = []; |
|
||||
private receiver: ServiceBusReceiver; |
|
||||
private senderMap = new Map<string, ServiceBusSender>(); |
|
||||
|
|
||||
name = 'Azure Service Bus'; |
|
||||
|
|
||||
constructor() { |
|
||||
} |
|
||||
|
|
||||
async init() { |
|
||||
const connectionString = `Endpoint=sb://${this.namespaceName}.servicebus.windows.net/;SharedAccessKeyName=${this.sasKeyName};SharedAccessKey=${this.sasKey}`; |
|
||||
this.sbClient = new ServiceBusClient(connectionString) |
|
||||
this.serviceBusService = new ServiceBusAdministrationClient(connectionString); |
|
||||
|
|
||||
this.parseQueueProperties(); |
|
||||
|
|
||||
const listQueues = this.serviceBusService.listQueues(); |
|
||||
for await (const queue of listQueues) { |
|
||||
this.queues.push(queue.name); |
|
||||
} |
|
||||
|
|
||||
if (!this.queues.includes(this.requestTopic)) { |
|
||||
await this.createQueueIfNotExist(this.requestTopic); |
|
||||
this.queues.push(this.requestTopic); |
|
||||
} |
|
||||
|
|
||||
this.receiver = this.sbClient.createReceiver(this.requestTopic, {receiveMode: 'peekLock'}); |
|
||||
|
|
||||
const messageProcessor = new JsInvokeMessageProcessor(this); |
|
||||
|
|
||||
const messageHandler = async (message: ServiceBusReceivedMessage) => { |
|
||||
if (message) { |
|
||||
messageProcessor.onJsInvokeMessage(message.body); |
|
||||
await this.receiver.completeMessage(message); |
|
||||
} |
|
||||
}; |
|
||||
const errorHandler = async (error: ProcessErrorArgs) => { |
|
||||
this.logger.error('Failed to receive message from queue.', error); |
|
||||
}; |
|
||||
this.receiver.subscribe({processMessage: messageHandler, processError: errorHandler}) |
|
||||
} |
|
||||
|
|
||||
async send(responseTopic: string, msgKey: string, rawResponse: Buffer, headers: any): Promise<any> { |
|
||||
if (!this.queues.includes(this.requestTopic)) { |
|
||||
await this.createQueueIfNotExist(this.requestTopic); |
|
||||
this.queues.push(this.requestTopic); |
|
||||
} |
|
||||
|
|
||||
let customSender = this.senderMap.get(responseTopic); |
|
||||
|
|
||||
if (!customSender) { |
|
||||
customSender = this.sbClient.createSender(responseTopic); |
|
||||
this.senderMap.set(responseTopic, customSender); |
|
||||
} |
|
||||
|
|
||||
let data = { |
|
||||
key: msgKey, |
|
||||
data: [...rawResponse], |
|
||||
headers: headers |
|
||||
}; |
|
||||
|
|
||||
return customSender.sendMessages({body: data}); |
|
||||
} |
|
||||
|
|
||||
private parseQueueProperties() { |
|
||||
let properties: { [n: string]: string } = {}; |
|
||||
const props = this.queueProperties.split(';'); |
|
||||
props.forEach(p => { |
|
||||
const delimiterPosition = p.indexOf(':'); |
|
||||
properties[p.substring(0, delimiterPosition)] = p.substring(delimiterPosition + 1); |
|
||||
}); |
|
||||
this.queueOptions = { |
|
||||
requiresDuplicateDetection: false, |
|
||||
maxSizeInMegabytes: Number(properties['maxSizeInMb']), |
|
||||
defaultMessageTimeToLive: `PT${properties['messageTimeToLiveInSec']}S`, |
|
||||
lockDuration: `PT${properties['lockDurationInSec']}S` |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
private async createQueueIfNotExist(topic: string) { |
|
||||
try { |
|
||||
await this.serviceBusService.createQueue(topic, this.queueOptions) |
|
||||
} catch (err: any) { |
|
||||
if (err && err.code !== "MessageEntityAlreadyExistsError") { |
|
||||
throw new Error(err); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
async destroy() { |
|
||||
this.logger.info('Stopping Azure Service Bus resources...') |
|
||||
if (this.receiver) { |
|
||||
this.logger.info('Stopping Service Bus Receiver...'); |
|
||||
try { |
|
||||
const _receiver = this.receiver; |
|
||||
// @ts-ignore
|
|
||||
delete this.receiver; |
|
||||
await _receiver.close(); |
|
||||
this.logger.info('Service Bus Receiver stopped.'); |
|
||||
} catch (e) { |
|
||||
this.logger.info('Service Bus Receiver stop error.'); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
this.logger.info('Stopping Service Bus Senders...'); |
|
||||
const senders: Promise<void>[] = []; |
|
||||
this.senderMap.forEach((sender) => { |
|
||||
senders.push(sender.close()); |
|
||||
}); |
|
||||
this.senderMap.clear(); |
|
||||
try { |
|
||||
await Promise.all(senders); |
|
||||
this.logger.info('Service Bus Senders stopped.'); |
|
||||
} catch (e) { |
|
||||
this.logger.info('Service Bus Senders stop error.'); |
|
||||
} |
|
||||
|
|
||||
if (this.sbClient) { |
|
||||
this.logger.info('Stopping Service Bus Client...'); |
|
||||
try { |
|
||||
const _sbClient = this.sbClient; |
|
||||
// @ts-ignore
|
|
||||
delete this.sbClient; |
|
||||
await _sbClient.close(); |
|
||||
this.logger.info('Service Bus Client stopped.'); |
|
||||
} catch (e) { |
|
||||
this.logger.info('Service Bus Client stop error.'); |
|
||||
} |
|
||||
} |
|
||||
this.logger.info('Azure Service Bus resources stopped.') |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue